| 262 | } |
| 263 | |
| 264 | void SyncValidator::WaitForSemaphore(VkSemaphore semaphore, uint64_t value) { |
| 265 | std::deque<TimelineHostSyncPoint>* sync_points = vvl::Find(host_waitable_semaphores_, semaphore); |
| 266 | if (!sync_points) { |
| 267 | return; |
| 268 | } |
| 269 | auto matching_sync_point = [value](const TimelineHostSyncPoint& sync_point) { return sync_point.timeline_value >= value; }; |
| 270 | auto sync_point_it = std::find_if(sync_points->begin(), sync_points->end(), matching_sync_point); |
| 271 | if (sync_point_it == sync_points->end()) { |
| 272 | return; |
| 273 | } |
| 274 | |
| 275 | const TimelineHostSyncPoint& sync_point = *sync_point_it; |
| 276 | const QueueState& queue_state = GetQueueState(sync_point.queue_id); |
| 277 | |
| 278 | // TODO: specify queue sync tags argument similar to WaitForFence |
| 279 | ApplyTaggedWait(sync_point.queue_id, sync_point.tag, queue_state.GetLastSynchronizedPresent(), {}); |
| 280 | |
| 281 | // Remove signals before the resolving one (keep the resolving signal). |
| 282 | std::vector<SignalInfo>& signals = timeline_signals_[semaphore]; |
| 283 | const size_t initial_signal_count = signals.size(); |
| 284 | vvl::erase_if(signals, [&sync_point](SignalInfo& signal) { |
| 285 | return signal.first_scope.queue == sync_point.queue_id && signal.timeline_value < sync_point.timeline_value; |
| 286 | }); |
| 287 | stats.RemoveTimelineSignals(uint32_t(initial_signal_count - signals.size())); |
| 288 | |
| 289 | // We can remove all sync points that are in the scope of current wait. |
| 290 | // Subsequent attempts to synchronize on the host with already synchronized |
| 291 | // timeline values will result in noop. |
| 292 | sync_points->erase(sync_points->begin(), sync_point_it + 1 /* include resolving sync point too*/); |
| 293 | } |
| 294 | |
| 295 | void SyncValidator::UpdateSyncImageMemoryBindState(uint32_t count, const VkBindImageMemoryInfo* infos) { |
| 296 | for (const auto& info : vvl::make_span(infos, count)) { |