syncval: Refactor BarrierOps functors for events
Reorganized the barrier ops functors to be flexible enough for use in
wait events operations.
Change-Id: Id6d9524a65c81e31758cb111333a3f18a2f8c949
diff --git a/layers/synchronization_validation.cpp b/layers/synchronization_validation.cpp
index 9b57061..274c487 100644
--- a/layers/synchronization_validation.cpp
+++ b/layers/synchronization_validation.cpp
@@ -1220,22 +1220,25 @@
// This functor applies a collection of barriers, updating the "pending state" in each touched memory range, and optionally
// resolves the pending state. Suitable for processing Global memory barriers, or Subpass Barriers when the "final" barrier
// of a collection is known/present.
+struct PipelineBarrierOp {
+ SyncBarrier barrier;
+ bool layout_transition;
+ PipelineBarrierOp(const SyncBarrier &barrier_, bool layout_transition_)
+ : barrier(barrier_), layout_transition(layout_transition_) {}
+ PipelineBarrierOp() = default;
+ void operator()(ResourceAccessState *access_state) const { access_state->ApplyBarrier(barrier, layout_transition); }
+};
+
+template <typename BarrierOp>
class ApplyBarrierOpsFunctor {
public:
using Iterator = ResourceAccessRangeMap::iterator;
inline Iterator Infill(ResourceAccessRangeMap *accesses, Iterator pos, ResourceAccessRange range) const { return pos; }
- struct BarrierOp {
- SyncBarrier barrier;
- bool layout_transition;
- BarrierOp(const SyncBarrier &barrier_, bool layout_transition_)
- : barrier(barrier_), layout_transition(layout_transition_) {}
- BarrierOp() = default;
- };
Iterator operator()(ResourceAccessRangeMap *accesses, Iterator pos) const {
auto &access_state = pos->second;
- for (const auto op : barrier_ops_) {
- access_state.ApplyBarrier(op.barrier, op.layout_transition);
+ for (const auto &op : barrier_ops_) {
+ op(&access_state);
}
if (resolve_) {
@@ -1246,36 +1249,31 @@
return pos;
}
- // A valid tag is required IFF any of the barriers ops are a layout transition, as transitions are write ops
- ApplyBarrierOpsFunctor(bool resolve, size_t size_hint, const ResourceUsageTag &tag)
- : resolve_(resolve), barrier_ops_(), tag_(tag) {
- if (size_hint) {
- barrier_ops_.reserve(size_hint);
- }
- };
-
// A valid tag is required IFF layout_transition is true, as transitions are write ops
- ApplyBarrierOpsFunctor(bool resolve, const std::vector<SyncBarrier> &barriers, bool layout_transition,
- const ResourceUsageTag &tag)
- : resolve_(resolve), barrier_ops_(), tag_(tag) {
- barrier_ops_.reserve(barriers.size());
- for (const auto &barrier : barriers) {
- barrier_ops_.emplace_back(barrier, layout_transition);
- }
- }
-
- void PushBack(const SyncBarrier &barrier, bool layout_transition) { barrier_ops_.emplace_back(barrier, layout_transition); }
-
- void PushBack(const std::vector<SyncBarrier> &barriers, bool layout_transition) {
- barrier_ops_.reserve(barrier_ops_.size() + barriers.size());
- for (const auto &barrier : barriers) {
- barrier_ops_.emplace_back(barrier, layout_transition);
- }
- }
+ ApplyBarrierOpsFunctor(bool resolve, const std::vector<BarrierOp> &barrier_ops, const ResourceUsageTag &tag)
+ : resolve_(resolve), barrier_ops_(barrier_ops), tag_(tag) {}
private:
bool resolve_;
- std::vector<BarrierOp> barrier_ops_;
+ const std::vector<BarrierOp> &barrier_ops_;
+ const ResourceUsageTag &tag_;
+};
+
+// This functor resolves the pendinging state.
+class ResolvePendingBarrierFunctor {
+ public:
+ using Iterator = ResourceAccessRangeMap::iterator;
+ inline Iterator Infill(ResourceAccessRangeMap *accesses, Iterator pos, ResourceAccessRange range) const { return pos; }
+
+ Iterator operator()(ResourceAccessRangeMap *accesses, Iterator pos) const {
+ auto &access_state = pos->second;
+ access_state.ApplyPendingBarriers(tag_);
+ return pos;
+ }
+
+ ResolvePendingBarrierFunctor(const ResourceUsageTag &tag) : tag_(tag) {}
+
+ private:
const ResourceUsageTag &tag_;
};
@@ -1471,7 +1469,7 @@
// If there were no transitions skip this global map walk
if (transitions.size()) {
- ApplyBarrierOpsFunctor apply_pending_action(true /* resolve */, 0, tag);
+ ResolvePendingBarrierFunctor apply_pending_action(tag);
ApplyGlobalBarriers(apply_pending_action);
}
}
@@ -2253,8 +2251,13 @@
const auto &attachment = attachment_views_[transition.attachment];
const auto &last_trackback = subpass_contexts_[transition.prev_pass].GetDstExternalTrackBack();
assert(&subpass_contexts_[transition.prev_pass] == last_trackback.context);
- ApplyBarrierOpsFunctor barrier_ops(true /* resolve */, last_trackback.barriers, true /* layout transition */, tag);
- external_context->UpdateResourceAccess(*attachment->image_state, attachment->normalized_subresource_range, barrier_ops);
+ std::vector<PipelineBarrierOp> barrier_ops;
+ barrier_ops.reserve(last_trackback.barriers.size());
+ for (const auto &barrier : last_trackback.barriers) {
+ barrier_ops.emplace_back(barrier, true);
+ }
+ ApplyBarrierOpsFunctor<PipelineBarrierOp> barrier_action(true /* resolve */, barrier_ops, tag);
+ external_context->UpdateResourceAccess(*attachment->image_state, attachment->normalized_subresource_range, barrier_action);
}
}
@@ -2677,17 +2680,19 @@
VkPipelineStageFlags dst_exec_scope, SyncStageAccessFlags src_access_scope,
SyncStageAccessFlags dst_access_scope, uint32_t memory_barrier_count,
const VkMemoryBarrier *pMemoryBarriers, const ResourceUsageTag &tag) {
- ApplyBarrierOpsFunctor barriers_functor(true /* resolve */, std::min<uint32_t>(1, memory_barrier_count), tag);
+ std::vector<PipelineBarrierOp> barrier_ops;
+ barrier_ops.reserve(std::min<uint32_t>(1, memory_barrier_count));
for (uint32_t barrier_index = 0; barrier_index < memory_barrier_count; barrier_index++) {
const auto &barrier = pMemoryBarriers[barrier_index];
SyncBarrier sync_barrier(src_exec_scope, SyncStageAccess::AccessScope(src_access_scope, barrier.srcAccessMask),
dst_exec_scope, SyncStageAccess::AccessScope(dst_access_scope, barrier.dstAccessMask));
- barriers_functor.PushBack(sync_barrier, false);
+ barrier_ops.emplace_back(sync_barrier, false);
}
if (0 == memory_barrier_count) {
// If there are no global memory barriers, force an exec barrier
- barriers_functor.PushBack(SyncBarrier(src_exec_scope, 0, dst_exec_scope, 0), false);
+ barrier_ops.emplace_back(SyncBarrier(src_exec_scope, 0, dst_exec_scope, 0), false);
}
+ ApplyBarrierOpsFunctor<PipelineBarrierOp> barriers_functor(true /* resolve */, barrier_ops, tag);
context->ApplyGlobalBarriers(barriers_functor);
}