| 451 | } |
| 452 | |
| 453 | void SyncOpPipelineBarrier::ApplyMultipleBarriers(CommandExecutionContext& exec_context, ResourceUsageTag exec_tag) const { |
| 454 | AccessContext& access_context = exec_context.GetCurrentAccessContext(); |
| 455 | const QueueId queue_id = exec_context.GetQueueId(); |
| 456 | |
| 457 | // Apply markup action. |
| 458 | // The markup action does not change any access state but it can trim the access map according to the |
| 459 | // provided range and creates infill ranges if necessary (for layout transitions). The purpose of all |
| 460 | // this is to ensure that after markup action the topology of access map ranges is finalized so we can |
| 461 | // safely cache pointers to specific access states with a goal to apply pending barriers in the end. |
| 462 | // |
| 463 | // NOTE: it is enough to apply markup action to buffer and image barriers. The global barriers |
| 464 | // do not use infill operations (no layout transitions) and also do not split access map ranges |
| 465 | // because global barriers are applied to the full range. |
| 466 | for (const SyncBufferBarrier& barrier : barrier_set_.buffer_barriers) { |
| 467 | if (SimpleBinding(*barrier.buffer)) { |
| 468 | const VkDeviceSize base_address = ResourceBaseAddress(*barrier.buffer); |
| 469 | const AccessRange range = barrier.range + base_address; |
| 470 | ApplyMarkupFunctor markup_action(false); |
| 471 | access_context.UpdateMemoryAccessState(markup_action, range); |
| 472 | } |
| 473 | } |
| 474 | for (const SyncImageBarrier& barrier : barrier_set_.image_barriers) { |
| 475 | const auto& sub_state = SubState(*barrier.image); |
| 476 | const bool can_transition_depth_slices = CanTransitionDepthSlices( |
| 477 | exec_context.GetSyncState().extensions, sub_state.base.GetImageType(), sub_state.base.create_flags); |
| 478 | auto range_gen = sub_state.MakeImageRangeGen(barrier.subresource_range, can_transition_depth_slices); |
| 479 | // TODO: check if we need: barrier.layout_transition && (queue_id == kQueueIdInvalid) |
| 480 | ApplyMarkupFunctor markup_action(barrier.layout_transition); |
| 481 | access_context.UpdateMemoryAccessState(markup_action, range_gen); |
| 482 | } |
| 483 | |
| 484 | // Use PendingBarriers to collect barriers that must be applied independently |
| 485 | PendingBarriers pending_barriers; |
| 486 | for (const SyncBufferBarrier& barrier : barrier_set_.buffer_barriers) { |
| 487 | if (SimpleBinding(*barrier.buffer)) { |
| 488 | const BarrierScope barrier_scope(barrier.barrier, queue_id); |
| 489 | CollectBarriersFunctor collect_barriers(access_context, barrier_scope, barrier.barrier, false, vvl::kNoIndex32, |
| 490 | pending_barriers); |
| 491 | |
| 492 | const VkDeviceSize base_address = ResourceBaseAddress(*barrier.buffer); |
| 493 | const AccessRange range = barrier.range + base_address; |
| 494 | |
| 495 | access_context.UpdateMemoryAccessState(collect_barriers, range); |
| 496 | } |
| 497 | } |
| 498 | for (const SyncImageBarrier& barrier : barrier_set_.image_barriers) { |
| 499 | const BarrierScope barrier_scope(barrier.barrier, queue_id); |
| 500 | CollectBarriersFunctor collect_barriers(access_context, barrier_scope, barrier.barrier, barrier.layout_transition, |
| 501 | barrier.handle_index, pending_barriers); |
| 502 | |
| 503 | const auto& sub_state = SubState(*barrier.image); |
| 504 | const bool can_transition_depth_slices = CanTransitionDepthSlices( |
| 505 | exec_context.GetSyncState().extensions, sub_state.base.GetImageType(), sub_state.base.create_flags); |
| 506 | auto range_gen = sub_state.MakeImageRangeGen(barrier.subresource_range, can_transition_depth_slices); |
| 507 | |
| 508 | access_context.UpdateMemoryAccessState(collect_barriers, range_gen); |
| 509 | } |
| 510 |
nothing calls this directly
no test coverage detected