@@ -23,10 +23,35 @@ class TestFailedButDeviceReusable extends Error {}
23
23
class FeaturesNotSupported extends Error { }
24
24
export class TestOOMedShouldAttemptGC extends Error { }
25
25
26
- export type DescriptorModifierFn = (
27
- adapter : GPUAdapter ,
28
- desc : CanonicalDeviceDescriptor | undefined
29
- ) => CanonicalDeviceDescriptor ;
26
+ /**
27
+ * DescriptorModifier lets you supply a function to select a device
28
+ * based on the limits/features available from the adapter.
29
+ * Devices pooled based on a key and that key is derived before
30
+ * an adapter is requested. That means you select key without
31
+ * knowledge of what the adapter will provide. You do this by
32
+ * providing a keyModifier function that appends a suffix.
33
+ *
34
+ * For example: If your modifier adds all the limits you might
35
+ * choose 'maxLimits' are your suffix
36
+ *
37
+ * ```js
38
+ * keyModifier(s: string) { return `${s}:maxLimits`; },
39
+ * ```
40
+ *
41
+ * If your modifier selects only `maxBindGroups` and `maxColorAttachments`
42
+ * then your suffix might be `maxBindGroups&maxColorAttachments`
43
+ *
44
+ * ```js
45
+ * keyModifier(s: string) { return `${s}:maxBindGroups&maxColorAttachments`; },
46
+ * ```
47
+ */
48
+ export type DescriptorModifier = {
49
+ keyModifier ( baseKey : string ) : string ;
50
+ descriptorModifier (
51
+ adapter : GPUAdapter ,
52
+ desc : CanonicalDeviceDescriptor | undefined
53
+ ) : CanonicalDeviceDescriptor ;
54
+ } ;
30
55
31
56
export class DevicePool {
32
57
private holders : 'uninitialized' | 'failed' | DescriptorToHolderMap = 'uninitialized' ;
@@ -35,13 +60,13 @@ export class DevicePool {
35
60
async acquire (
36
61
recorder : TestCaseRecorder ,
37
62
descriptor : UncanonicalizedDeviceDescriptor | undefined ,
38
- descriptorModifierFn : DescriptorModifierFn | undefined
63
+ descriptorModifier : DescriptorModifier | undefined
39
64
) : Promise < DeviceProvider > {
40
65
let errorMessage = '' ;
41
66
if ( this . holders === 'uninitialized' ) {
42
67
this . holders = new DescriptorToHolderMap ( ) ;
43
68
try {
44
- await this . holders . getOrCreate ( recorder , undefined , descriptorModifierFn ) ;
69
+ await this . holders . getOrCreate ( recorder , undefined , descriptorModifier ) ;
45
70
} catch ( ex ) {
46
71
this . holders = 'failed' ;
47
72
if ( ex instanceof Error ) {
@@ -55,7 +80,7 @@ export class DevicePool {
55
80
`WebGPU device failed to initialize${ errorMessage } ; not retrying`
56
81
) ;
57
82
58
- const holder = await this . holders . getOrCreate ( recorder , descriptor , descriptorModifierFn ) ;
83
+ const holder = await this . holders . getOrCreate ( recorder , descriptor , descriptorModifier ) ;
59
84
60
85
assert ( holder . state === 'free' , 'Device was in use on DevicePool.acquire' ) ;
61
86
holder . state = 'acquired' ;
@@ -150,9 +175,10 @@ class DescriptorToHolderMap {
150
175
async getOrCreate (
151
176
recorder : TestCaseRecorder ,
152
177
uncanonicalizedDescriptor : UncanonicalizedDeviceDescriptor | undefined ,
153
- descriptorModifierFn : DescriptorModifierFn | undefined
178
+ descriptorModifier : DescriptorModifier | undefined
154
179
) : Promise < DeviceHolder > {
155
- const [ descriptor , key ] = canonicalizeDescriptor ( uncanonicalizedDescriptor ) ;
180
+ const [ descriptor , baseKey ] = canonicalizeDescriptor ( uncanonicalizedDescriptor ) ;
181
+ const key = descriptorModifier ?. keyModifier ( baseKey ) || baseKey ;
156
182
// Quick-reject descriptors that are known to be unsupported already.
157
183
if ( this . unsupported . has ( key ) ) {
158
184
throw new SkipTestCase (
@@ -174,7 +200,7 @@ class DescriptorToHolderMap {
174
200
// No existing item was found; add a new one.
175
201
let value ;
176
202
try {
177
- value = await DeviceHolder . create ( recorder , descriptor , descriptorModifierFn ) ;
203
+ value = await DeviceHolder . create ( recorder , descriptor , descriptorModifier ) ;
178
204
} catch ( ex ) {
179
205
if ( ex instanceof FeaturesNotSupported ) {
180
206
this . unsupported . add ( key ) ;
@@ -313,13 +339,13 @@ class DeviceHolder implements DeviceProvider {
313
339
static async create (
314
340
recorder : TestCaseRecorder ,
315
341
descriptor : CanonicalDeviceDescriptor | undefined ,
316
- descriptorModifierFn : DescriptorModifierFn | undefined
342
+ descriptorModifier : DescriptorModifier | undefined
317
343
) : Promise < DeviceHolder > {
318
344
const gpu = getGPU ( recorder ) ;
319
345
const adapter = await gpu . requestAdapter ( ) ;
320
346
assert ( adapter !== null , 'requestAdapter returned null' ) ;
321
- if ( descriptorModifierFn ) {
322
- descriptor = descriptorModifierFn ( adapter , descriptor ) ;
347
+ if ( descriptorModifier ) {
348
+ descriptor = descriptorModifier . descriptorModifier ( adapter , descriptor ) ;
323
349
}
324
350
if ( ! supportsFeature ( adapter , descriptor ) ) {
325
351
throw new FeaturesNotSupported ( 'One or more features are not supported' ) ;
0 commit comments