Skip to content

Commit

Permalink
Make requestDevice not return null (gpuweb#1465)
Browse files Browse the repository at this point in the history
`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.
  • Loading branch information
kainino0x authored Mar 1, 2021
1 parent 25bbe6f commit 3259bce
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 10 deletions.
12 changes: 6 additions & 6 deletions design/ErrorHandling.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand All @@ -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) => {
Expand Down Expand Up @@ -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
Expand Down
16 changes: 12 additions & 4 deletions spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ interface GPUAdapter {
[SameObject] readonly attribute GPUAdapterFeatures features;
[SameObject] readonly attribute GPUAdapterLimits limits;

Promise<GPUDevice?> requestDevice(optional GPUDeviceDescriptor descriptor = {});
Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
};
</script>

Expand Down Expand Up @@ -1402,10 +1402,18 @@ interface GPUAdapter {
|adapter|.{{adapter/[[limits]]}}.
</div>

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|.
</div>
1. Return |promise|.
Expand Down

0 comments on commit 3259bce

Please sign in to comment.