| 422 | } |
| 423 | |
| 424 | bool WaitEventSubmitInfo::Validate(const CoreChecks& core, const vvl::Queue& queue_state, const vvl::CommandBuffer& cb_state, |
| 425 | EventSignalStateMap& local_signal_states, const Location& loc) const { |
| 426 | bool skip = false; |
| 427 | |
| 428 | VkPipelineStageFlags signals_src_stage_mask = 0; |
| 429 | bool set_wait_version_mismatch = false; // if version mismatch is detected some other validations make no sense |
| 430 | bool found_signals = false; |
| 431 | |
| 432 | for (VkEvent event : wait_events) { |
| 433 | if (auto event_state = core.Get<vvl::Event>(event)) { |
| 434 | if (!vvl::Contains(signal_states, event)) { |
| 435 | skip |= ValidateEventQueueMismatch(core, queue_state, cb_state, *event_state, local_signal_states, loc); |
| 436 | } |
| 437 | const EventSignalState* local_signal_state = vvl::Find(local_signal_states, event); |
| 438 | const EventSignalState* cb_signal_state = vvl::Find(signal_states, event); |
| 439 | const EventSignalState resolved_state = ResolveEventSignal(*event_state, local_signal_state, cb_signal_state); |
| 440 | |
| 441 | // Validate set-wait mismatch |
| 442 | if (IsValueIn(resolved_state.last_signaling_command, {vvl::Func::vkCmdSetEvent2, vvl::Func::vkCmdSetEvent2KHR})) { |
| 443 | set_wait_version_mismatch = true; |
| 444 | const LogObjectList objlist(cb_state.Handle(), event_state->Handle()); |
| 445 | skip |= core.LogError("VUID-vkCmdWaitEvents-pEvents-03847", objlist, loc, "%s: %s was set by %s.", |
| 446 | vvl::String(wait_command), core.FormatHandle(event).c_str(), |
| 447 | vvl::String(resolved_state.last_signaling_command)); |
| 448 | } |
| 449 | // Collect source stages from all signals |
| 450 | if (resolved_state.signaled) { |
| 451 | signals_src_stage_mask |= static_cast<VkPipelineStageFlags>(resolved_state.signal_src_stage_mask); |
| 452 | found_signals = true; |
| 453 | } |
| 454 | } |
| 455 | } |
| 456 | |
| 457 | // Validate src stage mask |
| 458 | if (!set_wait_version_mismatch && wait_src_stage_mask != signals_src_stage_mask) { |
| 459 | std::ostringstream ss; |
| 460 | ss << "(" << core.FormatHandle(cb_state.Handle()) << ") contains vkCmdWaitEvents with srcStageMask " |
| 461 | << string_VkPipelineStageFlags(wait_src_stage_mask); |
| 462 | |
| 463 | const VkPipelineStageFlags device_signals_src_stage_mask = signals_src_stage_mask & ~VK_PIPELINE_STAGE_HOST_BIT; |
| 464 | const VkPipelineStageFlags device_wait_src_stage_mask = wait_src_stage_mask & ~VK_PIPELINE_STAGE_HOST_BIT; |
| 465 | const bool host_wait = wait_src_stage_mask & VK_PIPELINE_STAGE_HOST_BIT; |
| 466 | const bool host_signal = signals_src_stage_mask & VK_PIPELINE_STAGE_HOST_BIT; |
| 467 | |
| 468 | if (found_signals) { |
| 469 | if (device_wait_src_stage_mask != device_signals_src_stage_mask) { |
| 470 | if (signals_src_stage_mask != VK_PIPELINE_STAGE_HOST_BIT) { |
| 471 | ss << ", but the bitwise OR of stageMask values from the most recent vkCmdSetEvent calls is " |
| 472 | << string_VkPipelineStageFlags(device_signals_src_stage_mask); |
| 473 | } else if (host_wait) { |
| 474 | // The host part of srcStageMask matches the host signal, but the device part has no signal |
| 475 | ss << ". srcStageMask includes " << string_VkPipelineStageFlags(device_wait_src_stage_mask) |
| 476 | << " which has no corresponding vkCmdSetEvent signal"; |
| 477 | } |
| 478 | } |
| 479 | if (host_wait && !host_signal) { |
| 480 | ss << ". srcStageMask specifies VK_PIPELINE_STAGE_HOST_BIT but none of the waited events were set by vkSetEvent"; |
| 481 | } |
no test coverage detected