20 static std::shared_ptr<WaitSetEntry>
Create(vk::UniqueFence p_fence,
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_;
40 bool is_signalled_ =
false;
43 : fence_(
std::move(p_fence)),
44 callback_(
fml::ScopedCleanupClosure{p_callback}) {}
46 WaitSetEntry(
const WaitSetEntry&) =
delete;
48 WaitSetEntry(WaitSetEntry&&) =
delete;
50 WaitSetEntry& operator=(
const WaitSetEntry&) =
delete;
52 WaitSetEntry& operator=(WaitSetEntry&&) =
delete;
55FenceWaiterVK::FenceWaiterVK(std::weak_ptr<DeviceHolderVK> device_holder)
56 : device_holder_(
std::move(device_holder)) {
57 waiter_thread_ = std::make_unique<std::thread>([&]() {
Main(); });
71 std::scoped_lock lock(wait_set_mutex_);
77 wait_set_cv_.notify_one();
82 std::vector<vk::Fence> fences;
83 for (
const auto& entry : set) {
84 if (!entry->IsSignalled()) {
85 fences.emplace_back(entry->GetFence());
91void FenceWaiterVK::Main() {
99 bool terminate =
false;
102 std::unique_lock lock(wait_set_mutex_);
105 wait_set_cv_.wait(lock,
106 [&]() {
return !wait_set_.empty() || terminate_; });
109 terminate = terminate_;
123void FenceWaiterVK::WaitUntilEmpty() {
126 FML_DCHECK(terminate_) <<
"Fence waiter must be terminated.";
127 while (!wait_set_.empty() && Wait()) {
132bool FenceWaiterVK::Wait() {
136 std::scoped_lock lock(wait_set_mutex_);
137 wait_set = wait_set_;
140 using namespace std::literals::chrono_literals;
143 auto device_holder = device_holder_.lock();
144 if (!device_holder) {
148 const auto&
device = device_holder->GetDevice();
154 if (fences.empty()) {
158 auto result =
device.waitForFences(
162 std::chrono::nanoseconds{100ms}.count());
163 if (!(result == vk::Result::eSuccess || result == vk::Result::eTimeout)) {
164 VALIDATION_LOG <<
"Fence waiter encountered an unexpected error. Tearing "
165 "down the waiter thread.";
173 for (
auto& entry : wait_set) {
174 entry->UpdateSignalledStatus(
device);
184 static constexpr auto is_signalled = [](
const auto& entry) {
185 return entry->IsSignalled();
187 std::scoped_lock lock(wait_set_mutex_);
190 std::copy_if(wait_set_.begin(), wait_set_.end(),
191 std::back_inserter(erased_entries), is_signalled);
193 std::remove_if(wait_set_.begin(), wait_set_.end(), is_signalled),
200 erased_entries.clear();
208 std::scoped_lock lock(wait_set_mutex_);
214 wait_set_cv_.notify_one();
215 waiter_thread_->join();
Wraps a closure that is invoked in the destructor unless released by the caller.
static void SetCurrentThreadName(const ThreadConfig &config)
bool AddFence(vk::UniqueFence fence, const fml::closure &callback)
const vk::Fence & GetFence() const
static std::shared_ptr< WaitSetEntry > Create(vk::UniqueFence p_fence, const fml::closure &p_callback)
void UpdateSignalledStatus(const vk::Device &device)
FlutterDesktopBinaryReply callback
#define FML_DCHECK(condition)
@ kEfficiency
Request CPU affinity for the efficiency cores.
bool RequestAffinity(CpuAffinity affinity)
Request the given affinity for the current thread.
std::function< void()> closure
bool Main(const fml::CommandLine &command_line)
static std::vector< vk::Fence > GetFencesForWaitSet(const WaitSet &set)
std::vector< std::shared_ptr< WaitSetEntry > > WaitSet
The ThreadConfig is the thread info include thread name, thread priority.
#define TRACE_EVENT0(category_group, name)