Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

kainino0x
Copy link
Contributor

@kainino0x kainino0x commented Dec 17, 2019

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 possible requestAdapter calls.
  • Many applications would end up trying to get every adapter they can find (by searching the space ...) and then using their own logic to pick among them. This prevents apps from needing that pattern.
  • 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 hasMajorPerformanceCaveat as one thing that pluralizing requestAdapters enables simply. (EDIT: will figure out later)


Preview | Diff

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 = {});
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

@kainino0x kainino0x Dec 21, 2019

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 as gpu { 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;
Copy link
Contributor

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?

Copy link
Contributor Author

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.
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

@kainino0x kainino0x Dec 21, 2019

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];

@kainino0x kainino0x mentioned this pull request Dec 18, 2019
@Kangz
Copy link
Contributor

Kangz commented Jan 6, 2020

This was discussed in the 2020-01-06 meeting

@kainino0x
Copy link
Contributor Author

Rebased.

@kainino0x kainino0x requested review from kdashg and litherum January 13, 2020 22:55
@kainino0x
Copy link
Contributor Author

+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.

Copy link
Contributor

@litherum litherum left a 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.

@litherum
Copy link
Contributor

litherum commented Jan 14, 2020

What I'm trying to say in #524 (review) is that allowing for these kinds of divergent behaviors among user agents would be unfortunate.

@litherum
Copy link
Contributor

The OP lists a few benefits of requestAdapters() that are worth responding to:

requestAdapters is not any more prone to fingerprinting

It is, because the UA may choose to expose different devices depending on what type of requests the website makes.

Many applications would end up trying to get every adapter they can find ... This prevents apps from needing that pattern.

In the second browser described in #524 (review), they would still need that pattern

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.

Electron and Node can include their own device creation functions; they include plenty of non-standard functions.

@kainino0x
Copy link
Contributor Author

It is, because the UA may choose to expose different devices depending on what type of requests the website makes.

It allows the browser to expose more fingerprinting info. It does not require it, therefore fingerprinting does not preclude us from using this design.

In the second browser described in #524 (review), they would still need that pattern

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.
If privacy budgets become a concern, all we have to do is add a way for sites to use minimal budget on creating adapters (e.g. requestDefaultAdapter or requestDefaultDevice).

Electron and Node can include their own device creation functions; they include plenty of non-standard functions.

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.

@litherum
Copy link
Contributor

@kainino0x

It does not require it

It does not allow a browser to selectively respond with certain devices depending on what the webpage asked for.

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.

Confusing perhaps, but better for fingerprinting. Protecting our users' privacy is more important than developers' confusion.

And yet if the standard Web API matched their needs, they could use it.

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.

@hober
Copy link

hober commented Jan 22, 2020

@litherum wrote:

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.

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.

@kainino0x
Copy link
Contributor Author

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.

@kainino0x
Copy link
Contributor Author

I guess I will close this to avoid fruitless discussions no one is prepared for.

@kainino0x kainino0x closed this Jan 22, 2020
@kdashg
Copy link
Contributor

kdashg commented Jan 22, 2020

I want to talk about this more. Shall I open a new PR of my own, or reopen this one?

@kainino0x
Copy link
Contributor Author

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.

@dcerisano
Copy link

dcerisano commented Jul 7, 2020

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:
A multiGPU load balancing algo could be designed to manage this 'under the hood'. Users could just give a wish list of features/extensions requests for a device, and the algo would simply 'do its best' to fullfill and balance the requests, without needing to know what features/extensions are actually extant on the host.

@kainino0x
Copy link
Contributor Author

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.

@dcerisano
Copy link

dcerisano commented Jul 7, 2020

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?)

ben-clayton pushed a commit to ben-clayton/gpuweb that referenced this pull request Sep 6, 2022
…vertex_count (gpuweb#524)

Also adds an `indirect` parameter to primitive_topology:basic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants