Skip to content

Commit 5a5838d

Browse files
committed
Implement CTS requestAdapter test
1 parent e583fa4 commit 5a5838d

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
export const description = `
2+
Tests for GPU.requestAdapter.
3+
4+
Test all possible options to requestAdapter.
5+
default, low-power, and high performance should all always return adapters.
6+
forceFallbackAdapter may or may not return an adapter.
7+
8+
GPU.requestAdapter can technically return null for any reason
9+
but we need test functionality so the test requires an adapter except
10+
when forceFallbackAdapter is true.
11+
12+
The test runs simple compute shader is run that fills a buffer with consecutive
13+
values and then checks the result to test the adapter for basic functionality.
14+
`;
15+
16+
import { Fixture } from '../../../../common/framework/fixture.js';
17+
import { makeTestGroup } from '../../../../common/framework/test_group.js';
18+
import { getGPU } from '../../../../common/util/navigator_gpu.js';
19+
import { assert, objectEquals, iterRange } from '../../../../common/util/util.js';
20+
21+
export const g = makeTestGroup(Fixture);
22+
23+
const powerPreferenceModes: Array<GPUPowerPreference | undefined> = [
24+
undefined,
25+
'low-power',
26+
'high-performance',
27+
];
28+
const forceFallbackOptions: Array<boolean | undefined> = [undefined, false, true];
29+
30+
async function testAdapter(adapter: GPUAdapter | null) {
31+
assert(adapter !== null, 'Failed to get adapter.');
32+
const device = await adapter.requestDevice();
33+
34+
assert(device !== null, 'Failed to get device.');
35+
36+
const kOffset = 1230000;
37+
const pipeline = await device.createComputePipeline({
38+
compute: {
39+
module: device.createShaderModule({
40+
code: `
41+
struct Buffer { data: array<u32>; };
42+
43+
@group(0) @binding(0) var<storage, read_write> buffer: Buffer;
44+
@stage(compute) @workgroup_size(1u) fn main(
45+
@builtin(global_invocation_id) id: vec3<u32>) {
46+
buffer.data[id.x] = id.x + ${kOffset}u;
47+
}
48+
`,
49+
}),
50+
entryPoint: 'main',
51+
},
52+
});
53+
54+
const kNumElements = 64;
55+
const kBufferSize = kNumElements * 4;
56+
const buffer = device.createBuffer({
57+
size: kBufferSize,
58+
usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,
59+
});
60+
61+
const resultBuffer = device.createBuffer({
62+
size: kBufferSize,
63+
usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,
64+
});
65+
66+
const bindGroup = device.createBindGroup({
67+
layout: pipeline.getBindGroupLayout(0),
68+
entries: [{ binding: 0, resource: { buffer } }],
69+
});
70+
71+
const encoder = device.createCommandEncoder();
72+
73+
const pass = encoder.beginComputePass();
74+
pass.setPipeline(pipeline);
75+
pass.setBindGroup(0, bindGroup);
76+
pass.dispatch(kNumElements);
77+
pass.end();
78+
79+
encoder.copyBufferToBuffer(buffer, 0, resultBuffer, 0, kBufferSize);
80+
81+
device.queue.submit([encoder.finish()]);
82+
83+
const expected = new Uint32Array([...iterRange(kNumElements, x => x + kOffset)]);
84+
85+
await resultBuffer.mapAsync(GPUMapMode.READ);
86+
const actual = new Uint32Array(resultBuffer.getMappedRange());
87+
88+
assert(objectEquals(actual, expected), 'compute pipeline ran');
89+
90+
resultBuffer.destroy();
91+
buffer.destroy();
92+
device.destroy();
93+
}
94+
95+
g.test('requestAdapter')
96+
.desc(`request adapter with all possible options and check for basic functionality`)
97+
.params(u =>
98+
u
99+
.combine('powerPreference', powerPreferenceModes)
100+
.combine('forceFallbackAdapter', forceFallbackOptions)
101+
)
102+
.fn(async t => {
103+
const { powerPreference, forceFallbackAdapter } = t.params;
104+
const adapter = await getGPU().requestAdapter({
105+
...(powerPreference !== undefined && { powerPreference }),
106+
...(forceFallbackAdapter !== undefined && { forceFallbackAdapter }),
107+
});
108+
109+
// failing to create an adapter when forceFallbackAdapter is true is ok.
110+
if (forceFallbackAdapter && !adapter) {
111+
t.skip('No adapter available');
112+
return;
113+
}
114+
115+
await testAdapter(adapter);
116+
});
117+
118+
g.test('requestAdapter_no_parameters')
119+
.desc(`request adapter with no parameters`)
120+
.fn(async () => {
121+
const adapter = await getGPU().requestAdapter();
122+
await testAdapter(adapter);
123+
});

0 commit comments

Comments
 (0)