From 3382e0d3a0afbc2adc4523727d134705a3f9bd5c Mon Sep 17 00:00:00 2001 From: Kai Ninomiya Date: Fri, 3 Nov 2023 14:58:17 -0700 Subject: [PATCH] Test errors for out-of-range limit requests (#3132) See https://crbug.com/1499030 --- .../operation/adapter/requestDevice.spec.ts | 59 +++++++++++++++++++ src/webgpu/listing_meta.json | 1 + src/webgpu/util/math.ts | 1 + 3 files changed, 61 insertions(+) diff --git a/src/webgpu/api/operation/adapter/requestDevice.spec.ts b/src/webgpu/api/operation/adapter/requestDevice.spec.ts index 314da6356eb7..51ab2303eb7f 100644 --- a/src/webgpu/api/operation/adapter/requestDevice.spec.ts +++ b/src/webgpu/api/operation/adapter/requestDevice.spec.ts @@ -311,6 +311,65 @@ g.test('limit,better_than_supported') t.shouldReject('OperationError', adapter.requestDevice({ requiredLimits })); }); +g.test('limit,out_of_range') + .desc( + ` + Test that specifying limits that are out of range (<0, >MAX_SAFE_INTEGER, >2**31-2 for 32-bit + limits, =0 for alignment limits) produce the appropriate error (TypeError or OperationError). + ` + ) + .params(u => + u + .combine('limit', kLimits) + .beginSubcases() + .expand('value', function* () { + yield -(2 ** 64); + yield Number.MIN_SAFE_INTEGER - 3; + yield Number.MIN_SAFE_INTEGER - 1; + yield Number.MIN_SAFE_INTEGER; + yield -(2 ** 32); + yield -1; + yield 0; + yield 2 ** 32 - 2; + yield 2 ** 32 - 1; + yield 2 ** 32; + yield 2 ** 32 + 1; + yield 2 ** 32 + 2; + yield Number.MAX_SAFE_INTEGER; + yield Number.MAX_SAFE_INTEGER + 1; + yield Number.MAX_SAFE_INTEGER + 3; + yield 2 ** 64; + yield Number.MAX_VALUE; + }) + ) + .fn(async t => { + const { limit, value } = t.params; + + const gpu = getGPU(t.rec); + const adapter = await gpu.requestAdapter(); + assert(adapter !== null); + const limitInfo = getDefaultLimitsForAdapter(adapter)[limit]; + + const requiredLimits = { + [limit]: value, + }; + + const errorName = + value < 0 || value > Number.MAX_SAFE_INTEGER + ? 'TypeError' + : limitInfo.class === 'maximum' && value > adapter.limits[limit] + ? 'OperationError' + : limitInfo.class === 'alignment' && (value > 2 ** 31 || !isPowerOfTwo(value)) + ? 'OperationError' + : false; + + if (errorName) { + t.shouldReject(errorName, adapter.requestDevice({ requiredLimits })); + } else { + await adapter.requestDevice({ requiredLimits }); + } + }); + g.test('limit,worse_than_default') .desc( ` diff --git a/src/webgpu/listing_meta.json b/src/webgpu/listing_meta.json index f9caeefc6ee1..b060b85e0726 100644 --- a/src/webgpu/listing_meta.json +++ b/src/webgpu/listing_meta.json @@ -9,6 +9,7 @@ "webgpu:api,operation,adapter,requestDevice:features,unknown:*": { "subcaseMS": 13.600 }, "webgpu:api,operation,adapter,requestDevice:invalid:*": { "subcaseMS": 27.801 }, "webgpu:api,operation,adapter,requestDevice:limit,better_than_supported:*": { "subcaseMS": 3.614 }, + "webgpu:api,operation,adapter,requestDevice:limit,out_of_range:*": { "subcaseMS": 1.000 }, "webgpu:api,operation,adapter,requestDevice:limit,worse_than_default:*": { "subcaseMS": 6.711 }, "webgpu:api,operation,adapter,requestDevice:limits,supported:*": { "subcaseMS": 4.579 }, "webgpu:api,operation,adapter,requestDevice:limits,unknown:*": { "subcaseMS": 0.601 }, diff --git a/src/webgpu/util/math.ts b/src/webgpu/util/math.ts index 851db40c7157..0fbe390856d4 100644 --- a/src/webgpu/util/math.ts +++ b/src/webgpu/util/math.ts @@ -2056,6 +2056,7 @@ export function isPowerOfTwo(n: number): boolean { if (!Number.isInteger(n)) { return false; } + assert((n | 0) === n, 'isPowerOfTwo only supports 32-bit numbers'); return n !== 0 && (n & (n - 1)) === 0; }