d3d: reuse event objects
Bug: chromium:335553337
Change-Id: I26c68b2a76d1885be3fdb7e9b72831185690221e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/184622
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
diff --git a/src/dawn/native/SystemEvent.cpp b/src/dawn/native/SystemEvent.cpp
index dd0d4b1..747f2bd 100644
--- a/src/dawn/native/SystemEvent.cpp
+++ b/src/dawn/native/SystemEvent.cpp
@@ -60,6 +60,10 @@
return receiver;
}
+const SystemHandle& SystemEventReceiver::GetPrimitive() const {
+ return mPrimitive;
+}
+
// SystemEventPipeSender
SystemEventPipeSender::~SystemEventPipeSender() {
diff --git a/src/dawn/native/SystemEvent.h b/src/dawn/native/SystemEvent.h
index f641cf7..391d430 100644
--- a/src/dawn/native/SystemEvent.h
+++ b/src/dawn/native/SystemEvent.h
@@ -59,6 +59,8 @@
SystemEventReceiver(SystemEventReceiver&&) = default;
SystemEventReceiver& operator=(SystemEventReceiver&&) = default;
+ const SystemHandle& GetPrimitive() const;
+
private:
template <typename It>
friend bool WaitAnySystemEvent(It begin, It end, Nanoseconds timeout);
diff --git a/src/dawn/native/d3d/QueueD3D.cpp b/src/dawn/native/d3d/QueueD3D.cpp
index f8615dc..5f07c57 100644
--- a/src/dawn/native/d3d/QueueD3D.cpp
+++ b/src/dawn/native/d3d/QueueD3D.cpp
@@ -27,6 +27,7 @@
#include "dawn/native/d3d/QueueD3D.h"
+#include <algorithm>
#include <utility>
#include "dawn/native/WaitAnySystemEvent.h"
@@ -35,6 +36,44 @@
Queue::~Queue() = default;
+ResultOrError<SystemEventReceiver> Queue::GetSystemEventReceiver() {
+ SystemEventReceiver receiver;
+ bool result = mAvailableEventReceivers.Use([&](auto receivers) -> auto {
+ if (receivers->empty()) {
+ return false;
+ }
+ receiver = std::move(receivers->back());
+ receivers->pop_back();
+ return true;
+ });
+ if (!result) {
+ HANDLE fenceEvent =
+ ::CreateEvent(nullptr, /*bManualReset=*/true, /*bInitialState=*/false, nullptr);
+ if (fenceEvent == nullptr) {
+ return DAWN_INTERNAL_ERROR("CreateEvent failed");
+ }
+ receiver = SystemEventReceiver(SystemHandle::Acquire(fenceEvent));
+ }
+
+ return receiver;
+}
+
+MaybeError Queue::ReturnSystemEventReceivers(std::vector<SystemEventReceiver> receivers) {
+ for (const auto& receiver : receivers) {
+ if (!ResetEvent(receiver.GetPrimitive().Get())) {
+ return DAWN_INTERNAL_ERROR("ResetEvent failed");
+ }
+ }
+ mAvailableEventReceivers.Use([&](auto availableEventReceivers) {
+ size_t count =
+ std::min(receivers.size(), kMaxEventReceivers - availableEventReceivers->size());
+ availableEventReceivers->insert(availableEventReceivers->end(),
+ std::make_move_iterator(receivers.begin()),
+ std::make_move_iterator(receivers.begin() + count));
+ });
+ return {};
+}
+
ResultOrError<bool> Queue::WaitForQueueSerial(ExecutionSerial serial, Nanoseconds timeout) {
ExecutionSerial completedSerial = GetCompletedCommandSerial();
if (serial <= completedSerial) {
@@ -43,16 +82,8 @@
auto receiver = mSystemEventReceivers->TakeOne(serial);
if (!receiver) {
- // Anytime we may create an event, clear out any completed receivers so the list doesn't
- // grow forever.
- mSystemEventReceivers->ClearUpTo(completedSerial);
-
- HANDLE fenceEvent =
- ::CreateEvent(nullptr, /*bManualReset=*/true, /*bInitialState=*/false, nullptr);
- DAWN_INVALID_IF(fenceEvent == nullptr, "CreateEvent failed");
- SetEventOnCompletion(serial, fenceEvent);
-
- receiver = SystemEventReceiver(SystemHandle::Acquire(fenceEvent));
+ DAWN_TRY_ASSIGN(receiver, GetSystemEventReceiver());
+ SetEventOnCompletion(serial, receiver->GetPrimitive().Get());
}
bool ready = false;
@@ -60,12 +91,26 @@
{{*receiver, &ready}}};
DAWN_ASSERT(serial <= GetLastSubmittedCommandSerial());
bool didComplete = WaitAnySystemEvent(events.begin(), events.end(), timeout);
- if (!didComplete) {
- // Return the SystemEventReceiver to the pool of receivers so it can be re-waited in the
- // future.
- mSystemEventReceivers->Enqueue(std::move(*receiver), serial);
- }
+ // Return the SystemEventReceiver to the pool of receivers so it can be re-waited in the
+ // future.
+ // The caller should call CheckPassedSerials() which will clear passed system events.
+ mSystemEventReceivers->Enqueue(std::move(*receiver), serial);
+
return didComplete;
}
+MaybeError Queue::RecycleSystemEventReceivers(ExecutionSerial completedSerial) {
+ std::vector<SystemEventReceiver> receivers;
+ mSystemEventReceivers.Use([&](auto systemEventReceivers) {
+ for (auto& receiver : systemEventReceivers->IterateUpTo(completedSerial)) {
+ receivers.emplace_back(std::move(receiver));
+ }
+ systemEventReceivers->ClearUpTo(completedSerial);
+ });
+
+ DAWN_TRY(ReturnSystemEventReceivers(std::move(receivers)));
+
+ return {};
+}
+
} // namespace dawn::native::d3d
diff --git a/src/dawn/native/d3d/QueueD3D.h b/src/dawn/native/d3d/QueueD3D.h
index ee9e7a4..05e8d03 100644
--- a/src/dawn/native/d3d/QueueD3D.h
+++ b/src/dawn/native/d3d/QueueD3D.h
@@ -28,6 +28,8 @@
#ifndef SRC_DAWN_NATIVE_D3D_QUEUED3D_H_
#define SRC_DAWN_NATIVE_D3D_QUEUED3D_H_
+#include <vector>
+
#include "dawn/common/MutexProtected.h"
#include "dawn/common/SerialMap.h"
#include "dawn/common/windows_with_undefs.h"
@@ -45,11 +47,20 @@
virtual ResultOrError<Ref<SharedFence>> GetOrCreateSharedFence() = 0;
+ protected:
ResultOrError<bool> WaitForQueueSerial(ExecutionSerial serial, Nanoseconds timeout) override;
+ ResultOrError<SystemEventReceiver> GetSystemEventReceiver();
+ MaybeError ReturnSystemEventReceivers(std::vector<SystemEventReceiver> receivers);
+ MaybeError RecycleSystemEventReceivers(ExecutionSerial completeSerial);
+
private:
virtual void SetEventOnCompletion(ExecutionSerial serial, HANDLE event) = 0;
+ // Available event receivers which can be reused.
+ static constexpr size_t kMaxEventReceivers = 32;
+ MutexProtected<std::vector<SystemEventReceiver>> mAvailableEventReceivers;
+
MutexProtected<SerialMap<ExecutionSerial, SystemEventReceiver>> mSystemEventReceivers;
};
diff --git a/src/dawn/native/d3d11/QueueD3D11.cpp b/src/dawn/native/d3d11/QueueD3D11.cpp
index a368d92..42070e5 100644
--- a/src/dawn/native/d3d11/QueueD3D11.cpp
+++ b/src/dawn/native/d3d11/QueueD3D11.cpp
@@ -222,6 +222,8 @@
DAWN_TRY(CheckAndMapReadyBuffers(completedSerial));
+ DAWN_TRY(RecycleSystemEventReceivers(completedSerial));
+
return completedSerial;
}
diff --git a/src/dawn/native/d3d12/QueueD3D12.cpp b/src/dawn/native/d3d12/QueueD3D12.cpp
index a358f85..6833eff 100644
--- a/src/dawn/native/d3d12/QueueD3D12.cpp
+++ b/src/dawn/native/d3d12/QueueD3D12.cpp
@@ -185,6 +185,8 @@
return ExecutionSerial(0);
}
+ DAWN_TRY(RecycleSystemEventReceivers(completedSerial));
+
return completedSerial;
}