blob: 88d08b77f5493654149e1efeafc91b7d758fd808 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
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.
readonly kDeviceLostTimeoutMS = 2000;
getDeviceLostWithTimeout(lost: Promise<GPUDeviceLostInfo>): Promise<GPUDeviceLostInfo> {
return raceWithRejectOnTimeout(lost, this.kDeviceLostTimeoutMS, 'device was not lost');
}
expectDeviceDestroyed(device: GPUDevice): void {
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: GPUDevice = 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: GPUDevice = 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);
});
|