Skip to content
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

Only start WebGPU thread if an adapter is requested #25030

Merged
merged 2 commits into from Jan 13, 2020

Conversation

@zakorgy
Copy link
Contributor

zakorgy commented Dec 3, 2019

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


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • These changes fix #___ (GitHub issue number if applicable)

This change is Reviewable

@highfive
Copy link

highfive commented Dec 3, 2019

Heads up! This PR modifies the following files:

  • @asajeffrey: components/constellation/constellation.rs, components/script/dom/bindings/trace.rs, components/script/dom/window.rs, components/script/dom/gpu.rs
  • @cbrewster: components/constellation/constellation.rs
  • @KiChjang: components/script_traits/script_msg.rs, components/script/dom/bindings/trace.rs, components/script/dom/window.rs, components/script/dom/gpu.rs
@highfive
Copy link

highfive commented Dec 3, 2019

warning Warning warning

  • These commits modify script code, but no tests are modified. Please consider adding a test!
@@ -1945,6 +1945,12 @@ where
EmbedderMsg::MediaSessionEvent(event),
));
},
FromScriptMsg::StartWebGPU(sender) => {
self.webgpu = WebGPU::new();

This comment has been minimized.

Copy link
@gterzian

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:

  1. Do you want to allow multiple DOM GPU to share a WebGPU at the same time? Is so, how would they be shared(one webgpu shared across the browser, one shared per origin, per agent-cluster?). Then the StartWebGPU would need to include information so that you can either clone an existing one, or start a new one.
  2. Do you want to allow multiple parallel WebGPU at 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.

Copy link
@kvark

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.

Copy link
@gterzian

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

pub fn spawn<Message, LTF, STF>(state: InitialPipelineState) -> Result<NewPipeline, Error>

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:

  1. As suggested in the other comment, make requesting an adapater a ScriptMsg.
  2. When you receive it:
    • get the corresponding pipeline
    • get the top-level browsing context for that pipeline.
    • get the host for that pipeline.
  3. The above info should be enough to then grab the right webgpu instance, or create it.
  4. I would suggest you store them on a HashMap<Host, WebGPU> inside a BrowsingContextGroup, similarly to what is done with EventLoop.
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.

Copy link
@gterzian

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

  1. Start a webgpu if needed,
  2. forward the RequestAdapter call.

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.

@jdm jdm assigned gterzian and unassigned SimonSapin Dec 4, 2019
@zakorgy
Copy link
Contributor Author

zakorgy commented Dec 5, 2019

@gterzian @kvark thanks for the well detailed descriptions, I will update my PR according to what you described.

@bors-servo
Copy link
Contributor

bors-servo commented Dec 5, 2019

The latest upstream changes (presumably #25029) made this pull request unmergeable. Please resolve the merge conflicts.

@gterzian gterzian mentioned this pull request Dec 15, 2019
3 of 3 tasks complete
@zakorgy zakorgy force-pushed the szeged:webgpu-constellation branch 2 times, most recently from ea1f917 to c023e0c Jan 9, 2020
@zakorgy
Copy link
Contributor Author

zakorgy commented Jan 9, 2020

@gterzian @kvark it took me some time but finally updated the PR to use the solution described in #25030 (comment).

@zakorgy zakorgy force-pushed the szeged:webgpu-constellation branch from c023e0c to 4ae3c8b Jan 9, 2020
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.

Copy link
@jdm

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.

@jdm jdm added S-fails-tidy and removed S-needs-rebase labels Jan 9, 2020
Copy link
Member

gterzian left a comment

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:

  1. Do we need the Option<WebGPU> in WebGPUResponse::RequestAdapter? Could we make sending back the channel non-optional(It doesn't seem to be about conveying failure to create an adapter)?
  2. I would like to try to get rid of window.wegbu_channel and window.set_webgpu_channel. Instead, you could store the channel on the GPUAdapter directly, when you handle WebGPUResponse::RequestAdapter. Then, when the adapter creates a device, it could simply clone it's channel and store it directly on the device when handling the WebGPUResponse::RequestDevice(and the device could clone it's own sender when creating a buffer, and so on, without having to go through the window everytime)
@zakorgy zakorgy requested a review from gterzian Jan 9, 2020
@zakorgy zakorgy force-pushed the szeged:webgpu-constellation branch from 4ae3c8b to 4a72a2c Jan 9, 2020
@zakorgy
Copy link
Contributor Author

zakorgy commented Jan 9, 2020

@gterzian those changes sounds doable for me. I will start adding them.

@zakorgy zakorgy force-pushed the szeged:webgpu-constellation branch from 4a72a2c to 71d5f8b Jan 9, 2020
@zakorgy
Copy link
Contributor Author

zakorgy commented Jan 9, 2020

@gterzian I've addressed your requested changes, could you please take a look now?

Copy link
Member

gterzian left a comment

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.

Copy link
@gterzian

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.

Copy link
@zakorgy

zakorgy Jan 10, 2020

Author Contributor

I think yes. Updated the code according to that.

@gterzian gterzian removed the S-fails-tidy label Jan 10, 2020
@zakorgy zakorgy force-pushed the szeged:webgpu-constellation branch from 71d5f8b to 3740754 Jan 10, 2020
Copy link
Member

gterzian left a comment

Ok looks good, just a few last suggestions.

.flatten();

for receiver in receivers {
if let Some(rec) = receiver {

This comment has been minimized.

Copy link
@gterzian

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.

Copy link
@gterzian

gterzian Jan 11, 2020

Member

Perhaps use WebGPU instead?

.send(WebGPURequest::RequestDevice(sender, self.adapter, desc, id))
.is_err()
{
promise.reject_error(Error::Type(

This comment has been minimized.

Copy link
@gterzian

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.

Copy link
@gterzian

gterzian Jan 11, 2020

Member

Error::Operation

id,
wgpu_descriptor,
))
.unwrap();

This comment has been minimized.

Copy link
@gterzian

gterzian Jan 11, 2020

Member

expect("Failed to create WebGPU buffer")

id,
wgpu_descriptor.clone(),
))
.unwrap()

This comment has been minimized.

Copy link
@gterzian

gterzian Jan 11, 2020

Member

expect

@zakorgy zakorgy force-pushed the szeged:webgpu-constellation branch from 3740754 to 430248e Jan 13, 2020
@zakorgy
Copy link
Contributor Author

zakorgy commented Jan 13, 2020

@gterzian updated the PR with your proposed changes, also added a separate commit where I've addressed #25492

@gterzian
Copy link
Member

gterzian commented Jan 13, 2020

FIX #25492

Great job!

@bors-servo r+

@bors-servo
Copy link
Contributor

bors-servo commented Jan 13, 2020

📌 Commit 430248e has been approved by gterzian

@zakorgy
Copy link
Contributor Author

zakorgy commented Jan 13, 2020

@gterzian thanks for the guidance and the valuable information about Servo infrastructure.

@bors-servo
Copy link
Contributor

bors-servo commented Jan 13, 2020

Testing commit 430248e with merge 81e4f17...

bors-servo added a commit that referenced this pull request Jan 13, 2020
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
Copy link
Contributor

bors-servo commented Jan 13, 2020

💔 Test failed - status-taskcluster

@jdm
Copy link
Member

jdm commented Jan 13, 2020

@bors-servo
Copy link
Contributor

bors-servo commented Jan 13, 2020

Testing commit 430248e with merge c1e1dea...

bors-servo added a commit that referenced this pull request Jan 13, 2020
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
Copy link
Contributor

bors-servo commented Jan 13, 2020

💔 Test failed - status-taskcluster

@jdm
Copy link
Member

jdm commented Jan 13, 2020

bors-servo added a commit that referenced this pull request Jan 13, 2020
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
Copy link
Contributor

bors-servo commented Jan 13, 2020

Testing commit 430248e with merge 0131952...

@bors-servo
Copy link
Contributor

bors-servo commented Jan 13, 2020

☀️ Test successful - status-taskcluster
Approved by: gterzian
Pushing 0131952 to master...

@bors-servo bors-servo merged commit 430248e into servo:master Jan 13, 2020
2 checks passed
2 checks passed
Community-TC (pull_request) TaskGroup: success
Details
homu Test successful
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

7 participants
You can’t perform that action at this time.