Update WebGPU CTS (#32783)

* Update CTS to 20425f60bb

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* expect

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

---------

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
This commit is contained in:
Samson 2024-07-16 19:24:52 +02:00 committed by GitHub
parent 039631cfa5
commit 946af8450c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
1385 changed files with 153348 additions and 13164 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,3 @@
[canvas_complex_rgba8unorm_store.https.html]
expected:
if os == "linux" and not debug: PASS
if os == "linux" and not debug: [PASS, FAIL]

View file

@ -0,0 +1,3 @@
[canvas_display_after_device_lost.https.html]
expected:
if os == "linux" and not debug: TIMEOUT

View file

@ -1 +1 @@
ad066ef01b1060802b4a2329443faead9f345d87
20425f60bb00676af386b5c31e7748c0e2cb1702

View file

@ -17,6 +17,8 @@ export { TestCaseRecorder } from '../internal/logging/test_case_recorder.js';
export class SubcaseBatchState {
constructor(
recorder,
@ -124,8 +126,14 @@ export class Fixture {
if (WEBGL_lose_context) WEBGL_lose_context.loseContext();
} else if ('destroy' in o) {
o.destroy();
} else {
} else if ('destroyAsync' in o) {
await o.destroyAsync();
} else if ('close' in o) {
o.close();
} else {
// HTMLVideoElement
o.src = '';
o.srcObject = null;
}
}
}
@ -133,11 +141,29 @@ export class Fixture {
/**
* 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.)
* Usually when creating buffers/textures/query sets, you can use the helpers in GPUTest instead.
*/
trackForCleanup(o) {
this.objectsToCleanUp.push(o);
if (o instanceof Promise) {
this.eventualAsyncExpectation(() =>
o.then(
(o) => this.trackForCleanup(o),
() => {}
)
);
return o;
}
if (o instanceof GPUDevice) {
this.objectsToCleanUp.push({
async destroyAsync() {
o.destroy();
await o.lost;
}
});
} else {
this.objectsToCleanUp.push(o);
}
return o;
}
@ -156,11 +182,25 @@ export class Fixture {
return o;
}
/** Call requestDevice() and track the device for cleanup. */
requestDeviceTracked(adapter, desc = undefined) {
return this.trackForCleanup(adapter.requestDevice(desc));
}
/** Log a debug message. */
debug(msg) {
this.rec.debug(new Error(msg));
}
/**
* Log an info message.
* **Use sparingly. Use `debug()` instead if logs are only needed with debug logging enabled.**
*/
info(msg) {
this.rec.info(new Error(msg));
}
/** Throws an exception marking the subcase as skipped. */
skip(msg) {
throw new SkipTestCase(msg);

View file

@ -16,6 +16,7 @@
export function loadMetadataForSuite(suiteDir) {
assert(typeof require !== 'undefined', 'loadMetadataForSuite is only implemented on Node');
const fs = require('fs');
const metadataFile = `${suiteDir}/listing_meta.json`;

View file

@ -17,6 +17,21 @@
@ -24,9 +39,12 @@
export const globalTestConfig = {
enableDebugLogs: false,
maxSubcasesInFlight: 500,
testHeartbeatCallback: () => {},
noRaceWithRejectOnTimeout: false,
unrollConstEvalLoops: false,
compatibility: false
compatibility: false,
forceFallbackAdapter: false,
logToWebSocket: false
};

View file

@ -1,19 +1,36 @@
/**
* 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);
/**
* Wrap an Error (which was created to capture the stack at that point) into a
* LogMessageWithStack (which has extra stuff for good log messages).
*
* The original `ex.name` is ignored. Inclued it in the `name` parameter if it
* needs to be preserved.
*/
static wrapError(name, ex) {
return new LogMessageWithStack({
name,
message: ex.message,
stackHiddenMessage: undefined,
stack: ex.stack,
extra: 'extra' in ex ? ex.extra : undefined
});
}
this.name = name;
this.stack = ex.stack;
if ('extra' in ex) {
this.extra = ex.extra;
}
constructor(o) {
super(o.message);
this.name = o.name;
this.stackHiddenMessage = o.stackHiddenMessage;
this.stack = o.stack;
this.extra = o.extra;
}
/** Set a flag so the stack is not printed in toJSON(). */
@ -21,6 +38,11 @@ export class LogMessageWithStack extends Error {
this.stackHiddenMessage ??= stackHiddenMessage;
}
/**
* Print the message for display.
*
* Note: This is toJSON instead of toString to make it easy to save logs using JSON.stringify.
*/
toJSON() {
let m = this.name;
if (this.message) m += ': ' + this.message;
@ -33,6 +55,21 @@ export class LogMessageWithStack extends Error {
}
return m;
}
/**
* Flatten the message for sending over a message channel.
*
* Note `extra` may get mangled by postMessage.
*/
toRawData() {
return {
name: this.name,
message: this.message,
stackHiddenMessage: this.stackHiddenMessage,
stack: this.stack,
extra: this.extra
};
}
}
/**

View file

@ -1,13 +1,12 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/import { version } from '../version.js';
**/import { globalTestConfig } from '../../framework/test_config.js';import { version } from '../version.js';
import { TestCaseRecorder } from './test_case_recorder.js';
export class Logger {
static globalDebugMode = false;
results = new Map();
@ -19,7 +18,7 @@ export class Logger {
const result = { status: 'running', timems: -1 };
this.results.set(name, result);
return [
new TestCaseRecorder(result, this.overriddenDebugMode ?? Logger.globalDebugMode),
new TestCaseRecorder(result, this.overriddenDebugMode ?? globalTestConfig.enableDebugLogs),
result];
}

View file

@ -1,4 +1,34 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ // MAINTENANCE_TODO: Add warn expectations
export {};
/**
* Raw data for a test log message.
*
* This form is sendable over a message channel, except `extra` may get mangled.
*/
/**
* Test case results in a form sendable over a message channel.
*
* Note `extra` may get mangled by postMessage.
*/export {};

View file

@ -45,8 +45,6 @@ export class TestCaseRecorder {
logs = [];
logLinesAtCurrentSeverity = 0;
debugging = false;
/** Used to dedup log messages which have identical stacks. */
messagesForPreviouslySeenStacks = new Map();
constructor(result, debugging) {
this.result = result;
@ -143,13 +141,15 @@ export class TestCaseRecorder {
this.skipped(ex);
return;
}
this.logImpl(LogSeverity.ThrewException, 'EXCEPTION', ex);
// logImpl will discard the original error's ex.name. Preserve it here.
const name = ex instanceof Error ? `EXCEPTION: ${ex.name}` : 'EXCEPTION';
this.logImpl(LogSeverity.ThrewException, name, ex);
}
logImpl(level, name, baseException) {
assert(baseException instanceof Error, 'test threw a non-Error object');
globalTestConfig.testHeartbeatCallback();
const logMessage = new LogMessageWithStack(name, baseException);
const logMessage = LogMessageWithStack.wrapError(name, baseException);
// Final case status should be the "worst" of all log entries.
if (this.inSubCase) {

View file

@ -58,7 +58,10 @@ function compareOneLevel(ordering, aIsBig, bIsBig) {
return Ordering.Unordered;
}
function comparePaths(a, b) {
/**
* Compare two file paths, or file-local test paths, returning an Ordering between the two.
*/
export function comparePaths(a, b) {
const shorter = Math.min(a.length, b.length);
for (let i = 0; i < shorter; ++i) {

View file

@ -1,6 +1,6 @@
/**
* 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 { optionWorkerMode } from '../../runtime/helper/options.js';import { assert, unreachable } from '../../util/util.js';
import { compareQueries, Ordering } from './compare.js';
@ -188,12 +188,12 @@ wptURL)
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;...
Expectation should be of the form path/to/cts.https.html?debug=0&q=suite:test_path:test_name:foo=1;bar=2;...
`
);
const params = expectationURL.searchParams;
if (optionEnabled('worker', params) !== optionEnabled('worker', wptURL.searchParams)) {
if (optionWorkerMode('worker', params) !== optionWorkerMode('worker', wptURL.searchParams)) {
continue;
}

View file

@ -34,7 +34,7 @@ import { validQueryPart } from '../internal/query/validQueryPart.js';
import { assert, unreachable } from '../util/util.js';
import { logToWebsocket } from './websocket_logger.js';
import { logToWebSocket } from './websocket_logger.js';
@ -294,9 +294,11 @@ class TestBuilder {
(this.description ? this.description + '\n\n' : '') + 'TODO: .unimplemented()';
this.isUnimplemented = true;
this.testFn = () => {
// Use the beforeFn to skip the test, so we don't have to iterate the subcases.
this.beforeFn = () => {
throw new SkipTestCase('test unimplemented');
};
this.testFn = () => {};
}
/** Perform various validation/"lint" chenks. */
@ -350,7 +352,7 @@ class TestBuilder {
const testcaseStringUnique = stringifyPublicParamsUniquely(params);
assert(
!seen.has(testcaseStringUnique),
`Duplicate public test case+subcase params for test ${testPathString}: ${testcaseString}`
`Duplicate public test case+subcase params for test ${testPathString}: ${testcaseString} (${caseQuery})`
);
seen.add(testcaseStringUnique);
}
@ -737,7 +739,7 @@ class RunCaseSpecific {
timems: rec.result.timems,
nonskippedSubcaseCount: rec.nonskippedSubcaseCount
};
logToWebsocket(JSON.stringify(msg));
logToWebSocket(JSON.stringify(msg));
}
}
}

View file

@ -2,5 +2,5 @@
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ // A listing of all specs within a single suite. This is the (awaited) type of
// `groups` in '{cts,unittests}/listing.ts' and `listing` in the auto-generated
// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings).
// 'out/{cts,unittests}/listing.js' files (see tools/gen_listings_and_webworkers).
export {};

View file

@ -1,3 +1,3 @@
// AUTO-GENERATED - DO NOT EDIT. See tools/gen_version.
export const version = 'ad066ef01b1060802b4a2329443faead9f345d87';
export const version = '20425f60bb00676af386b5c31e7748c0e2cb1702';

View file

@ -1,19 +1,24 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ /**
**/import { globalTestConfig } from '../framework/test_config.js'; /**
* - 'uninitialized' means we haven't tried to connect yet
* - Promise means it's pending
* - 'failed' means it failed (this is the most common case, where the logger isn't running)
* - WebSocket means it succeeded
*/let connection = 'uninitialized';
*/
let connection =
'uninitialized';
/**
* Log a string to a websocket at `localhost:59497`. See `tools/websocket-logger`.
* If the logToWebSocket option is enabled (?log_to_web_socket=1 in browser,
* --log-to-web-socket on command line, or enable it by default in options.ts),
* log a string to a websocket at `localhost:59497`. See `tools/websocket-logger`.
*
* This does nothing if a connection couldn't be established on the first call.
* This does nothing if a logToWebSocket is not enabled, or if a connection
* couldn't be established on the first call.
*/
export function logToWebsocket(msg) {
if (connection === 'failed') {
export function logToWebSocket(msg) {
if (!globalTestConfig.logToWebSocket || connection === 'failed') {
return;
}

View file

@ -1,11 +1,14 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/let windowURL = undefined;function getWindowURL() {if (windowURL === undefined) {
**/import { unreachable } from '../../util/util.js';let windowURL = undefined;
function getWindowURL() {
if (windowURL === undefined) {
windowURL = new URL(window.location.toString());
}
return windowURL;
}
/** Parse a runner option that is always boolean-typed. False if missing or '0'. */
export function optionEnabled(
opt,
searchParams = getWindowURL().searchParams)
@ -14,11 +17,32 @@ searchParams = getWindowURL().searchParams)
return val !== null && val !== '0';
}
/** Parse a runner option that is string-typed. If the option is missing, returns `null`. */
export function optionString(
opt,
searchParams = getWindowURL().searchParams)
{
return searchParams.get(opt) || '';
return searchParams.get(opt);
}
/** Runtime modes for running tests in different types of workers. */
/** Parse a runner option for different worker modes (as in `?worker=shared`). Null if no worker. */
export function optionWorkerMode(
opt,
searchParams = getWindowURL().searchParams)
{
const value = searchParams.get(opt);
if (value === null || value === '0') {
return null;
} else if (value === 'service') {
return 'service';
} else if (value === 'shared') {
return 'shared';
} else if (value === '' || value === '1' || value === 'dedicated') {
return 'dedicated';
}
unreachable('invalid worker= option value');
}
/**
@ -32,12 +56,16 @@ searchParams = getWindowURL().searchParams)
export const kDefaultCTSOptions = {
worker: false,
worker: null,
debug: true,
compatibility: false,
forceFallbackAdapter: false,
unrollConstEvalLoops: false,
powerPreference: ''
powerPreference: null,
logToWebSocket: false
};
/**
@ -59,19 +87,30 @@ export const kDefaultCTSOptions = {
* Options to the CTS.
*/
export const kCTSOptionsInfo = {
worker: { description: 'run in a worker' },
worker: {
description: 'run in a worker',
parser: optionWorkerMode,
selectValueDescriptions: [
{ value: null, description: 'no worker' },
{ value: 'dedicated', description: 'dedicated worker' },
{ value: 'shared', description: 'shared worker' },
{ value: 'service', description: 'service worker' }]
},
debug: { description: 'show more info' },
compatibility: { description: 'run in compatibility mode' },
forceFallbackAdapter: { description: 'pass forceFallbackAdapter: true to requestAdapter' },
unrollConstEvalLoops: { description: 'unroll const eval loops in WGSL' },
powerPreference: {
description: 'set default powerPreference for some tests',
parser: optionString,
selectValueDescriptions: [
{ value: '', description: 'default' },
{ value: null, description: 'default' },
{ value: 'low-power', description: 'low-power' },
{ value: 'high-performance', description: 'high-performance' }]
}
},
logToWebSocket: { description: 'send some logs to ws://localhost:59497/' }
};
/**

View file

@ -1,15 +1,11 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/import { setBaseResourcePath } from '../../framework/resources.js';import { globalTestConfig } from '../../framework/test_config.js';import { DefaultTestFileLoader } from '../../internal/file_loader.js';
import { Logger } from '../../internal/logging/logger.js';
import { parseQuery } from '../../internal/query/parseQuery.js';
import { setDefaultRequestAdapterOptions } from '../../util/navigator_gpu.js';
**/import { setBaseResourcePath } from '../../framework/resources.js';import { DefaultTestFileLoader } from '../../internal/file_loader.js';import { parseQuery } from '../../internal/query/parseQuery.js';
import { assert } from '../../util/util.js';
import { setupWorkerEnvironment } from './utils_worker.js';
// Should be DedicatedWorkerGlobalScope, but importing lib "webworker" conflicts with lib "dom".
// Should be WorkerGlobalScope, but importing lib "webworker" conflicts with lib "dom".
@ -17,25 +13,10 @@ const loader = new DefaultTestFileLoader();
setBaseResourcePath('../../../resources');
self.onmessage = async (ev) => {
const query = ev.data.query;
const expectations = ev.data.expectations;
const ctsOptions = ev.data.ctsOptions;
async function reportTestResults(ev) {
const { query, expectations, ctsOptions } = ev.data;
const { debug, unrollConstEvalLoops, powerPreference, compatibility } = ctsOptions;
globalTestConfig.unrollConstEvalLoops = unrollConstEvalLoops;
globalTestConfig.compatibility = compatibility;
Logger.globalDebugMode = debug;
const log = new Logger();
if (powerPreference || compatibility) {
setDefaultRequestAdapterOptions({
...(powerPreference && { powerPreference }),
// MAINTENANCE_TODO: Change this to whatever the option ends up being
...(compatibility && { compatibilityMode: true })
});
}
const log = setupWorkerEnvironment(ctsOptions);
const testcases = Array.from(await loader.loadCases(parseQuery(query)));
assert(testcases.length === 1, 'worker query resulted in != 1 cases');
@ -44,5 +25,23 @@ self.onmessage = async (ev) => {
const [rec, result] = log.record(testcase.query.toString());
await testcase.run(rec, expectations);
self.postMessage({ query, result });
this.postMessage({
query,
result: {
...result,
logs: result.logs?.map((l) => l.toRawData())
}
});
}
self.onmessage = (ev) => {
void reportTestResults.call(ev.source || self, ev);
};
self.onconnect = (event) => {
const port = event.ports[0];
port.onmessage = (ev) => {
void reportTestResults.call(port, ev);
};
};

View file

@ -2,33 +2,73 @@
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/import { LogMessageWithStack } from '../../internal/logging/log_message.js';
import { timeout } from '../../util/timeout.js';
import { assert } from '../../util/util.js';
import { kDefaultCTSOptions } from './options.js';
export class TestWorker {
/** Query all currently-registered service workers, and unregister them. */
function unregisterAllServiceWorkers() {
void navigator.serviceWorker.getRegistrations().then((registrations) => {
for (const registration of registrations) {
void registration.unregister();
}
});
}
// Firefox has serviceWorkers disabled in private mode
// and Servo does not support serviceWorkers yet.
if ('serviceWorker' in navigator) {
// NOTE: This code runs on startup for any runtime with worker support. Here, we use that chance to
// delete any leaked service workers, and register to clean up after ourselves at shutdown.
unregisterAllServiceWorkers();
window.addEventListener('beforeunload', () => {
unregisterAllServiceWorkers();
});
}
class TestBaseWorker {
resolvers = new Map();
constructor(ctsOptions) {
this.ctsOptions = { ...(ctsOptions || kDefaultCTSOptions), ...{ worker: true } };
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);
constructor(worker, ctsOptions) {
this.ctsOptions = { ...(ctsOptions || kDefaultCTSOptions), ...{ worker } };
}
// 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).
onmessage(ev) {
const query = ev.data.query;
const transferredResult = ev.data.result;
const result = {
status: transferredResult.status,
timems: transferredResult.timems,
logs: transferredResult.logs?.map((l) => new LogMessageWithStack(l))
};
this.resolvers.get(query)(result);
this.resolvers.delete(query);
// 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).
}
makeRequestAndRecordResult(
target,
query,
expectations)
{
const request = {
query,
expectations,
ctsOptions: this.ctsOptions
};
target.postMessage(request);
return new Promise((resolve) => {
assert(!this.resolvers.has(query), "can't request same query twice simultaneously");
this.resolvers.set(query, resolve);
});
}
async run(
@ -36,14 +76,120 @@ export class TestWorker {
query,
expectations = [])
{
this.worker.postMessage({
query,
expectations,
ctsOptions: this.ctsOptions
try {
rec.injectResult(await this.runImpl(query, expectations));
} catch (ex) {
rec.start();
rec.threw(ex);
rec.finish();
}
}
}
export class TestDedicatedWorker extends TestBaseWorker {
constructor(ctsOptions) {
super('dedicated', ctsOptions);
try {
if (typeof Worker === 'undefined') {
throw new Error('Dedicated Workers not available');
}
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) => this.onmessage(ev);
} catch (ex) {
assert(ex instanceof Error);
// Save the exception to re-throw in runImpl().
this.worker = ex;
}
}
runImpl(query, expectations = []) {
if (this.worker instanceof Worker) {
return this.makeRequestAndRecordResult(this.worker, query, expectations);
} else {
throw this.worker;
}
}
}
/** @deprecated Use TestDedicatedWorker instead. */
export class TestWorker extends TestDedicatedWorker {}
export class TestSharedWorker extends TestBaseWorker {
/** MessagePort to the SharedWorker, or an Error if it couldn't be initialized. */
constructor(ctsOptions) {
super('shared', ctsOptions);
try {
if (typeof SharedWorker === 'undefined') {
throw new Error('Shared Workers not available');
}
const selfPath = import.meta.url;
const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/'));
const workerPath = selfPathDir + '/test_worker-worker.js';
const worker = new SharedWorker(workerPath, { type: 'module' });
this.port = worker.port;
this.port.start();
this.port.onmessage = (ev) => this.onmessage(ev);
} catch (ex) {
assert(ex instanceof Error);
// Save the exception to re-throw in runImpl().
this.port = ex;
}
}
runImpl(query, expectations = []) {
if (this.port instanceof MessagePort) {
return this.makeRequestAndRecordResult(this.port, query, expectations);
} else {
throw this.port;
}
}
}
export class TestServiceWorker extends TestBaseWorker {
constructor(ctsOptions) {
super('service', ctsOptions);
}
async runImpl(query, expectations = []) {
if (!('serviceWorker' in navigator)) {
throw new Error('Service Workers not available');
}
const [suite, name] = query.split(':', 2);
const fileName = name.split(',').join('/');
const selfPath = import.meta.url;
const selfPathDir = selfPath.substring(0, selfPath.lastIndexOf('/'));
// Construct the path to the worker file, then use URL to resolve the `../` components.
const serviceWorkerURL = new URL(
`${selfPathDir}/../../../${suite}/webworker/${fileName}.as_worker.js`
).toString();
// If a registration already exists for this path, it will be ignored.
const registration = await navigator.serviceWorker.register(serviceWorkerURL, {
type: 'module'
});
const workerResult = await new Promise((resolve) => {
this.resolvers.set(query, resolve);
});
rec.injectResult(workerResult);
// Make sure the registration we just requested is active. (We don't worry about it being
// outdated from a previous page load, because we wipe all service workers on shutdown/startup.)
while (!registration.active || registration.active.scriptURL !== serviceWorkerURL) {
await new Promise((resolve) => timeout(resolve, 0));
}
const serviceWorker = registration.active;
navigator.serviceWorker.onmessage = (ev) => this.onmessage(ev);
return this.makeRequestAndRecordResult(serviceWorker, query, expectations);
}
}

View file

@ -0,0 +1,35 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/import { globalTestConfig } from '../../framework/test_config.js';import { Logger } from '../../internal/logging/logger.js';
import { setDefaultRequestAdapterOptions } from '../../util/navigator_gpu.js';
/**
* Set config environment for workers with ctsOptions and return a Logger.
*/
export function setupWorkerEnvironment(ctsOptions) {
const { powerPreference, compatibility } = ctsOptions;
globalTestConfig.enableDebugLogs = ctsOptions.debug;
globalTestConfig.unrollConstEvalLoops = ctsOptions.unrollConstEvalLoops;
globalTestConfig.compatibility = compatibility;
globalTestConfig.logToWebSocket = ctsOptions.logToWebSocket;
const log = new Logger();
if (powerPreference || compatibility) {
setDefaultRequestAdapterOptions({
...(powerPreference && { powerPreference }),
// MAINTENANCE_TODO: Change this to whatever the option ends up being
...(compatibility && { compatibilityMode: true })
});
}
return log;
}

View file

@ -0,0 +1,54 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/import { LogMessageWithStack } from '../../internal/logging/log_message.js';import { comparePaths, comparePublicParamsPaths, Ordering } from '../../internal/query/compare.js';
import { parseQuery } from '../../internal/query/parseQuery.js';
import { TestQuerySingleCase } from '../../internal/query/query.js';
import { assert } from '../../util/util.js';
import { setupWorkerEnvironment } from './utils_worker.js';
/**
* Sets up the currently running Web Worker to wrap the TestGroup object `g`.
* `g` is the `g` exported from a `.spec.ts` file: a TestGroupBuilder<F> interface,
* which underneath is actually a TestGroup<F> object.
*
* This is used in the generated `.as_worker.js` files that are generated to use as service workers.
*/
export function wrapTestGroupForWorker(g) {
self.onmessage = async (ev) => {
const { query, expectations, ctsOptions } = ev.data;
try {
const log = setupWorkerEnvironment(ctsOptions);
const testQuery = parseQuery(query);
assert(testQuery instanceof TestQuerySingleCase);
let testcase = null;
for (const t of g.iterate()) {
if (comparePaths(t.testPath, testQuery.testPathParts) !== Ordering.Equal) {
continue;
}
for (const c of t.iterate(testQuery.params)) {
if (comparePublicParamsPaths(c.id.params, testQuery.params) === Ordering.Equal) {
testcase = c;
}
}
}
assert(!!testcase, 'testcase not found');
const [rec, result] = log.record(query);
await testcase.run(rec, testQuery, expectations);
ev.source?.postMessage({ query, result });
} catch (thrown) {
const ex = thrown instanceof Error ? thrown : new Error(`${thrown}`);
ev.source?.postMessage({
query,
result: {
status: 'fail',
timems: 0,
logs: [LogMessageWithStack.wrapError('INTERNAL', ex)]
}
});
}
};
}

View file

@ -8,8 +8,8 @@ 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';
import { optionEnabled, optionWorkerMode } from './helper/options.js';
import { TestDedicatedWorker, TestServiceWorker, TestSharedWorker } from './helper/test_worker.js';
// testharness.js API (https://web-platform-tests.org/writing-tests/testharness-api.html)
@ -31,8 +31,10 @@ setup({
});
void (async () => {
const workerEnabled = optionEnabled('worker');
const worker = workerEnabled ? new TestWorker() : undefined;
const workerString = optionWorkerMode('worker');
const dedicatedWorker = workerString === 'dedicated' ? new TestDedicatedWorker() : undefined;
const sharedWorker = workerString === 'shared' ? new TestSharedWorker() : undefined;
const serviceWorker = workerString === 'service' ? new TestServiceWorker() : undefined;
globalTestConfig.unrollConstEvalLoops = optionEnabled('unroll_const_eval_loops');
@ -63,8 +65,12 @@ void (async () => {
const wpt_fn = async () => {
const [rec, res] = log.record(name);
if (worker) {
await worker.run(rec, name, expectations);
if (dedicatedWorker) {
await dedicatedWorker.run(rec, name, expectations);
} else if (sharedWorker) {
await sharedWorker.run(rec, name, expectations);
} else if (serviceWorker) {
await serviceWorker.run(rec, name, expectations);
} else {
await testcase.run(rec, expectations);
}

View file

@ -1,8 +1,6 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/ /// <reference types="@webgpu/types" />
import { ErrorWithExtra, assert, objectEquals } from './util.js';
**/import { ErrorWithExtra, assert, objectEquals } from './util.js';
/**
* Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations).
@ -72,7 +70,8 @@ export function getGPU(recorder) {
if (recorder) {
void promise.then(async (adapter) => {
if (adapter) {
const info = await adapter.requestAdapterInfo();
// MAINTENANCE_TODO: Remove requestAdapterInfo when info is implemented.
const info = adapter.info || (await adapter.requestAdapterInfo());
const infoString = `Adapter: ${info.vendor} / ${info.architecture} / ${info.device}`;
recorder.debug(new ErrorWithExtra(infoString, () => ({ adapterInfo: info })));
}

View file

@ -1,7 +1,6 @@
/**
* AUTO-GENERATED - DO NOT EDIT. Source: https://github.com/gpuweb/cts
**/import { Float16Array } from '../../external/petamoriken/float16/float16.js';import { SkipTestCase } from '../framework/fixture.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';
@ -24,7 +23,7 @@ export class ErrorWithExtra extends Error {
super(message);
const oldExtras = baseOrMessage instanceof ErrorWithExtra ? baseOrMessage.extra : {};
this.extra = Logger.globalDebugMode ?
this.extra = globalTestConfig.enableDebugLogs ?
{ ...oldExtras, ...newExtra() } :
{ omitted: 'pass ?debug=1' };
}
@ -91,6 +90,7 @@ export function skipTestCase(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;
/**
@ -304,7 +304,8 @@ new Int32Array(),
new Float16Array(),
new Float32Array(),
new Float64Array(),
new BigInt64Array()];
new BigInt64Array(),
new BigUint64Array()];

File diff suppressed because it is too large Load diff

View file

@ -390,6 +390,26 @@
@ -467,4 +487,11 @@
/**
* Returns the nearest half-precision float representation of a number.
* @param x A numeric expression.
*/
/**
* Returns the nearest half-precision float representation of a number.
* @alias f16round
* @param x A numeric expression.
*/export {};

View file

@ -1,6 +1,6 @@
/**
* 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";
**/ /*! @petamoriken/float16 v3.8.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";
@ -19,6 +19,8 @@ const CANNOT_MIX_BIGINT_AND_OTHER_TYPES =
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 THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED =
"The comparison function must be either a function or undefined";
const OFFSET_IS_OUT_OF_BOUNDS = "Offset is out of bounds";
function uncurryThis(target) {
@ -48,7 +50,8 @@ const {
} = Reflect;
const NativeProxy = Proxy;
const {
MAX_SAFE_INTEGER: MAX_SAFE_INTEGER,
EPSILON,
MAX_SAFE_INTEGER,
isFinite: NumberIsFinite,
isNaN: NumberIsNaN
} = Number;
@ -97,7 +100,10 @@ const ArrayPrototypeToLocaleString = uncurryThis(
);
const NativeArrayPrototypeSymbolIterator = ArrayPrototype[SymbolIterator];
const ArrayPrototypeSymbolIterator = uncurryThis(NativeArrayPrototypeSymbolIterator);
const MathTrunc = Math.trunc;
const {
abs: MathAbs,
trunc: MathTrunc
} = Math;
const NativeArrayBuffer = ArrayBuffer;
const ArrayBufferIsView = NativeArrayBuffer.isView;
const ArrayBufferPrototype = NativeArrayBuffer.prototype;
@ -146,6 +152,7 @@ const TypedArrayPrototypeGetSymbolToStringTag = uncurryThisGetter(
TypedArrayPrototype,
SymbolToStringTag
);
const NativeUint8Array = Uint8Array;
const NativeUint16Array = Uint16Array;
const Uint16ArrayFrom = (...args) => {
return ReflectApply(TypedArrayFrom, NativeUint16Array, args);
@ -190,7 +197,10 @@ const SafeIteratorPrototype = ObjectCreate(null, {
}
});
function safeIfNeeded(array) {
if (array[SymbolIterator] === NativeArrayPrototypeSymbolIterator) {
if (
array[SymbolIterator] === NativeArrayPrototypeSymbolIterator &&
ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext)
{
return array;
}
const safe = ObjectCreate(SafeIteratorPrototype);
@ -221,8 +231,10 @@ function wrap(generator) {
}
function isObject(value) {
return value !== null && typeof value === "object" ||
typeof value === "function";
return (
value !== null && typeof value === "object" ||
typeof value === "function");
}
function isObjectLike(value) {
return value !== null && typeof value === "object";
@ -232,11 +244,16 @@ function isNativeTypedArray(value) {
}
function isNativeBigIntTypedArray(value) {
const typedArrayName = TypedArrayPrototypeGetSymbolToStringTag(value);
return typedArrayName === "BigInt64Array" ||
typedArrayName === "BigUint64Array";
return (
typedArrayName === "BigInt64Array" ||
typedArrayName === "BigUint64Array");
}
function isArrayBuffer(value) {
try {
if (ArrayIsArray(value)) {
return false;
}
ArrayBufferPrototypeGetByteLength(value);
return true;
} catch (e) {
@ -254,25 +271,26 @@ function isSharedArrayBuffer(value) {
return false;
}
}
function isAnyArrayBuffer(value) {
return isArrayBuffer(value) || isSharedArrayBuffer(value);
}
function isOrdinaryArray(value) {
if (!ArrayIsArray(value)) {
return false;
}
if (value[SymbolIterator] === NativeArrayPrototypeSymbolIterator) {
return true;
}
const iterator = value[SymbolIterator]();
return iterator[SymbolToStringTag] === "Array Iterator";
return (
value[SymbolIterator] === NativeArrayPrototypeSymbolIterator &&
ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext);
}
function isOrdinaryNativeTypedArray(value) {
if (!isNativeTypedArray(value)) {
return false;
}
if (value[SymbolIterator] === NativeTypedArrayPrototypeSymbolIterator) {
return true;
}
const iterator = value[SymbolIterator]();
return iterator[SymbolToStringTag] === "Array Iterator";
return (
value[SymbolIterator] === NativeTypedArrayPrototypeSymbolIterator &&
ArrayIteratorPrototype.next === ArrayIteratorPrototypeNext);
}
function isCanonicalIntegerIndexString(value) {
if (typeof value !== "string") {
@ -307,11 +325,37 @@ function hasFloat16ArrayBrand(target) {
return ReflectHas(constructor, brand);
}
const INVERSE_OF_EPSILON = 1 / EPSILON;
function roundTiesToEven(num) {
return num + INVERSE_OF_EPSILON - INVERSE_OF_EPSILON;
}
const FLOAT16_MIN_VALUE = 6.103515625e-05;
const FLOAT16_MAX_VALUE = 65504;
const FLOAT16_EPSILON = 0.0009765625;
const FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE = FLOAT16_EPSILON * FLOAT16_MIN_VALUE;
const FLOAT16_EPSILON_DEVIDED_BY_EPSILON = FLOAT16_EPSILON * INVERSE_OF_EPSILON;
function roundToFloat16(num) {
const number = +num;
if (!NumberIsFinite(number) || number === 0) {
return number;
}
const sign = number > 0 ? 1 : -1;
const absolute = MathAbs(number);
if (absolute < FLOAT16_MIN_VALUE) {
return sign * roundTiesToEven(absolute / FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE) * FLOAT16_EPSILON_MULTIPLIED_BY_FLOAT16_MIN_VALUE;
}
const temp = (1 + FLOAT16_EPSILON_DEVIDED_BY_EPSILON) * absolute;
const result = temp - (temp - absolute);
if (result > FLOAT16_MAX_VALUE || NumberIsNaN(result)) {
return sign * Infinity;
}
return sign * result;
}
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);
const baseTable = new NativeUint16Array(512);
const shiftTable = new NativeUint8Array(512);
for (let i = 0; i < 256; ++i) {
const e = i - 127;
if (e < -27) {
@ -342,14 +386,12 @@ for (let i = 0; i < 256; ++i) {
}
}
function roundToFloat16Bits(num) {
floatView[0] = num;
floatView[0] = roundToFloat16(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;
@ -364,6 +406,7 @@ for (let i = 1; i < 1024; ++i) {
for (let i = 1024; i < 2048; ++i) {
mantissaTable[i] = 0x38000000 + (i - 1024 << 13);
}
const exponentTable = new NativeUint32Array(64);
for (let i = 1; i < 31; ++i) {
exponentTable[i] = i << 23;
}
@ -373,14 +416,15 @@ for (let i = 33; i < 63; ++i) {
exponentTable[i] = 0x80000000 + (i - 32 << 23);
}
exponentTable[63] = 0xc7800000;
const offsetTable = new NativeUint16Array(64);
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];
const i = float16bits >> 10;
uint32View[0] = mantissaTable[offsetTable[i] + (float16bits & 0x3ff)] + exponentTable[i];
return floatView[0];
}
@ -572,26 +616,20 @@ class Float16Array {
let float16bitsArray;
if (isFloat16Array(input)) {
float16bitsArray = ReflectConstruct(NativeUint16Array, [getFloat16BitsArray(input)], new.target);
} else if (isObject(input) && !isArrayBuffer(input)) {
} else if (isObject(input) && !isAnyArrayBuffer(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(
const data = new NativeArrayBuffer(
length * BYTES_PER_ELEMENT
);
float16bitsArray = ReflectConstruct(NativeUint16Array, [data], new.target);
@ -758,6 +796,30 @@ class Float16Array {
}
return convertToNumber(float16bitsArray[k]);
}
with(index, value) {
assertFloat16Array(this);
const float16bitsArray = getFloat16BitsArray(this);
const length = TypedArrayPrototypeGetLength(float16bitsArray);
const relativeIndex = ToIntegerOrInfinity(index);
const k = relativeIndex >= 0 ? relativeIndex : length + relativeIndex;
const number = +value;
if (k < 0 || k >= length) {
throw NativeRangeError(OFFSET_IS_OUT_OF_BOUNDS);
}
const uint16 = new NativeUint16Array(
TypedArrayPrototypeGetBuffer(float16bitsArray),
TypedArrayPrototypeGetByteOffset(float16bitsArray),
TypedArrayPrototypeGetLength(float16bitsArray)
);
const cloned = new Float16Array(
TypedArrayPrototypeGetBuffer(
TypedArrayPrototypeSlice(uint16)
)
);
const array = getFloat16BitsArray(cloned);
array[k] = roundToFloat16Bits(number);
return cloned;
}
map(callback, ...opts) {
assertFloat16Array(this);
const float16bitsArray = getFloat16BitsArray(this);
@ -995,6 +1057,23 @@ class Float16Array {
TypedArrayPrototypeReverse(float16bitsArray);
return this;
}
toReversed() {
assertFloat16Array(this);
const float16bitsArray = getFloat16BitsArray(this);
const uint16 = new NativeUint16Array(
TypedArrayPrototypeGetBuffer(float16bitsArray),
TypedArrayPrototypeGetByteOffset(float16bitsArray),
TypedArrayPrototypeGetLength(float16bitsArray)
);
const cloned = new Float16Array(
TypedArrayPrototypeGetBuffer(
TypedArrayPrototypeSlice(uint16)
)
);
const clonedFloat16bitsArray = getFloat16BitsArray(cloned);
TypedArrayPrototypeReverse(clonedFloat16bitsArray);
return cloned;
}
fill(value, ...opts) {
assertFloat16Array(this);
const float16bitsArray = getFloat16BitsArray(this);
@ -1020,6 +1099,29 @@ class Float16Array {
});
return this;
}
toSorted(compareFn) {
assertFloat16Array(this);
const float16bitsArray = getFloat16BitsArray(this);
if (compareFn !== undefined && typeof compareFn !== "function") {
throw new NativeTypeError(THE_COMPARISON_FUNCTION_MUST_BE_EITHER_A_FUNCTION_OR_UNDEFINED);
}
const sortCompare = compareFn !== undefined ? compareFn : defaultCompare;
const uint16 = new NativeUint16Array(
TypedArrayPrototypeGetBuffer(float16bitsArray),
TypedArrayPrototypeGetByteOffset(float16bitsArray),
TypedArrayPrototypeGetLength(float16bitsArray)
);
const cloned = new Float16Array(
TypedArrayPrototypeGetBuffer(
TypedArrayPrototypeSlice(uint16)
)
);
const clonedFloat16bitsArray = getFloat16BitsArray(cloned);
TypedArrayPrototypeSort(clonedFloat16bitsArray, (x, y) => {
return sortCompare(convertToNumber(x), convertToNumber(y));
});
return cloned;
}
slice(start, end) {
assertFloat16Array(this);
const float16bitsArray = getFloat16BitsArray(this);
@ -1216,13 +1318,8 @@ function setFloat16(dataView, byteOffset, value, ...opts) {
);
}
function hfround(x) {
const number = +x;
if (!NumberIsFinite(number) || number === 0) {
return number;
}
const x16 = roundToFloat16Bits(number);
return convertToNumber(x16);
function f16round(x) {
return roundToFloat16(x);
}
export { Float16Array, getFloat16, hfround, isFloat16Array, isTypedArray, setFloat16 };
export { Float16Array, f16round, getFloat16, f16round as hfround, isFloat16Array, isTypedArray, setFloat16 };

View file

@ -44,17 +44,17 @@ rm temp.mp4
Vp9 rotated video files are generated by ffmpeg cmds below:
```
// Generate four-colors-h264-bt601-rotate-90.mp4, mimeType: 'video/mp4; codecs=vp9'
// Generate four-colors-vp9-bt601-rotate-90.mp4, mimeType: 'video/mp4; codecs=vp9'
ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv -vf transpose=2 temp.mp4
ffmpeg -display_rotation 270 -i temp.mp4 -c copy four-colors-vp9-bt601-rotate-90.mp4
rm temp.mp4
// Generate four-colors-h264-bt601-rotate-180.mp4, mimeType: 'video/mp4; codecs=vp9'
// Generate four-colors-vp9-bt601-rotate-180.mp4, mimeType: 'video/mp4; codecs=vp9'
ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv -vf transpose=2,transpose=2 temp.mp4
ffmpeg -display_rotation 180 -i temp.mp4 -c copy four-colors-vp9-bt601-rotate-180.mp4
rm temp.mp4
// Generate four-colors-h264-bt601-rotate-270.mp4, mimeType: 'video/mp4; codecs=vp9'
// Generate four-colors-vp9-bt601-rotate-270.mp4, mimeType: 'video/mp4; codecs=vp9'
ffmpeg.exe -loop 1 -i .\four-colors.png -c:v libvpx-vp9 -pix_fmt yuv420p -frames 50 -colorspace smpte170m -color_primaries smpte170m -color_trc smpte170m -color_range tv -vf transpose=1 temp.mp4
ffmpeg -display_rotation 90 -i temp.mp4 -c copy four-colors-vp9-bt601-rotate-270.mp4
rm temp.mp4

View file

@ -1,107 +1,112 @@
{
"webgpu/shader/execution/binary/af_addition.bin": "c7c51c39",
"webgpu/shader/execution/binary/af_logical.bin": "59188363",
"webgpu/shader/execution/binary/af_division.bin": "3dceb51d",
"webgpu/shader/execution/binary/af_matrix_addition.bin": "7dce888f",
"webgpu/shader/execution/binary/af_matrix_subtraction.bin": "1bf7797",
"webgpu/shader/execution/binary/af_multiplication.bin": "5bd9db91",
"webgpu/shader/execution/binary/af_remainder.bin": "9426ee9f",
"webgpu/shader/execution/binary/af_subtraction.bin": "823576a9",
"webgpu/shader/execution/binary/f16_addition.bin": "98228b04",
"webgpu/shader/execution/binary/f16_logical.bin": "7f4e05ab",
"webgpu/shader/execution/binary/f16_division.bin": "95e60c24",
"webgpu/shader/execution/binary/f16_matrix_addition.bin": "3503e24",
"webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin": "5b0b6c54",
"webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin": "7c2b67cc",
"webgpu/shader/execution/binary/f16_matrix_subtraction.bin": "3ab51e54",
"webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin": "c509829e",
"webgpu/shader/execution/binary/f16_multiplication.bin": "2cb9031c",
"webgpu/shader/execution/binary/f16_remainder.bin": "36a93ab6",
"webgpu/shader/execution/binary/f16_subtraction.bin": "5e564fad",
"webgpu/shader/execution/binary/f32_addition.bin": "6a004a96",
"webgpu/shader/execution/binary/f32_logical.bin": "29b78ff7",
"webgpu/shader/execution/binary/f32_division.bin": "f3960bd",
"webgpu/shader/execution/binary/f32_matrix_addition.bin": "b7a7252c",
"webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin": "223c03dc",
"webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin": "9fa0adb0",
"webgpu/shader/execution/binary/f32_matrix_subtraction.bin": "48fb4b77",
"webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin": "9a9a8e4f",
"webgpu/shader/execution/binary/f32_multiplication.bin": "6384c269",
"webgpu/shader/execution/binary/f32_remainder.bin": "668869cd",
"webgpu/shader/execution/binary/f32_subtraction.bin": "b720a489",
"webgpu/shader/execution/binary/i32_arithmetic.bin": "794ff384",
"webgpu/shader/execution/binary/i32_comparison.bin": "5742ecc8",
"webgpu/shader/execution/binary/u32_arithmetic.bin": "61c3eca",
"webgpu/shader/execution/binary/u32_comparison.bin": "8b463360",
"webgpu/shader/execution/abs.bin": "84759b96",
"webgpu/shader/execution/acos.bin": "d2fecf7e",
"webgpu/shader/execution/acosh.bin": "ae49ab4a",
"webgpu/shader/execution/asin.bin": "ef8d1ee0",
"webgpu/shader/execution/asinh.bin": "3fddcdc",
"webgpu/shader/execution/atan.bin": "fa01b779",
"webgpu/shader/execution/atan2.bin": "6544e27b",
"webgpu/shader/execution/atanh.bin": "dbfcf972",
"webgpu/shader/execution/bitcast.bin": "c871c53a",
"webgpu/shader/execution/ceil.bin": "a9259b43",
"webgpu/shader/execution/clamp.bin": "1c0cdd92",
"webgpu/shader/execution/cos.bin": "d32e388f",
"webgpu/shader/execution/cosh.bin": "353519fe",
"webgpu/shader/execution/cross.bin": "e1425e59",
"webgpu/shader/execution/degrees.bin": "303cb3",
"webgpu/shader/execution/determinant.bin": "b61bbfdb",
"webgpu/shader/execution/distance.bin": "9aee4ac6",
"webgpu/shader/execution/dot.bin": "2786d688",
"webgpu/shader/execution/exp.bin": "c791dee0",
"webgpu/shader/execution/exp2.bin": "7317dc87",
"webgpu/shader/execution/faceForward.bin": "2d7ecc3d",
"webgpu/shader/execution/floor.bin": "aad85712",
"webgpu/shader/execution/fma.bin": "cc8a275d",
"webgpu/shader/execution/fract.bin": "b651c53",
"webgpu/shader/execution/frexp.bin": "63c4d7b5",
"webgpu/shader/execution/inverseSqrt.bin": "8065a8af",
"webgpu/shader/execution/ldexp.bin": "e3d5da1e",
"webgpu/shader/execution/length.bin": "c4a77d",
"webgpu/shader/execution/log.bin": "19bd1b97",
"webgpu/shader/execution/log2.bin": "750e4aef",
"webgpu/shader/execution/max.bin": "1858ef6c",
"webgpu/shader/execution/min.bin": "27604a2a",
"webgpu/shader/execution/mix.bin": "e9174bda",
"webgpu/shader/execution/modf.bin": "faeb6938",
"webgpu/shader/execution/normalize.bin": "8325262b",
"webgpu/shader/execution/pack2x16float.bin": "3eab9d7e",
"webgpu/shader/execution/pow.bin": "a95ee5d5",
"webgpu/shader/execution/quantizeToF16.bin": "87ea1db0",
"webgpu/shader/execution/radians.bin": "8900171f",
"webgpu/shader/execution/reflect.bin": "34871ff1",
"webgpu/shader/execution/refract.bin": "8afd8086",
"webgpu/shader/execution/round.bin": "1f0d895",
"webgpu/shader/execution/saturate.bin": "208f6223",
"webgpu/shader/execution/sign.bin": "5d5eef01",
"webgpu/shader/execution/sin.bin": "88673d1b",
"webgpu/shader/execution/sinh.bin": "912004c4",
"webgpu/shader/execution/smoothstep.bin": "58521adc",
"webgpu/shader/execution/sqrt.bin": "6efab59a",
"webgpu/shader/execution/step.bin": "5d6a0269",
"webgpu/shader/execution/tan.bin": "1c2ed170",
"webgpu/shader/execution/tanh.bin": "69c199a6",
"webgpu/shader/execution/transpose.bin": "298a08a6",
"webgpu/shader/execution/trunc.bin": "b7f8c151",
"webgpu/shader/execution/unpack2x16float.bin": "ea2edfa",
"webgpu/shader/execution/unpack2x16snorm.bin": "982a4f26",
"webgpu/shader/execution/unpack2x16unorm.bin": "938aa3f3",
"webgpu/shader/execution/unpack4x8snorm.bin": "38d66fd9",
"webgpu/shader/execution/unpack4x8unorm.bin": "ea69a50e",
"webgpu/shader/execution/unary/af_arithmetic.bin": "ff253208",
"webgpu/shader/execution/unary/af_assignment.bin": "9b7be51c",
"webgpu/shader/execution/unary/bool_conversion.bin": "cc9afc72",
"webgpu/shader/execution/unary/f16_arithmetic.bin": "9d141077",
"webgpu/shader/execution/unary/f16_conversion.bin": "411d49cb",
"webgpu/shader/execution/unary/f32_arithmetic.bin": "cfbaceaf",
"webgpu/shader/execution/unary/f32_conversion.bin": "1e5cb1a7",
"webgpu/shader/execution/unary/i32_arithmetic.bin": "a10a7f07",
"webgpu/shader/execution/unary/i32_complement.bin": "4a7fabe2",
"webgpu/shader/execution/unary/i32_conversion.bin": "46a36b14",
"webgpu/shader/execution/unary/u32_complement.bin": "efe3fec7",
"webgpu/shader/execution/unary/u32_conversion.bin": "afebfab2",
"webgpu/shader/execution/unary/ai_assignment.bin": "dd599f63"
"webgpu/shader/execution/binary/af_addition.bin": "338b5b67",
"webgpu/shader/execution/binary/af_logical.bin": "3b2aceb8",
"webgpu/shader/execution/binary/af_division.bin": "a77dc4c0",
"webgpu/shader/execution/binary/af_matrix_addition.bin": "136a7fbb",
"webgpu/shader/execution/binary/af_matrix_subtraction.bin": "90f2c731",
"webgpu/shader/execution/binary/af_multiplication.bin": "35ba40b9",
"webgpu/shader/execution/binary/af_remainder.bin": "41582f85",
"webgpu/shader/execution/binary/af_subtraction.bin": "a41420b2",
"webgpu/shader/execution/binary/f16_addition.bin": "ef10ca66",
"webgpu/shader/execution/binary/f16_logical.bin": "4bf24ca5",
"webgpu/shader/execution/binary/f16_division.bin": "f826b6ba",
"webgpu/shader/execution/binary/f16_matrix_addition.bin": "a910ddb0",
"webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin": "9458671c",
"webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin": "36be05d3",
"webgpu/shader/execution/binary/f16_matrix_subtraction.bin": "8aa6a88a",
"webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin": "38282a11",
"webgpu/shader/execution/binary/f16_multiplication.bin": "62f91819",
"webgpu/shader/execution/binary/f16_remainder.bin": "f829bb65",
"webgpu/shader/execution/binary/f16_subtraction.bin": "82d4e231",
"webgpu/shader/execution/binary/f32_addition.bin": "9b0a0c50",
"webgpu/shader/execution/binary/f32_logical.bin": "b75af25a",
"webgpu/shader/execution/binary/f32_division.bin": "f6d7832f",
"webgpu/shader/execution/binary/f32_matrix_addition.bin": "3317c75b",
"webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin": "c6f990c8",
"webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin": "b091a702",
"webgpu/shader/execution/binary/f32_matrix_subtraction.bin": "2d12a16b",
"webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin": "e1217524",
"webgpu/shader/execution/binary/f32_multiplication.bin": "19774fb3",
"webgpu/shader/execution/binary/f32_remainder.bin": "fd94bb9a",
"webgpu/shader/execution/binary/f32_subtraction.bin": "dba7cd7a",
"webgpu/shader/execution/binary/i32_arithmetic.bin": "e3b317e1",
"webgpu/shader/execution/binary/i32_comparison.bin": "63fa9be8",
"webgpu/shader/execution/binary/u32_arithmetic.bin": "e8b4008c",
"webgpu/shader/execution/binary/u32_comparison.bin": "d472fd61",
"webgpu/shader/execution/abs.bin": "631d932d",
"webgpu/shader/execution/acos.bin": "afcafcb1",
"webgpu/shader/execution/acosh.bin": "4b30eb95",
"webgpu/shader/execution/asin.bin": "c850c13d",
"webgpu/shader/execution/asinh.bin": "66a6acc0",
"webgpu/shader/execution/atan.bin": "2aabbb53",
"webgpu/shader/execution/atan2.bin": "82dd926a",
"webgpu/shader/execution/atanh.bin": "b98c937c",
"webgpu/shader/execution/bitcast.bin": "5daaee1b",
"webgpu/shader/execution/ceil.bin": "d0c32cf4",
"webgpu/shader/execution/clamp.bin": "4d1fc26a",
"webgpu/shader/execution/cos.bin": "dc837ae2",
"webgpu/shader/execution/cosh.bin": "d9e90580",
"webgpu/shader/execution/cross.bin": "ce7979f",
"webgpu/shader/execution/degrees.bin": "1436a196",
"webgpu/shader/execution/determinant.bin": "f36f1fa1",
"webgpu/shader/execution/distance.bin": "5103f8bd",
"webgpu/shader/execution/dot.bin": "4514172c",
"webgpu/shader/execution/exp.bin": "f41150bd",
"webgpu/shader/execution/exp2.bin": "19c494e",
"webgpu/shader/execution/faceForward.bin": "27b6e4a7",
"webgpu/shader/execution/floor.bin": "5bb5098b",
"webgpu/shader/execution/fma.bin": "daace9a4",
"webgpu/shader/execution/fract.bin": "be5f0334",
"webgpu/shader/execution/frexp.bin": "c9efaf7c",
"webgpu/shader/execution/inverseSqrt.bin": "8a50b907",
"webgpu/shader/execution/ldexp.bin": "cb4cea21",
"webgpu/shader/execution/length.bin": "a1b9fbeb",
"webgpu/shader/execution/log.bin": "9f2eb7c3",
"webgpu/shader/execution/log2.bin": "9ee7d861",
"webgpu/shader/execution/max.bin": "11e4608e",
"webgpu/shader/execution/min.bin": "7a084c44",
"webgpu/shader/execution/mix.bin": "7b892a4f",
"webgpu/shader/execution/modf.bin": "b3bf26d7",
"webgpu/shader/execution/normalize.bin": "18eba01d",
"webgpu/shader/execution/pack2x16float.bin": "82df446e",
"webgpu/shader/execution/pow.bin": "d3a05344",
"webgpu/shader/execution/quantizeToF16.bin": "7793770e",
"webgpu/shader/execution/radians.bin": "582c1f6b",
"webgpu/shader/execution/reflect.bin": "9161d6e5",
"webgpu/shader/execution/refract.bin": "817b59aa",
"webgpu/shader/execution/round.bin": "cb881aa2",
"webgpu/shader/execution/saturate.bin": "3716605e",
"webgpu/shader/execution/sign.bin": "549ac92f",
"webgpu/shader/execution/sin.bin": "5ec5bcb7",
"webgpu/shader/execution/sinh.bin": "62f6b736",
"webgpu/shader/execution/smoothstep.bin": "aa97768",
"webgpu/shader/execution/sqrt.bin": "d0a134ce",
"webgpu/shader/execution/step.bin": "b8035bb9",
"webgpu/shader/execution/tan.bin": "b34366cd",
"webgpu/shader/execution/tanh.bin": "8f5edddc",
"webgpu/shader/execution/transpose.bin": "1aa2de65",
"webgpu/shader/execution/trunc.bin": "cf43e3f7",
"webgpu/shader/execution/unpack2x16float.bin": "57ea7c02",
"webgpu/shader/execution/unpack2x16snorm.bin": "17fd3f86",
"webgpu/shader/execution/unpack2x16unorm.bin": "fc68bc4b",
"webgpu/shader/execution/unpack4x8snorm.bin": "fef504c1",
"webgpu/shader/execution/unpack4x8unorm.bin": "e8d8de93",
"webgpu/shader/execution/unary/af_arithmetic.bin": "14c0612a",
"webgpu/shader/execution/unary/af_assignment.bin": "3ad4afc",
"webgpu/shader/execution/unary/bool_conversion.bin": "15f7f3fb",
"webgpu/shader/execution/unary/f16_arithmetic.bin": "4a20db6d",
"webgpu/shader/execution/unary/f16_conversion.bin": "31f72f5a",
"webgpu/shader/execution/unary/f32_arithmetic.bin": "f1c311cb",
"webgpu/shader/execution/unary/f32_conversion.bin": "7539cdb3",
"webgpu/shader/execution/unary/i32_arithmetic.bin": "de945eec",
"webgpu/shader/execution/unary/i32_conversion.bin": "1728a03e",
"webgpu/shader/execution/unary/u32_conversion.bin": "9e6ca0ce",
"webgpu/shader/execution/unary/ai_assignment.bin": "1fd685a2",
"webgpu/shader/execution/binary/ai_arithmetic.bin": "90e651f4",
"webgpu/shader/execution/unary/ai_arithmetic.bin": "ba31d178",
"webgpu/shader/execution/binary/af_matrix_matrix_multiplication.bin": "bc8b52ef",
"webgpu/shader/execution/binary/af_matrix_scalar_multiplication.bin": "54edf6a2",
"webgpu/shader/execution/binary/af_matrix_vector_multiplication.bin": "43b036b1",
"webgpu/shader/execution/derivatives.bin": "65c15fc3",
"webgpu/shader/execution/fwidth.bin": "cc91c875"
}

Some files were not shown because too many files have changed in this diff Show more