11 #include "flutter/fml/cpu_affinity.h"
12 #include "flutter/fml/thread.h"
13 #include "flutter/fml/trace_event.h"
20 static std::shared_ptr<WaitSetEntry>
Create(vk::UniqueFence p_fence,
21 const fml::closure& p_callback) {
22 return std::shared_ptr<WaitSetEntry>(
30 is_signalled_ = device.getFenceStatus(fence_.get()) == vk::Result::eSuccess;
33 const vk::Fence&
GetFence()
const {
return fence_.get(); }
38 vk::UniqueFence fence_;
39 fml::ScopedCleanupClosure callback_;
40 bool is_signalled_ =
false;
42 WaitSetEntry(vk::UniqueFence p_fence,
const fml::closure& p_callback)
43 : fence_(
std::move(p_fence)),
44 callback_(fml::ScopedCleanupClosure{p_callback}) {}
46 FML_DISALLOW_COPY_ASSIGN_AND_MOVE(WaitSetEntry);
49 FenceWaiterVK::FenceWaiterVK(std::weak_ptr<DeviceHolder> device_holder)
50 : device_holder_(
std::move(device_holder)) {
51 waiter_thread_ = std::make_unique<std::thread>([&]() {
Main(); });
56 waiter_thread_->join();
60 const fml::closure& callback) {
61 TRACE_EVENT0(
"flutter",
"FenceWaiterVK::AddFence");
62 if (!fence || !callback) {
67 std::scoped_lock lock(wait_set_mutex_);
73 wait_set_cv_.notify_one();
78 std::vector<vk::Fence> fences;
79 for (
const auto& entry : set) {
80 if (!entry->IsSignalled()) {
81 fences.emplace_back(entry->GetFence());
87 void FenceWaiterVK::Main() {
88 fml::Thread::SetCurrentThreadName(
89 fml::Thread::ThreadConfig{
"io.flutter.impeller.fence_waiter"});
91 fml::RequestAffinity(fml::CpuAffinity::kEfficiency);
95 bool terminate =
false;
98 std::unique_lock lock(wait_set_mutex_);
101 wait_set_cv_.wait(lock,
102 [&]() {
return !wait_set_.empty() || terminate_; });
105 terminate = terminate_;
119 void FenceWaiterVK::WaitUntilEmpty() {
122 FML_DCHECK(terminate_) <<
"Fence waiter must be terminated.";
123 while (!wait_set_.empty() && Wait()) {
128 bool FenceWaiterVK::Wait() {
132 std::scoped_lock lock(wait_set_mutex_);
133 wait_set = wait_set_;
136 using namespace std::literals::chrono_literals;
139 auto device_holder = device_holder_.lock();
140 if (!device_holder) {
144 const auto& device = device_holder->GetDevice();
150 if (fences.empty()) {
154 auto result = device.waitForFences(
158 std::chrono::nanoseconds{100ms}.count());
159 if (!(result == vk::Result::eSuccess || result == vk::Result::eTimeout)) {
160 VALIDATION_LOG <<
"Fence waiter encountered an unexpected error. Tearing "
161 "down the waiter thread.";
168 TRACE_EVENT0(
"impeller",
"CheckFenceStatus");
169 for (
auto& entry : wait_set) {
170 entry->UpdateSignalledStatus(device);
180 static constexpr
auto is_signalled = [](
const auto& entry) {
181 return entry->IsSignalled();
183 std::scoped_lock lock(wait_set_mutex_);
186 std::copy_if(wait_set_.begin(), wait_set_.end(),
187 std::back_inserter(erased_entries), is_signalled);
189 std::remove_if(wait_set_.begin(), wait_set_.end(), is_signalled),
194 TRACE_EVENT0(
"impeller",
"ClearSignaledFences");
196 erased_entries.clear();
204 std::scoped_lock lock(wait_set_mutex_);
207 wait_set_cv_.notify_one();