@@ -883,6 +883,22 @@ An [=adapter=] has the following internal slots:
883883
884884 Each adapter limit must be the same or [=limit/better=] than its default value
885885 in [=supported limits=] .
886+
887+ : <dfn>\[[current]]</dfn> , of type boolean
888+ ::
889+ Indicates whether the adapter is allowed to vend new devices at this time.
890+ Its value may change at any time.
891+
892+ It is initially set to `true` inside {{GPU/requestAdapter()}} .
893+ It becomes `false` inside "[=lose the device=] " and "[=mark adapters stale=] ".
894+ Once set to `false`, it cannot become `true` again.
895+
896+ Note:
897+ This mechanism ensures that various adapter-creation scenarios look similar to applications,
898+ so they can easily be robust to more scenarios with less testing: first initialization,
899+ reinitialization due to an unplugged adapter, reinitialization due to a test
900+ {{GPUDevice/destroy()|GPUDevice.destroy()}} call, etc. It also ensures applications use
901+ the latest system state to make decisions about which adapter to use.
886902</dl>
887903
888904[=Adapters=] are exposed via {{GPUAdapter}} .
@@ -894,7 +910,7 @@ through which [=internal objects=] are created.
894910It can be shared across multiple [=agents=] (e.g. dedicated workers).
895911
896912A [=device=] is the exclusive owner of all [=internal objects=] created from it:
897- when the [=device=] is lost, it and all objects created on it (directly, e.g.
913+ when the [=device=] is [=lose the device| lost=] , it and all objects created on it (directly, e.g.
898914{{GPUDevice/createTexture()}} , or indirectly, e.g. {{GPUTexture/createView()}} ) become
899915[=invalid=] .
900916
@@ -935,6 +951,22 @@ and adds extra `[[`/`]]` in spec text. Consider removing the brackets.
935951 member corresponding to |key| in |device|.{{device/[[limits]]}} to the value |value|.
936952</div>
937953
954+ Any time the user agent needs to revoke access to a device, it calls
955+ [=lose the device=] (device, `undefined`).
956+
957+ <div algorithm>
958+ To <dfn dfn>lose the device</dfn> (|device|, |reason|):
959+
960+ 1. Set |device|.{{device/[[adapter]]}} .{{adapter/[[current]]}} to `false`.
961+ 1. Issue: explain how to get from |device| to its "primary" {{GPUDevice}} .
962+ 1. Resolve {{GPUDevice/lost|GPUDevice.lost}} with a new {{GPUDeviceLostInfo}} with
963+ {{GPUDeviceLostInfo/reason}} set to |reason| and
964+ {{GPUDeviceLostInfo/message}} set to an implementation-defined value.
965+
966+ Note: {{GPUDeviceLostInfo/message}} should not disclose unnecessary user/system
967+ information and should never be parsed by applications.
968+ </div>
969+
938970[=Devices=] are exposed via {{GPUDevice}} .
939971
940972## Optional Capabilities ## {#optional-capabilities}
@@ -1225,12 +1257,13 @@ interface GPU {
12251257 1. Let |promise| be [=a new promise=] .
12261258 1. Issue the following steps on the [=Device timeline=] of |this|:
12271259 <div class=device-timeline>
1228- 1. If the user agent chooses to return an adapter:
1260+ 1. If the user agent chooses to return an adapter, it should :
12291261
1230- 1. The user agent chooses an [=adapter=] |adapter| according to the rules in
1262+ 1. Create an [=adapter=] |adapter| with {{adapter/[[current]]}} set to `true`,
1263+ chosen according to the rules in
12311264 [[#adapter-selection]] and the criteria in |options|.
12321265
1233- 1. |promise| [=resolves=] with a new {{GPUAdapter}} encapsulating |adapter|.
1266+ 1. [=Resolve=] |promise| with a new {{GPUAdapter}} encapsulating |adapter|.
12341267
12351268 1. Otherwise, |promise| [=resolves=] with `null`.
12361269 </div>
@@ -1241,6 +1274,38 @@ interface GPU {
12411274 </div>
12421275</dl>
12431276
1277+ {{GPU}} has the following internal slots:
1278+
1279+ <dl dfn-type=attribute dfn-for=GPU>
1280+ : <dfn>\[[previously_returned_adapters]]</dfn> , of type [=ordered set=] <[=adapter=] >
1281+ ::
1282+ The set of [=adapters=] that have been returned via {{GPU/requestAdapter()}} .
1283+ It is used, then cleared, in [=mark adapters stale=] .
1284+ </dl>
1285+
1286+ Upon any change in the system's state that could affect the result of any {{GPU/requestAdapter()}}
1287+ call, the user agent *should* [=mark adapters stale=] . For example:
1288+
1289+ - A physical adapter is added/removed (via plug, driver update, TDR, etc.)
1290+ - The system's power configuration has changed (laptop unplugged, power settings changed, etc.)
1291+
1292+ Additionally, [=mark adapters stale=] may by scheduled at any time.
1293+ User agents may choose to do this often even when there has been no system state change (e.g.
1294+ several seconds after the last call to {{GPUAdapter/requestDevice()}} .
1295+ This has no effect on well-formed applications, obfuscates real system state changes, and makes
1296+ developers more aware that calling {{GPU/requestAdapter()}} again is always necessary before
1297+ calling {{GPUAdapter/requestDevice()}} .
1298+
1299+ <div algorithm>
1300+ To <dfn dfn>mark adapters stale</dfn> :
1301+
1302+ 1. For each |adapter| in `navigator.gpu.`{{GPU/[[previously_returned_adapters]]}} :
1303+ 1. Set |adapter|.{{GPUAdapter/[[adapter]]}} .{{adapter/[[current]]}} to `false`.
1304+ 1. [=list/Empty=] `navigator.gpu.`{{GPU/[[previously_returned_adapters]]}} .
1305+
1306+ Issue: Update here if an `adaptersadded`/`adapterschanged` event is introduced.
1307+ </div>
1308+
12441309<div class="example">
12451310 Request a {{GPUAdapter}} :
12461311 <pre highlight="js">
@@ -1408,16 +1473,22 @@ interface GPUAdapter {
14081473 |adapter|.{{adapter/[[limits]]}} .
14091474 </div>
14101475
1411- 1. If the user agent cannot fulfill the request:
1476+ 1. If |adapter|.{{adapter/[[current]]}} is `false`,
1477+ or the user agent otherwise cannot fulfill the request:
1478+
1479+ 1. Let |device| be a new [=device=] .
1480+ 1. [=Lose the device=] (|device|, `undefined`).
14121481
1413- 1. Let |device| be a new {{GPUDevice}} object which has
1414- {{GPUDevice/lost|GPUDevice.lost}} resolved with a {{GPUDeviceLostInfo}}
1415- with {{GPUDeviceLostInfo/reason}} `undefined` and an
1416- implementation-defined {{GPUDeviceLostInfo/message}} .
1482+ Note:
1483+ This makes |adapter|.{{adapter/[[current]]}} `false`, if it wasn't already.
14171484
1418- Issue: Probably centralize this better with other device loss triggering, once added.
1485+ Note:
1486+ User agents should consider issuing developer-visible warnings in
1487+ most or all cases when this occurs. Applications should perform
1488+ reinitialization logic starting with {{GPU/requestAdapter()}} .
14191489
1420- 1. [=Resolve=] |promise| with |device| and stop.
1490+ 1. [=Resolve=] |promise| with a new {{GPUDevice}} encapsulating |device|,
1491+ and stop.
14211492
14221493 1. [=Resolve=] |promise| with a new {{GPUDevice}} object encapsulating
14231494 [=a new device=] with the capabilities described by |descriptor|.
@@ -1548,24 +1619,19 @@ Those not defined here are defined elsewhere in this document.
15481619<dl dfn-type=method dfn-for=GPUDevice>
15491620 : <dfn>destroy()</dfn>
15501621 ::
1551- Destroys the [=device=] .
1622+ Destroys the [=device=] , preventing further operations on it.
1623+ Outstanding asynchronous operations will fail.
15521624
15531625 <div algorithm=GPUDevice.destroy()>
15541626 **Called on:** {{GPUDevice}} |this|.
15551627
1556- 1. Make |this|.{{GPUDevice/[[device]]}} [=invalid=] .
1557- 1. Resolve {{GPUDevice/lost}} , on every {{GPUDevice}} associated with
1558- |this|.{{GPUDevice/[[device]]}} , with a {{GPUDeviceLostInfo}} with
1559- {{GPUDeviceLostInfo/reason}} {{GPUDeviceLostReason/"destroyed"}}
1560- and an implementation-defined {{GPUDeviceLostInfo/message}} .
1561-
1562- Issue: Probably centralize this better with other device loss triggering, once added.
1628+ 1. [=Lose the device=] (|this|.{{GPUDevice/[[device]]}} ,
1629+ {{GPUDeviceLostReason/"destroyed"}} ).
15631630 </div>
15641631
15651632 Note:
1566- This prevents any further operations on the device.
1567- Implementations can free resource allocations immediately.
1568- Outstanding asynchronous operations will fail, so implementations can abort them early.
1633+ Since no further operations can occur on this device, implementations can free resource
1634+ allocations and abort outstanding asynchronous operations immediately.
15691635</dl>
15701636
15711637{{GPUDevice}} objects are [=serializable objects=] .
0 commit comments