-
Notifications
You must be signed in to change notification settings - Fork 335
Pluralize requestAdapters and adjacent changes #524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
spec/index.bs
Outdated
interface GPU { | ||
// May reject with DOMException // TODO: DOMException("OperationError")? | ||
Promise<GPUAdapter> requestAdapter(optional GPURequestAdapterOptions options = {}); | ||
Promise<sequence<GPUAdapter>> requestAdapters(optional GPURequestAdapterOptions options = {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I kinda like the idea you surfaced internally of having a Promise<GPUAdapterList>
that's on GPU
and contains the gpuadapterschanged
event and that you could query synchronously for adapters. It makes sense: the system or GPU process can continuously push updates to this object so only its initial creation needs to be asynchronous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decided against this, but given #522 (comment) I will look into it again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so the problem with GPUAdapterList is there's no way to signal to the application (e.g. in a background tab): "I can't give you an adapter yet, but I probably will, so don't fallback yet".
Haven't yet come up with a better way to do that, but still working through it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alternatives:
gpu { adapterList { getAdapters(), onadapteradded } }
. adapterList can get 'revoked' and replaced with a new, pending promise to indicate this state. Problems: no signal for when adapterList goes from rejected (app should use fallback) to pending (app should consider initializing webgpu), because onadapteradded is basically deregistered on adapterList replacement. Would need a separate one.gpu { onadapteradded, adapterList { getAdapters() } }
. adapterList can get 'revoked'. onadapteradded indicates a signal to await and probe the adapterList (regardless of whether the app is already using webgpu or whether the adapterList got replaced). Problem: basically the same asgpu { onadapteradded, requestAdapters() }
but more complex.
So, I still prefer gpu.requestAdapters.
spec/index.bs
Outdated
readonly attribute DOMString name; | ||
readonly attribute sequence<GPUExtensionName> extensions; | ||
//readonly attribute GPULimits limits; Don't expose higher limits for now. | ||
readonly attribute boolean hasMajorPerformanceCaveat; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about having the powerPreference too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I want to avoid letting applications hard-filter on powerPreference, but it's a possibility.
spec/index.bs
Outdated
available adapters. | ||
|
||
If unspecified, the user agent decides which class of adapter is most suitable. | ||
Provides a hint indicating what class of [=adapter=] should be preferred. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IDK that having a hint helps, if we have the GPUAdapterList
then maybe we can just return all the adapters the application can query and let them decide which one they want to use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as we always return low power adapters first, I suppose this would work. It would mean apps looking for the high performance gpu would have some fairly complex logic to find it though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not that bad I guess:
for (const adapter of adapters) {
if (adapter.powerProfile === 'high-performance') {
return adapter;
}
}
return adapters[0];
This was discussed in the 2020-01-06 meeting |
1eaa910
to
2471512
Compare
Rebased. |
+Jeff +Myles for review, if you'd like to. This is approximately the "most minimal"/"least committal" version of this change which I think we were OK with in the meeting. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have some concerns with this approach. Consider the following situation:
- One browser chooses to return every adapter from every call to
requestAdapters()
, albeit with different orderings. - Another browser chooses to only ever return at most one adapter from each call to
requestAdapters()
, in order to combat fingerprinting.
A developer using the first browser writes a website which uses WebGPU. This developer calls requestAdapters()
with some arbitrary GPURequestAdapterOptions
. They get back a list of every adapter, and they iterate through the list, looking for one which suits their purposes. If the developer doesn't find what they are looking for, they may think the correct thing for them to do is give up, and tell the user to navigate to a different website.
However, when running on the second browser, the correct thing to do is to call requestAdapters()
again with different arguments. If they don't do this, their website would appear not to work in the second browser, despite the existence of an adapter which satisfies their desires.
What I'm trying to say in #524 (review) is that allowing for these kinds of divergent behaviors among user agents would be unfortunate. |
The OP lists a few benefits of
It is, because the UA may choose to expose different devices depending on what type of requests the website makes.
In the second browser described in #524 (review), they would still need that pattern
Electron and Node can include their own device creation functions; they include plenty of non-standard functions. |
It allows the browser to expose more fingerprinting info. It does not require it, therefore fingerprinting does not preclude us from using this design.
If it's possible to get more info by calling it again, the browser should have returned the full info the first time around. Anything else is confusing without, IMO, solving any problems.
And yet if the standard Web API matched their needs, they could use it. For instance, this would Babylon.js would work unmodified inside of any Electron app. |
It does not allow a browser to selectively respond with certain devices depending on what the webpage asked for.
Confusing perhaps, but better for fingerprinting. Protecting our users' privacy is more important than developers' confusion.
They can use whatever device discovery API the CG creates, just like any website can. The fact that there is some context where privacy is less important than the open web is irrelevant. I'm sure there will be some intranet somewhere which uniquely identifies each user upon login and which uses WebGPU; that doesn't mean the WebGPU API can entirely ignore privacy in its design. Regardless of what the spec says, if the default way of using the API will cause Chrome to return a list of every adapter on the system, that's a problem for any browser which has stricter privacy requirements than Chrome. |
@litherum wrote:
This will/would also be a problem even for Chrome, in a possible future where it ships the Privacy Budget proposal. Calling this once would blow your budget. |
FTR: All of this was brought up in the last meeting and it was agreed we needed to think more about this. Myles: thank you for recording the details here. Beyond that, let's please hold off on further discussion unless there are specific proposals on how to fix this. It is not helpful to pile on arguments against something we already have agreed is wrong. |
I guess I will close this to avoid fruitless discussions no one is prepared for. |
I want to talk about this more. Shall I open a new PR of my own, or reopen this one? |
If you think this PR is good as it stands, please reopen. If you have an alternative or tweaks, maybe a new one would be best. Up to you. |
The issue seems to be with preserving browser k-anonimity security policies (to avoid fingerprinting user hardware). If the requestAdapter returned a single list representing the union of all the features/extensions available on all the devices in a system (rather than a specific list per device), then users could request any of these devices by feature/extension. Requested devices would not then be required to return their specific feature/extension list, and the level of k-anonimity would be preserved. In the case there are multiple devices that could fullfill a given user request for features/extensions, the least busy could be returned. This would allow loading all the devices that match the requested features/extensions (make one busy, request another, always returning a device to avoid revealing the number of devices). @kainino0x suggested clamping could be implemented in-browser to avoid additional fingerprinting, but if the returned devices do not reveal their unique features/extensions, then this would not affect k-anonimity. Requires further baking: |
It wouldn't be possible to create devices with certain combinations of extensions/limits. For example take adapter A that has EXT_ONE and adapter B that has EXT_TWO. requestDevice would not be able to succeed if you asked for both. So the API would become unpredictable, and the info could be extracted by repeatedly calling requestDevice. |
The API would not be any less predictable or secure than just returning a fingerprint of a specific device (as it does now - actually two - low and high power). The point is to avoid reducing k-anonimity, or even improve it if possible. Others have pointed out this information can already be gleaned elsewhere, so as long as the API does not reveal anything above that, the level of k-anonimity would at least be preserved. I kind of like the idea of algo-based wish-lists/hints (without revealing lists of available specific device features/extensions at all) - even with repeated requests, a profiler could still be left guessing as to the number of devices and their specific features/extensions (smudged/redacted fingerprints?) |
…vertex_count (gpuweb#524) Also adds an `indirect` parameter to primitive_topology:basic
We made requestAdapter singular due to fingerprinting concerns, IIRC.
requestAdapters
is not any more prone to fingerprinting. The UA can choose to put whichever adapters it wants in the list. Any adapters returned from it could have been found by searching the space of possiblerequestAdapter
calls.requestAdapters
still allows an easy default: e.g. ask for"low-power"
, then get adapter[0]
.requestAdapter
is hostile to any situation where the UA does want to give a little more trust to the app, perhaps Electron, Node, or even installed PWAs.Finally, adds(EDIT: will figure out later)hasMajorPerformanceCaveat
as one thing that pluralizingrequestAdapters
enables simply.Preview | Diff