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 fml::closure p_callback) {
22 return std::shared_ptr<WaitSetEntry>(
23 new WaitSetEntry(std::move(p_fence), std::move(p_callback)));
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, fml::closure p_callback)
43 : fence_(
std::move(p_fence)), callback_(
std::move(p_callback)) {}
45 WaitSetEntry(
const WaitSetEntry&) =
delete;
47 WaitSetEntry(WaitSetEntry&&) =
delete;
49 WaitSetEntry& operator=(
const WaitSetEntry&) =
delete;
51 WaitSetEntry& operator=(WaitSetEntry&&) =
delete;
54 FenceWaiterVK::FenceWaiterVK(std::weak_ptr<DeviceHolderVK> device_holder)
55 : device_holder_(
std::move(device_holder)) {
56 waiter_thread_ = std::make_unique<std::thread>([&]() {
Main(); });
64 vk::UniqueFence fence,
65 const std::function<fml::Status(vk::Fence)>& submit_callback,
66 fml::closure completion_callback) {
67 if (!fence || !submit_callback || !completion_callback) {
68 return fml::Status(fml::StatusCode::kInvalidArgument,
"Invalid arguments");
72 std::scoped_lock lock(wait_set_mutex_);
74 return fml::Status(fml::StatusCode::kCancelled,
75 "Fence waiter is terminated");
77 auto submit_status = submit_callback(fence.get());
78 if (!submit_status.ok()) {
81 wait_set_.emplace_back(
84 wait_set_cv_.notify_one();
89 std::vector<vk::Fence> fences;
90 for (
const auto& entry : set) {
91 if (!entry->IsSignalled()) {
92 fences.emplace_back(entry->GetFence());
98 void FenceWaiterVK::Main() {
99 fml::Thread::SetCurrentThreadName(
100 fml::Thread::ThreadConfig{
"IplrVkFenceWait"});
102 fml::RequestAffinity(fml::CpuAffinity::kEfficiency);
106 bool terminate =
false;
109 std::unique_lock lock(wait_set_mutex_);
112 wait_set_cv_.wait(lock,
113 [&]() {
return !wait_set_.empty() || terminate_; });
116 terminate = terminate_;
130 void FenceWaiterVK::WaitUntilEmpty() {
133 FML_DCHECK(terminate_) <<
"Fence waiter must be terminated.";
134 while (!wait_set_.empty() && Wait()) {
139 bool FenceWaiterVK::Wait() {
143 std::scoped_lock lock(wait_set_mutex_);
144 wait_set = wait_set_;
147 using namespace std::literals::chrono_literals;
150 auto device_holder = device_holder_.lock();
151 if (!device_holder) {
155 const auto& device = device_holder->GetDevice();
161 if (fences.empty()) {
165 auto result = device.waitForFences(
169 std::chrono::nanoseconds{100ms}.count());
170 if (!(result == vk::Result::eSuccess || result == vk::Result::eTimeout)) {
171 VALIDATION_LOG <<
"Fence waiter encountered an unexpected error. Tearing "
172 "down the waiter thread.";
179 TRACE_EVENT0(
"impeller",
"CheckFenceStatus");
180 for (
auto& entry : wait_set) {
181 entry->UpdateSignalledStatus(device);
191 static constexpr
auto is_signalled = [](
const auto& entry) {
192 return entry->IsSignalled();
194 std::scoped_lock lock(wait_set_mutex_);
197 std::copy_if(wait_set_.begin(), wait_set_.end(),
198 std::back_inserter(erased_entries), is_signalled);
200 std::remove_if(wait_set_.begin(), wait_set_.end(), is_signalled),
205 TRACE_EVENT0(
"impeller",
"ClearSignaledFences");
207 erased_entries.clear();
215 std::scoped_lock lock(wait_set_mutex_);
221 wait_set_cv_.notify_one();
222 waiter_thread_->join();
fml::Status AddFence(vk::UniqueFence fence, const std::function< fml::Status(vk::Fence)> &submit_callback, fml::closure completion_callback)
Invokes the [submit_callback] synchronously and adds the fence to the wait set if it succeeds....
const vk::Fence & GetFence() const
static std::shared_ptr< WaitSetEntry > Create(vk::UniqueFence p_fence, fml::closure p_callback)
void UpdateSignalledStatus(const vk::Device &device)
bool Main(const fml::CommandLine &command_line)
static std::vector< vk::Fence > GetFencesForWaitSet(const WaitSet &set)
std::vector< std::shared_ptr< WaitSetEntry > > WaitSet