Commit 8b199243 authored by Austin Eng's avatar Austin Eng Committed by Commit Bot

WebGPU: Flush eagerly after GPUQueue::submit

In other parts of the WebGPU API, we flush lazily at the end of the
task because the page needs to yield back to the browser for pending
callbacks to resolve anyway. Queue submissions however may be holding
lots of data which the GPU process can begin working on promptly.
Frequent queue submissions will have poor command throughput if we don't
flush eagerly.

In the future, the WebGPU command buffer should have a better
way for the Renderer process to ask the GPU process to begin processing
work, and update the GPU process (in a non-blocking way) of the latest
command it has finished writing. This would yield better throughput
without requiring frequent flushes.

Bug: 1128293
Change-Id: I19903dffc946865b11512d100b711409857b025f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2417639Reviewed-by: default avatarCorentin Wallez <cwallez@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809002}
parent 4044e751
...@@ -580,6 +580,16 @@ void WebGPUImplementation::FlushCommands() { ...@@ -580,6 +580,16 @@ void WebGPUImplementation::FlushCommands() {
helper_->Flush(); helper_->Flush();
} }
void WebGPUImplementation::FlushCommands(DawnDeviceClientID device_client_id) {
#if BUILDFLAG(USE_DAWN)
WebGPUCommandSerializer* command_serializer =
GetCommandSerializerWithDeviceClientID(device_client_id);
DCHECK(command_serializer);
command_serializer->Flush();
helper_->Flush();
#endif
}
void WebGPUImplementation::EnsureAwaitingFlush( void WebGPUImplementation::EnsureAwaitingFlush(
DawnDeviceClientID device_client_id, DawnDeviceClientID device_client_id,
bool* needs_flush) { bool* needs_flush) {
......
...@@ -158,6 +158,7 @@ class WEBGPU_EXPORT WebGPUImplementation final : public WebGPUInterface, ...@@ -158,6 +158,7 @@ class WEBGPU_EXPORT WebGPUImplementation final : public WebGPUInterface,
// WebGPUInterface implementation // WebGPUInterface implementation
const DawnProcTable& GetProcs() const override; const DawnProcTable& GetProcs() const override;
void FlushCommands() override; void FlushCommands() override;
void FlushCommands(DawnDeviceClientID device_client_id) override;
void EnsureAwaitingFlush(DawnDeviceClientID device_client_id, void EnsureAwaitingFlush(DawnDeviceClientID device_client_id,
bool* needs_flush) override; bool* needs_flush) override;
void FlushAwaitingCommands(DawnDeviceClientID device_client_id) override; void FlushAwaitingCommands(DawnDeviceClientID device_client_id) override;
......
...@@ -32,6 +32,9 @@ class WebGPUInterface : public InterfaceBase { ...@@ -32,6 +32,9 @@ class WebGPUInterface : public InterfaceBase {
// Flush all commands. // Flush all commands.
virtual void FlushCommands() = 0; virtual void FlushCommands() = 0;
// Flush all commands on the device client.
virtual void FlushCommands(DawnDeviceClientID device_client_id) = 0;
// Ensure the awaiting flush flag is set on the device client. Returns false // Ensure the awaiting flush flag is set on the device client. Returns false
// if a flush has already been indicated, or a flush is not needed (there may // if a flush has already been indicated, or a flush is not needed (there may
// be no commands to flush). Returns true if the caller should schedule a // be no commands to flush). Returns true if the caller should schedule a
......
...@@ -23,6 +23,7 @@ const DawnProcTable& WebGPUInterfaceStub::GetProcs() const { ...@@ -23,6 +23,7 @@ const DawnProcTable& WebGPUInterfaceStub::GetProcs() const {
return null_procs_; return null_procs_;
} }
void WebGPUInterfaceStub::FlushCommands() {} void WebGPUInterfaceStub::FlushCommands() {}
void WebGPUInterfaceStub::FlushCommands(DawnDeviceClientID device_client_id) {}
void WebGPUInterfaceStub::EnsureAwaitingFlush( void WebGPUInterfaceStub::EnsureAwaitingFlush(
DawnDeviceClientID device_client_id, DawnDeviceClientID device_client_id,
bool* needs_flush) {} bool* needs_flush) {}
......
...@@ -25,6 +25,7 @@ class WebGPUInterfaceStub : public WebGPUInterface { ...@@ -25,6 +25,7 @@ class WebGPUInterfaceStub : public WebGPUInterface {
// WebGPUInterface implementation // WebGPUInterface implementation
const DawnProcTable& GetProcs() const override; const DawnProcTable& GetProcs() const override;
void FlushCommands() override; void FlushCommands() override;
void FlushCommands(DawnDeviceClientID device_client_id) override;
void EnsureAwaitingFlush(DawnDeviceClientID device_client_id, void EnsureAwaitingFlush(DawnDeviceClientID device_client_id,
bool* needs_flush) override; bool* needs_flush) override;
void FlushAwaitingCommands(DawnDeviceClientID device_client_id) override; void FlushAwaitingCommands(DawnDeviceClientID device_client_id) override;
......
...@@ -83,6 +83,12 @@ void DeviceTreeObject::EnsureFlush() { ...@@ -83,6 +83,12 @@ void DeviceTreeObject::EnsureFlush() {
device_client_serializer_holder_)); device_client_serializer_holder_));
} }
// Flush commands up until now on this object's parent device immediately.
void DeviceTreeObject::FlushNow() {
GetInterface()->FlushCommands(
device_client_serializer_holder_->device_client_id_);
}
DawnObjectImpl::DawnObjectImpl(GPUDevice* device) DawnObjectImpl::DawnObjectImpl(GPUDevice* device)
: DeviceTreeObject(device->GetDeviceClientSerializerHolder()), : DeviceTreeObject(device->GetDeviceClientSerializerHolder()),
device_(device) {} device_(device) {}
......
...@@ -92,6 +92,9 @@ class DeviceTreeObject { ...@@ -92,6 +92,9 @@ class DeviceTreeObject {
// the end of the task. // the end of the task.
void EnsureFlush(); void EnsureFlush();
// Flush commands up until now on this object's parent device immediately.
void FlushNow();
protected: protected:
scoped_refptr<DawnDeviceClientSerializerHolder> scoped_refptr<DawnDeviceClientSerializerHolder>
device_client_serializer_holder_; device_client_serializer_holder_;
......
...@@ -147,8 +147,9 @@ void GPUQueue::submit(const HeapVector<Member<GPUCommandBuffer>>& buffers) { ...@@ -147,8 +147,9 @@ void GPUQueue::submit(const HeapVector<Member<GPUCommandBuffer>>& buffers) {
GetProcs().queueSubmit(GetHandle(), buffers.size(), commandBuffers.get()); GetProcs().queueSubmit(GetHandle(), buffers.size(), commandBuffers.get());
// WebGPU guarantees that submitted commands finish in finite time so we // WebGPU guarantees that submitted commands finish in finite time so we
// need to ensure commands are flushed. // need to ensure commands are flushed. Flush immediately so the GPU process
EnsureFlush(); // eagerly processes commands to maximize throughput.
FlushNow();
} }
void GPUQueue::signal(GPUFence* fence, uint64_t signal_value) { void GPUQueue::signal(GPUFence* fence, uint64_t signal_value) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment