| 783 | } |
| 784 | |
| 785 | void ApplyBarriers(AccessState& access_state, const std::vector<SyncBarrier>& barriers, bool layout_transition, |
| 786 | ResourceUsageTag layout_transition_tag) { |
| 787 | // The common case of a single barrier. |
| 788 | // The pending barrier helper is unnecessary because there are no independent barriers to track. |
| 789 | // The barrier can be applied directly to the access state. |
| 790 | if (barriers.size() == 1) { |
| 791 | access_state.ApplyBarrier(BarrierScope(barriers[0]), barriers[0], layout_transition, vvl::kNoIndex32, |
| 792 | layout_transition_tag); |
| 793 | return; |
| 794 | } |
| 795 | |
| 796 | PendingBarriers pending_barriers; |
| 797 | if (layout_transition) { |
| 798 | // When layout transition is bundled with multiple barriers (e.g. multiple subpass dependencies |
| 799 | // can be associated with the same layout transition) we need to ensure that AddLayoutTransition() |
| 800 | // is called only once (it resets write state including applied barriers). That's the reason |
| 801 | // CollectPendingBarriers can't be used in this scenario. |
| 802 | // NOTE: CollectPendingBarriers works correctly for a common case when layout transition is defined |
| 803 | // by a single barrier |
| 804 | OrderingBarrier layout_ordering_barrier; |
| 805 | for (const SyncBarrier& barrier : barriers) { |
| 806 | layout_ordering_barrier.exec_scope |= barrier.src_exec_scope.exec_scope; |
| 807 | layout_ordering_barrier.access_scope |= barrier.src_access_scope; |
| 808 | } |
| 809 | pending_barriers.AddLayoutTransition(&access_state, layout_ordering_barrier, vvl::kNoIndex32); |
| 810 | |
| 811 | for (const SyncBarrier& barrier : barriers) { |
| 812 | pending_barriers.AddWriteBarrier(&access_state, barrier); |
| 813 | } |
| 814 | } else { |
| 815 | // There are multiple barriers. We can't apply them sequentially because they can form dependencies |
| 816 | // between themselves (result of the previous barrier might affect application of the next barrier). |
| 817 | // The APIs we are dealing require that the barriers in a set of barriers are applied independently. |
| 818 | // That's the intended use case of PendingBarriers helper. |
| 819 | for (const SyncBarrier& barrier : barriers) { |
| 820 | access_state.CollectPendingBarriers(BarrierScope(barrier), barrier, false, vvl::kNoIndex32, pending_barriers); |
| 821 | } |
| 822 | } |
| 823 | pending_barriers.Apply(layout_transition_tag); |
| 824 | } |
| 825 | |
| 826 | BarrierScope::BarrierScope(const SyncBarrier& barrier, QueueId scope_queue, ResourceUsageTag scope_tag) |
| 827 | : src_exec_scope(barrier.src_exec_scope.exec_scope), |
no test coverage detected