| 652 | } |
| 653 | |
| 654 | bool SyncOpWaitEvents::DoValidate(const CommandExecutionContext& exec_context, const ResourceUsageTag base_tag) const { |
| 655 | bool skip = false; |
| 656 | const auto& sync_state = exec_context.GetSyncState(); |
| 657 | const QueueId queue_id = exec_context.GetQueueId(); |
| 658 | |
| 659 | const SyncEventsContext& events_context = exec_context.GetEventsContext(); |
| 660 | size_t barrier_set_index = 0; |
| 661 | size_t barrier_set_incr = (barrier_sets_.size() == 1) ? 0 : 1; |
| 662 | const Location loc(command_); |
| 663 | for (const auto& event : events_) { |
| 664 | const auto* sync_event = events_context.Get(event); |
| 665 | const auto& barrier_set = barrier_sets_[barrier_set_index]; |
| 666 | if (!sync_event || !sync_event->first_scope) { |
| 667 | barrier_set_index += barrier_set_incr; |
| 668 | continue; // Core, Lifetimes, or Param check needs to catch invalid events. |
| 669 | } |
| 670 | |
| 671 | // For replay calls, don't revalidate "same command buffer" events |
| 672 | if (sync_event->last_command_tag >= base_tag) { |
| 673 | continue; |
| 674 | } |
| 675 | |
| 676 | const VkEvent event_handle = sync_event->event->VkHandle(); |
| 677 | |
| 678 | // TODO: Cleanup this error message |
| 679 | if (sync_event->unsynchronized_set != vvl::Func::Empty) { |
| 680 | // Issue error message that Wait is waiting on an signal subject to race condition, and is thus ignored for |
| 681 | // this event |
| 682 | const char* const vuid = "SYNC-vkCmdWaitEvents-unsynchronized-setops"; |
| 683 | const char* const message = "%s Unsychronized %s calls result in race conditions w.r.t. event signalling, %s %s"; |
| 684 | const char* const reason = "First synchronization scope is undefined."; |
| 685 | skip |= sync_state.LogError(vuid, event_handle, loc, message, sync_state.FormatHandle(event_handle).c_str(), |
| 686 | vvl::String(sync_event->last_command), reason, kIgnored); |
| 687 | } |
| 688 | if (barrier_set.image_barriers.size()) { |
| 689 | const auto& image_memory_barriers = barrier_set.image_barriers; |
| 690 | const AccessContext& context = exec_context.GetCurrentAccessContext(); |
| 691 | for (const auto& image_memory_barrier : image_memory_barriers) { |
| 692 | if (!image_memory_barrier.layout_transition) continue; |
| 693 | const auto* image_state = image_memory_barrier.image.get(); |
| 694 | if (!image_state) continue; |
| 695 | const auto& subresource_range = image_memory_barrier.subresource_range; |
| 696 | const auto& src_access_scope = image_memory_barrier.barrier.src_access_scope; |
| 697 | const auto hazard = context.DetectImageBarrierHazard( |
| 698 | *image_state, subresource_range, sync_event->scope.exec_scope, src_access_scope, queue_id, |
| 699 | sync_event->FirstScope(), sync_event->first_scope_tag, AccessContext::DetectOptions::kDetectAll); |
| 700 | if (hazard.IsHazard()) { |
| 701 | LogObjectList objlist(exec_context.Handle(), image_state->Handle()); |
| 702 | const std::string resource_description = sync_state.FormatHandle(image_state->Handle()); |
| 703 | const std::string error = sync_state.error_messages_.ImageBarrierError( |
| 704 | hazard, exec_context, command_, resource_description, image_memory_barrier); |
| 705 | skip |= sync_state.SyncError(hazard.Hazard(), image_state->Handle(), loc, error); |
| 706 | break; |
| 707 | } |
| 708 | } |
| 709 | } |
| 710 | // TODO: Add infrastructure for checking pDependencyInfo's vs. CmdSetEvent2 VUID - vkCmdWaitEvents2KHR - pEvents - |
| 711 | // 03839 |
nothing calls this directly
no test coverage detected