| 2295 | } |
| 2296 | |
| 2297 | bool SyncValidator::ProcessQueuePresent(VkQueue queue, const VkPresentInfoKHR* pPresentInfo, const ErrorObject& error_obj) { |
| 2298 | bool skip = false; |
| 2299 | |
| 2300 | const QueueId queue_id = GetQueueId(queue); |
| 2301 | if (queue_id == kQueueIdInvalid) { |
| 2302 | return skip; |
| 2303 | } |
| 2304 | QueueState& queue_state = GetQueueState(queue_id); |
| 2305 | const uint64_t submit_id = queue_state.ReserveSubmitId(); |
| 2306 | |
| 2307 | BatchContextPtr last_batch = queue_state.LastBatch(); |
| 2308 | BatchContextPtr batch(std::make_shared<QueueBatchContext>(*this, queue_state)); |
| 2309 | |
| 2310 | const auto wait_semaphores = vvl::make_span(pPresentInfo->pWaitSemaphores, pPresentInfo->waitSemaphoreCount); |
| 2311 | |
| 2312 | PresentedImages presented_images; |
| 2313 | uint32_t present_tag_count = SetupPresentInfo(*pPresentInfo, batch, presented_images); |
| 2314 | |
| 2315 | SignalsUpdate signals_update(*this); |
| 2316 | auto resolved_batches = batch->ResolvePresentWaits(wait_semaphores, presented_images, signals_update); |
| 2317 | |
| 2318 | // Import the previous batch information |
| 2319 | if (last_batch && !vvl::Contains(resolved_batches, last_batch)) { |
| 2320 | batch->ResolveLastBatch(last_batch); |
| 2321 | resolved_batches.emplace_back(std::move(last_batch)); |
| 2322 | } |
| 2323 | |
| 2324 | // The purpose of keeping return value is to ensure async batches are alive during validation. |
| 2325 | // Validation accesses raw pointer to async contexts stored in AsyncReference. |
| 2326 | const auto async_batches = batch->RegisterAsyncContexts(resolved_batches); |
| 2327 | |
| 2328 | // Convert present tags to global range |
| 2329 | const ResourceUsageTag global_range_start = batch->SetupBatchTags(present_tag_count); |
| 2330 | for (PresentedImage& presented : presented_images) { |
| 2331 | presented.tag += global_range_start; |
| 2332 | } |
| 2333 | |
| 2334 | skip |= batch->DoQueuePresentValidate(error_obj.location, presented_images); |
| 2335 | batch->DoPresentOperations(presented_images); |
| 2336 | batch->LogPresentOperations(presented_images, submit_id); |
| 2337 | |
| 2338 | // Update state if there are no validation errors |
| 2339 | if (!skip) { |
| 2340 | stats.UpdateAccessStats(*this); |
| 2341 | stats.UpdateMemoryStats(); |
| 2342 | queue_state.SetLastBatch(std::move(batch)); |
| 2343 | ApplySignalsUpdate(signals_update, queue_state.LastBatch()); |
| 2344 | for (auto& presented : presented_images) { |
| 2345 | presented.ExportToSwapchain(); |
| 2346 | } |
| 2347 | } |
| 2348 | return skip; |
| 2349 | } |
| 2350 | |
| 2351 | uint32_t SyncValidator::SetupPresentInfo(const VkPresentInfoKHR& present_info, BatchContextPtr& batch, |
| 2352 | PresentedImages& presented_images) { |
no test coverage detected