From 3259bce4e21003cd6398d33c644c0306c5ef75f9 Mon Sep 17 00:00:00 2001 From: Kai Ninomiya Date: Mon, 1 Mar 2021 14:03:25 -0800 Subject: [PATCH] Make requestDevice not return null (#1465) `requestDevice` returning null simply means "the UA couldn't do it for some reason". There's no reason this should be distinguishable from device loss, as it's essentially the same as the device being lost "at the last moment" just before it's returned. --- design/ErrorHandling.md | 12 ++++++------ spec/index.bs | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/design/ErrorHandling.md b/design/ErrorHandling.md index 263665ba0a..c041c71be3 100644 --- a/design/ErrorHandling.md +++ b/design/ErrorHandling.md @@ -58,7 +58,8 @@ It returns a Promise which resolves when a device is ready. The Promise may not resolve for a long time - for example, even if the adapter is still valid, the browser could delay until a background tab is foregrounded, to make sure that system resources are conserved until then. -If the adapter is lost and therefore unable to create a device, `requestDevice()` returns null. +If the adapter is lost and therefore unable to create a device, `requestDevice()` +returns an already-lost device. If the `descriptor` is invalid (e.g. it exceeds the limits of the adapter), `requestDevice()` rejects. The `GPUDevice` may be lost if something goes fatally wrong on the device @@ -71,8 +72,7 @@ The device and all objects created from the device have become invalid. All further operations on the device and its objects are errors. The `"validationerror"` event will no longer fire. (This makes all further operations no-ops.) -An app should never give up on getting WebGPU access due to -`requestDevice` returning `null` or `GPUDevice.lost` resolving. +An app should never give up on getting WebGPU access due to `GPUDevice.lost` resolving. Instead of giving up, the app should try again starting with `requestAdapter`. It *should* give up based on a `requestAdapter` returning `null` or rejecting. @@ -117,6 +117,7 @@ class MyRenderer { // ... Upload resources, etc. return true; } + // TODO: This example should not retry on the current adapter, it should get a new adapter. async tryEnsureDeviceOnCurrentAdapter() { // If no adapter, get one. // If we can't, rejects and the app falls back. @@ -129,10 +130,8 @@ class MyRenderer { } // Try to get a device. - // null => try new adapter // rejection => options were invalid (app programming error) this.device = await this.adapter.requestDevice({ /* options */ }); - if (!this.device) return; // When the device is lost, just try to get a device again. device.lost.then((info) => { @@ -197,7 +196,8 @@ All devices and adapters are lost (except for software?) because GPU access has WebGPU access has been disabled for the page. - `requestAdapter` returns null (or a software adapter). -The device is lost right as it's being returned by requestDevice. +The device is lost right as it's being returned by requestDevice, or otherwise couldn't be +created due to non-deterministic/internal reasons. - `device.lost` resolves. ## Operation Errors and Internal Nullability diff --git a/spec/index.bs b/spec/index.bs index 07b03e6b34..ffd5b76ead 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1331,7 +1331,7 @@ interface GPUAdapter { [SameObject] readonly attribute GPUAdapterFeatures features; [SameObject] readonly attribute GPUAdapterLimits limits; - Promise requestDevice(optional GPUDeviceDescriptor descriptor = {}); + Promise requestDevice(optional GPUDeviceDescriptor descriptor = {}); }; @@ -1402,10 +1402,18 @@ interface GPUAdapter { |adapter|.{{adapter/[[limits]]}}. - 1. If the user agent cannot fulfill the request, - [=resolve=] |promise| to `null` and stop. + 1. If the user agent cannot fulfill the request: - 1. [=Resolve=] |promise| to a new {{GPUDevice}} object encapsulating + 1. Let |device| be a new {{GPUDevice}} object which has + {{GPUDevice/lost|GPUDevice.lost}} resolved with a {{GPUDeviceLostInfo}} + with {{GPUDeviceLostInfo/reason}} `undefined` and an + implementation-defined {{GPUDeviceLostInfo/message}}. + + Issue: Probably centralize this better with other device loss triggering, once added. + + 1. [=Resolve=] |promise| with |device| and stop. + + 1. [=Resolve=] |promise| with a new {{GPUDevice}} object encapsulating [=a new device=] with the capabilities described by |descriptor|. 1. Return |promise|.