Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upOnly start WebGPU thread if an adapter is requested #25030
Conversation
highfive
commented
Dec 3, 2019
|
Heads up! This PR modifies the following files:
|
highfive
commented
Dec 3, 2019
| @@ -1945,6 +1945,12 @@ where | |||
| EmbedderMsg::MediaSessionEvent(event), | |||
| )); | |||
| }, | |||
| FromScriptMsg::StartWebGPU(sender) => { | |||
| self.webgpu = WebGPU::new(); | |||
This comment has been minimized.
This comment has been minimized.
gterzian
Dec 3, 2019
•
Member
Even though you are tracking the webgpu_channel_requested flag inside the DOM GPU, multiple script-threads(EventLoop from the perspective of the constellation) could send this message, in which case you would be overwriting previously set self.webgpu(and running multiple gpu threads?).
Also, even within one script-thread, multiple windows could be running on it(see documents in ScriptThread, pipelines in the constellation), in which case I think you could also have multiple DOM GPU instances, each tracking their own webgpu_channel_requested flag.
So I think you need to decide:
- Do you want to allow multiple DOM
GPUto share aWebGPUat the same time? Is so, how would they be shared(one webgpu shared across the browser, one shared per origin, per agent-cluster?). Then theStartWebGPUwould need to include information so that you can either clone an existing one, or start a new one. - Do you want to allow multiple parallel
WebGPUat all? In that case, you would need a map with a key representing how an instance is shared, so that you could get it out here, clone the sender, or start a new one.
It's not clear to me from the spec how sharing should happen, although @kvark has previously said multiple parallel applications are wanted(although it's not clear if that means sharing a single webgpu, or running multiple ones, or a combination of that).
The easiest for now might be to simply share a single webgpu instance across the whole browser, in which case all you have to do here is to avoid overwriting an existing one.
This comment has been minimized.
This comment has been minimized.
kvark
Dec 3, 2019
Member
Yes, the choice of boundaries for separating WebGPU instances is still ours.
Here is how it works in Gecko, for the reference:
- each content process manages multiple tabs
- a single WebGPU remote client is established per content process
- it spawns a separate WebGPU server on the GPU process
- the IPC is a child of CompositorBridge and thus the server message loop is happening on a thread that this parent protocol manages (I assume it's a separate thread)
Does Servo have multiple content processes? I think we can start here by having the same approach - one WebGPU client-server pair per content process.
This comment has been minimized.
This comment has been minimized.
gterzian
Dec 4, 2019
•
Member
Yes so a content-process would correspond to a EventLoop in Servo(which is an interface for the constellation to communicate with the underlying ScriptThread that is running in another process). I'd say it maps to the spec concept of agent-cluster.
From the constellation's perspective a document corresponds to a Pipeline, of which multiple can run on one event-loop. Associated dedicated workers also run in the same "event-loop", although on their own thread, not the script-thread(they do have a pipeline id, which I think is the id of the document that started them, to be looked into).
When a pipeline is spawned, an event-loop is either created or re-used, see
servo/components/constellation/pipeline.rs
Line 219 in 6e3c131
The "re-using" of event-loops is done when a pipeline is part of the same BrowsingContextGroup, and based on the Host of the url of that pipeline, see get_event_loop.
So, this would actually be the first time something is shared like that on an "per-event-loop" basis, and you're going to have to provide some infra for this, because currently the constellation receives message from a given pipeline(see how each ScriptMsg comes with a PipelineID, representing the pipeline from which the message originated).
I think you could do something like:
- As suggested in the other comment, make requesting an adapater a
ScriptMsg. - When you receive it:
- get the corresponding pipeline
- get the top-level browsing context for that pipeline.
- get the host for that pipeline.
- The above info should be enough to then grab the right webgpu instance, or create it.
- I would suggest you store them on a
HashMap<Host, WebGPU>inside aBrowsingContextGroup, similarly to what is done withEventLoop.
| let (sender, receiver) = ipc::channel().unwrap(); | ||
| let script_to_constellation_chan = global.script_to_constellation_chan(); | ||
| if script_to_constellation_chan | ||
| .send(ScriptMsg::StartWebGPU(sender)) |
This comment has been minimized.
This comment has been minimized.
gterzian
Dec 3, 2019
•
Member
So I would say you could make the WebGPURequest::RequestAdapter into a ScriptMsg, and in RequestAdapter below just use the script_to_constellation_chan to send it to the constellation.
Then the constellation can
- Start a webgpu if needed,
- forward the
RequestAdaptercall.
And webgpu can then reply on a channel included in the RequestAdapter message with a webgpu_channel which can be stored in the adapter(so that it can communicate directly with webgpu going forward).
The main benefit is not blocking on the constellation reply inside the wgpu_channel call, instead making it non-blocking as the actual RequestAdapter call, where the reply eventually resolves via a promise.
You cold store the webgpu_channel somewhere besides the adapter, however it doesn't seem to have much benefit at this point(since the sole RequestAdapter method would always have to go through the constellation first). So it would only make sense to store it internally on the adapter, so that methods of it could send a message directly to webgpu without having to go through the constellation.
|
|
ea1f917
to
c023e0c
|
@gterzian @kvark it took me some time but finally updated the PR to use the solution described in #25030 (comment). |
| Some(browsing_context_group) => { | ||
| match browsing_context_group.webgpus.entry(host) { | ||
| Entry::Vacant(v) => { | ||
| let webgpu = v.insert(WebGPU::new().unwrap()); |
This comment has been minimized.
This comment has been minimized.
jdm
Jan 9, 2020
Member
Note: using unwrap in the constellation isn't allowed (and our CI catches it), so please turn this into an error! if it fails.
|
Ok, I think it looks very good, great work! Before I review everything in details, there are two small changes in the overall structure I would like to suggest:
|
|
@gterzian those changes sounds doable for me. I will start adding them. |
|
@gterzian I've addressed your requested changes, could you please take a look now? |
|
Ok it looks good to me. I have one small comment, and I'll take another read after it has been addressed. |
| @@ -16,7 +16,7 @@ use smallvec::SmallVec; | |||
|
|
|||
| #[derive(Debug, Deserialize, Serialize)] | |||
| pub enum WebGPUResponse { | |||
| RequestAdapter(String, WebGPUAdapter), | |||
| RequestAdapter(String, WebGPUAdapter, WebGPU), | |||
This comment has been minimized.
This comment has been minimized.
gterzian
Jan 10, 2020
•
Member
Could it make sense for the WGPU to keep a sender to itself, so that the constellation doesn't have to send it in the request?
This comment has been minimized.
This comment has been minimized.
|
Ok looks good, just a few last suggestions. |
| .flatten(); | ||
|
|
||
| for receiver in receivers { | ||
| if let Some(rec) = receiver { |
This comment has been minimized.
This comment has been minimized.
gterzian
Jan 11, 2020
Member
I think you can use filter_map on webgpus.values() above to filter out the None.
| @@ -28,6 +29,8 @@ use webgpu::{wgpu, WebGPUAdapter, WebGPURequest, WebGPUResponse}; | |||
| #[dom_struct] | |||
| pub struct GPUAdapter { | |||
| reflector_: Reflector, | |||
| #[ignore_malloc_size_of = "channels are hard"] | |||
| channel: IpcSender<WebGPURequest>, | |||
This comment has been minimized.
This comment has been minimized.
| .send(WebGPURequest::RequestDevice(sender, self.adapter, desc, id)) | ||
| .is_err() | ||
| { | ||
| promise.reject_error(Error::Type( |
This comment has been minimized.
This comment has been minimized.
gterzian
Jan 11, 2020
Member
They spec says to use Error::Operation https://gpuweb.github.io/gpuweb/#requestdevice
| { | ||
| promise.reject_error(Error::Type( | ||
| "Failed to send RequestDevice message...".to_owned(), | ||
| )); | ||
| } | ||
| } else { | ||
| promise.reject_error(Error::Type("No WebGPU thread...".to_owned())) |
This comment has been minimized.
This comment has been minimized.
| id, | ||
| wgpu_descriptor, | ||
| )) | ||
| .unwrap(); |
This comment has been minimized.
This comment has been minimized.
| id, | ||
| wgpu_descriptor.clone(), | ||
| )) | ||
| .unwrap() |
This comment has been minimized.
This comment has been minimized.
|
FIX #25492 Great job! @bors-servo r+ |
|
|
|
@gterzian thanks for the guidance and the valuable information about Servo infrastructure. |
Only start WebGPU thread if an adapter is requested <!-- Please describe your changes on the following line: --> This addresses 1 and 2 from #24706 (comment) We send a message to constellation instead of creating the `WebGPU` thread on the start. We send back the result to script and set the `Window`'s `web_gpu` component there. cc @jdm @imiklos --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #___ (GitHub issue number if applicable) <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/25030) <!-- Reviewable:end -->
|
|
|
@bors-servo retry |
Only start WebGPU thread if an adapter is requested <!-- Please describe your changes on the following line: --> This addresses 1 and 2 from #24706 (comment) We send a message to constellation instead of creating the `WebGPU` thread on the start. We send back the result to script and set the `Window`'s `web_gpu` component there. cc @jdm @imiklos --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #___ (GitHub issue number if applicable) <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/25030) <!-- Reviewable:end -->
|
|
|
@bors-servo retry |
Only start WebGPU thread if an adapter is requested <!-- Please describe your changes on the following line: --> This addresses 1 and 2 from #24706 (comment) We send a message to constellation instead of creating the `WebGPU` thread on the start. We send back the result to script and set the `Window`'s `web_gpu` component there. cc @jdm @imiklos --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #___ (GitHub issue number if applicable) <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/25030) <!-- Reviewable:end -->
|
|
zakorgy commentedDec 3, 2019
•
edited
This addresses 1 and 2 from #24706 (comment)
We send a message to constellation instead of creating the
WebGPUthread on the start. We send back the result to script and set theWindow'sweb_gpucomponent there.cc @jdm @imiklos
./mach build -ddoes not report any errors./mach test-tidydoes not report any errorsThis change is