<!DOCTYPE html>
<meta charset="utf-8">
<title>WebGPU GPUAdapter single-use test</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
'use strict';
/**
* Takes a promise `p`, and returns a new one which rejects if `p` takes too long,
* and otherwise passes the result through.
* Borrowed from the WebGPU CTS common/util/util.ts
*/
function raceWithRejectOnTimeout(p, ms, msg) {
// 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 = setTimeout(() => {
reject(new PromiseTimeoutError(msg));
}, ms);
p = p.finally(() => clearTimeout(handle));
});
return Promise.race([p, timeoutPromise]);
}
promise_test(async t => {
const adapter = await navigator.gpu.requestAdapter();
assert_true(adapter !== null);
const device = await adapter.requestDevice();
assert_true(device !== null);
// requestDevice was successful, should begin returning lost devices from
// here on.
const staleDevice = await adapter.requestDevice();
assert_true(staleDevice !== null);
// Check to ensure the device is lost, and the loss is not due to it being explicitly destroyed.
const kTimeoutMS = 1000;
const lost = await raceWithRejectOnTimeout(staleDevice.lost, kTimeoutMS, 'device was not lost');
assert_true(lost.reason === 'unknown');
}, 'invalid after successful requestDevice');
promise_test(async t => {
const adapter = await navigator.gpu.requestAdapter();
assert_true(adapter !== null);
try {
await adapter.requestDevice({
requiredLimits: { maxBindGroups: adapter.limits.maxBindGroups + 1 },
});
assert_unreached('invalid requestDevice should have rejected');
} catch (e) {
assert_equals(e.name, 'OperationError');
}
// requestDevice failed, so should still be able to succeed.
const device = await adapter.requestDevice();
assert_true(device !== null);
}, 'valid when called after unsuccessful requestDevice');
promise_test(async t => {
const adapter = await navigator.gpu.requestAdapter();
assert_true(adapter !== null);
adapter.requestDevice({
requiredLimits: { maxBindGroups: adapter.limits.maxBindGroups + 1 },
}).catch(() => {});
// requestDevice will fail, so this should still be able to succeed.
const device = await adapter.requestDevice();
assert_true(device !== null);
}, 'valid when overlapping with unsuccessful requestDevice');
</script>