| 303 | |
| 304 | template <typename Predicate> |
| 305 | void QueueBatchContext::ApplyPredicatedWait(Predicate& predicate, const LastSynchronizedPresent& last_synchronized_present) { |
| 306 | access_context_.EraseIf([this, &last_synchronized_present, &predicate](AccessMap::value_type& access) { |
| 307 | AccessState& access_state = access.second; |
| 308 | |
| 309 | // Tell EraseIf to remove present accesses that are already synchronized according to LastSynchronizedPresent |
| 310 | if (access_state.HasWriteOp() && access_state.LastWrite().IsPresent()) { |
| 311 | const ResourceUsageRecord& usage_record = *batch_log_.GetAccessRecord(access_state.LastWriteTag()).record; |
| 312 | assert(usage_record.alt_usage); |
| 313 | assert(usage_record.alt_usage.GetCommand() == vvl::Func::vkQueuePresentKHR); |
| 314 | const VkSwapchainKHR swapchain = usage_record.alt_usage.GetSwapchainHandle(); |
| 315 | for (const auto& [synchronized_swapchain, synchronized_present_tag] : last_synchronized_present.per_swapchain) { |
| 316 | // NOTE: it is important to check that access belongs to a specific swapchain and not only |
| 317 | // compare the tag values. It is possible to have accesses from a different swapchain that |
| 318 | // are *not* synchronized and have tag values that satisfy tag comparison check. |
| 319 | if (swapchain == synchronized_swapchain && access_state.LastWriteTag() <= synchronized_present_tag) { |
| 320 | return true; |
| 321 | } |
| 322 | } |
| 323 | } |
| 324 | |
| 325 | // Tell eraseIf to remove accesses that become empty after applying predicate |
| 326 | return access_state.ClearPredicatedAccesses<Predicate>(predicate); |
| 327 | }); |
| 328 | } |
| 329 | |
| 330 | struct WaitQueueTagPredicate { |
| 331 | QueueId queue; |
nothing calls this directly
no test coverage detected