| 106 | } |
| 107 | |
| 108 | void SyncValidator::ApplySignalsUpdate(SignalsUpdate& update, const BatchContextPtr& last_batch) { |
| 109 | // NOTE: All conserved QueueBatchContexts need to have their access logs reset to use the global |
| 110 | // logger and the only conserved QBCs are those referenced by unwaited signals and the last batch. |
| 111 | |
| 112 | for (auto& signal_entry : update.binary_signal_requests) { |
| 113 | auto& signal_batch = signal_entry.second.batch; |
| 114 | // Batches retained for signalled semaphore don't need to retain |
| 115 | // event data, unless it's the last batch in the submit |
| 116 | if (signal_batch != last_batch) { |
| 117 | signal_batch->ResetEventsContext(); |
| 118 | // Make sure that retained batches are minimal, and trim |
| 119 | // after the events contexts has been cleared. |
| 120 | signal_batch->Trim(); |
| 121 | } |
| 122 | const VkSemaphore semaphore = signal_entry.first; |
| 123 | SignalInfo& signal_info = signal_entry.second; |
| 124 | binary_signals_.insert_or_assign(semaphore, std::move(signal_info)); |
| 125 | } |
| 126 | for (VkSemaphore semaphore : update.binary_unsignal_requests) { |
| 127 | binary_signals_.erase(semaphore); |
| 128 | } |
| 129 | for (auto& [semaphore, new_signals] : update.timeline_signals) { |
| 130 | std::vector<SignalInfo>& signals = timeline_signals_[semaphore]; |
| 131 | vvl::Append(signals, new_signals); |
| 132 | stats.AddTimelineSignals((uint32_t)new_signals.size()); |
| 133 | |
| 134 | // Update host sync points |
| 135 | std::deque<TimelineHostSyncPoint>& host_sync_points = host_waitable_semaphores_[semaphore]; |
| 136 | for (SignalInfo& new_signal : new_signals) { |
| 137 | if (new_signal.batch) { |
| 138 | // The lifetimes of the semaphore host sync points are managed by vkWaitSemaphores. |
| 139 | // kMaxTimelineHostSyncPoints limit is used when the program does not use vkWaitSemaphores. |
| 140 | // We accumulate up to kMaxTimelineHostSyncPoints of the host sync points per semaphore. |
| 141 | // Dropping old sync points cannot introduce false positives but may miss a sync hazard. |
| 142 | // The limit is chosen to be large enough comparing to typical numbers of queue submissions |
| 143 | // between host synchronization points. |
| 144 | const uint32_t kMaxTimelineHostSyncPoints = 256; // max ~6 Kb per semaphore |
| 145 | if (host_sync_points.size() >= kMaxTimelineHostSyncPoints) { |
| 146 | host_sync_points.pop_front(); |
| 147 | } |
| 148 | // Add a host sync point for this signal |
| 149 | TimelineHostSyncPoint sync_point; |
| 150 | assert(new_signal.first_scope.queue != kQueueIdInvalid); |
| 151 | sync_point.queue_id = new_signal.first_scope.queue; |
| 152 | sync_point.tag = new_signal.batch->GetTagRange().end - 1; |
| 153 | sync_point.timeline_value = new_signal.timeline_value; |
| 154 | host_sync_points.emplace_back(sync_point); |
| 155 | } |
| 156 | } |
| 157 | } |
| 158 | for (const auto& remove_signals_request : update.remove_timeline_signals_requests) { |
| 159 | auto& signals = timeline_signals_[remove_signals_request.semaphore]; |
| 160 | for (auto it = signals.begin(); it != signals.end();) { |
| 161 | const SignalInfo& signal = *it; |
| 162 | if (signal.first_scope.queue == remove_signals_request.queue && |
| 163 | signal.timeline_value < remove_signals_request.signal_threshold_value) { |
| 164 | it = signals.erase(it); |
| 165 | stats.RemoveTimelineSignals(1); |
nothing calls this directly
no test coverage detected