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

Return queue_empty for Device::poll #2643

Merged
merged 3 commits into from
May 10, 2022
Merged

Conversation

xiaopengli89
Copy link
Contributor

Description

queue_empty can avoid unnecessary device polling.

@jimblandy
Copy link
Member

This is great - just half an hour ago, I was thinking about making this exact change.

The concern I ran into is this: if the device is shared between threads, another thread could submit a request immediately after your call to Device::poll returns and says the queue is empty. If you decide to stop polling, then futures of the new request will never get woken up.

If you could intercept all access to the Queue, then you could arrange to start polling again somehow, but it feels like an API that is easy to use incorrectly.

@jimblandy
Copy link
Member

There was some discussion about this in the matrix chat.

Assuming @xiaopengli89 and I are on the same page: the reason we want this feature is because we'd like to manage polling transparently, in a set-and-forget kind of way. We want to write buffer.map_async(Write).await, say, and have it Just Work, because of arrangements made earlier.

Further, we'd like to not do dumb things like the current Firefox code (for which I am responsible):

  mTimer.Start(base::TimeDelta::FromMilliseconds(POLL_TIME_MS), this,
               &WebGPUParent::MaintainDevices);

i.e., just poll every once in a while, from a timer.

Further, we don't want to follow the example of wgpu/wgpu/examples, which addresses the obligation to poll with an undocumented requirement that Example::render implementations must submit something to the queue; Queue::submit does one internal poll. This is no good for compute-only tasks, and it also imposes a one-frame minimum latency for requests that might be able to proceed much more quickly.

One solution, if we take this PR, would be to protect all access to the Queue with a mutex and condvar, and have a helper thread that wakes up when work is submitted and calls poll(Wait) until the queue is empty. Every operation that could submit new work to the queue would need to acquire the mutex and signal the condvar.

The downsides to this are:

  • It's awkward because Queue has several useful methods, and each of them needs to be wrapped and forwarded individually.

  • The API is easy to misuse. It takes some careful attention to avoid missing wakeups, and getting it wrong will lead to intermittent bugs. This seems like the wrong thing to leave to users to sort out.

@grovesNL pointed out that #1891 has prior discussion on the same (or at least a closely related) question.

wgpu/src/lib.rs Outdated Show resolved Hide resolved
@xiaopengli89 xiaopengli89 force-pushed the queue-empty branch 3 times, most recently from edd4d0b to 8f66594 Compare May 8, 2022 10:58
@xiaopengli89 xiaopengli89 reopened this May 8, 2022
@xiaopengli89
Copy link
Contributor Author

I think it is an acceptable solution to let user make sure that the device polling is used correctly during the transition period when the automatic device polling feature is not implemented。

@jimblandy jimblandy merged commit 9be974a into gfx-rs:master May 10, 2022
@jimblandy
Copy link
Member

Thank you!

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.

2 participants