/*
 * Copyright (c) 2019-2026 Valve Corporation
 * Copyright (c) 2019-2026 LunarG, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sync/sync_op.h"
#include "sync/sync_renderpass.h"
#include "sync/sync_access_context.h"
#include "sync/sync_commandbuffer.h"
#include "sync/sync_image.h"
#include "sync/sync_validation.h"

#include "state_tracker/buffer_state.h"
#include "state_tracker/cmd_buffer_state.h"
#include "state_tracker/render_pass_state.h"

#include "utils/image_utils.h"
#include "utils/sync_utils.h"

namespace syncval {

// Range generators for to allow event scope filtration to be limited to the top of the resource access traversal pipeline
//
// Note: there is no "begin/end" or reset facility.  These are each written as "one time through" generators.
//
// Usage:
//  Constructor() -- initializes the generator to point to the begin of the space declared.
//  *  -- the current range of the generator empty signfies end
//  ++ -- advance to the next non-empty range (or end)

// Generate the ranges that are the intersection of range and the entries in the RangeMap
class MapRangesRangeGenerator {
  public:
    // Default constructed is safe to dereference for "empty" test, but for no other operation.
    MapRangesRangeGenerator() {
        // Default construction *must* be empty range
        assert(current_.empty());
    }
    MapRangesRangeGenerator(const AccessMap &filter, const AccessRange &range)
        : range_(range), map_(&filter), map_pos_(), current_() {
        SeekBegin();
    }
    MapRangesRangeGenerator(const MapRangesRangeGenerator &from) = default;

    const AccessRange &operator*() const { return current_; }
    const AccessRange *operator->() const { return &current_; }
    MapRangesRangeGenerator &operator++() {
        ++map_pos_;
        UpdateCurrent();
        return *this;
    }

    bool operator==(const MapRangesRangeGenerator &other) const { return current_ == other.current_; }

  protected:
    void UpdateCurrent() {
        if (map_pos_ != map_->end()) {
            current_ = range_ & map_pos_->first;
        } else {
            current_ = {};
        }
    }
    void SeekBegin() {
        map_pos_ = map_->LowerBound(range_.begin);
        UpdateCurrent();
    }

    // Adding this functionality here, to avoid gratuitous Base:: qualifiers in the derived class
    // Note: Not exposed in this classes public interface to encourage using a consistent ++/empty generator semantic
    template <typename Pred>
    MapRangesRangeGenerator &PredicatedIncrement(Pred &pred) {
        do {
            ++map_pos_;
        } while (map_pos_ != map_->end() && map_pos_->first.intersects(range_) && !pred(map_pos_));
        UpdateCurrent();
        return *this;
    }

    const AccessRange range_;
    const AccessMap *map_ = nullptr;
    AccessMap::const_iterator map_pos_;
    AccessRange current_;
};
using EventSimpleRangeGenerator = MapRangesRangeGenerator;

// Generate the ranges that are the intersection of the RangeGen ranges and the entries in the FilterMap
template <typename RangeGen>
class FilteredGeneratorGenerator {
  public:
    // Default constructed is safe to dereference for "empty" test, but for no other operation.
    FilteredGeneratorGenerator() : filter_(nullptr), gen_(), filter_pos_(), current_() {
        // Default construction for KeyType *must* be empty range
        assert(current_.empty());
    }
    FilteredGeneratorGenerator(const AccessMap &filter, RangeGen &gen) : filter_(&filter), gen_(gen), filter_pos_(), current_() {
        SeekBegin();
    }
    FilteredGeneratorGenerator(const FilteredGeneratorGenerator &from) = default;
    const AccessRange &operator*() const { return current_; }
    const AccessRange *operator->() const { return &current_; }
    FilteredGeneratorGenerator &operator++() {
        AccessRange gen_range = GenRange();
        AccessRange filter_range = FilterRange();
        current_ = {};
        while (gen_range.non_empty() && filter_range.non_empty() && current_.empty()) {
            if (gen_range.end > filter_range.end) {
                // if the generated range is beyond the filter_range, advance the filter range
                filter_range = AdvanceFilter();
            } else {
                gen_range = AdvanceGen();
            }
            current_ = gen_range & filter_range;
        }
        return *this;
    }

    bool operator==(const FilteredGeneratorGenerator &other) const { return current_ == other.current_; }

  private:
    AccessRange AdvanceFilter() {
        ++filter_pos_;
        auto filter_range = FilterRange();
        assert(filter_range.valid());
        if (filter_range.valid()) {
            FastForwardGen(filter_range);
        }
        return filter_range;
    }
    AccessRange AdvanceGen() {
        ++gen_;
        auto gen_range = GenRange();
        if (gen_range.valid()) {
            FastForwardFilter(gen_range);
        }
        return gen_range;
    }

    AccessRange FilterRange() const { return (filter_pos_ != filter_->end()) ? filter_pos_->first : AccessRange{}; }
    AccessRange GenRange() const { return *gen_; }

    AccessRange FastForwardFilter(const AccessRange &range) {
        auto filter_range = FilterRange();
        int retry_count = 0;
        const static int kRetryLimit = 2;  // TODO -- determine whether this limit is optimal
        while (!filter_range.empty() && (filter_range.end <= range.begin)) {
            if (retry_count < kRetryLimit) {
                ++filter_pos_;
                filter_range = FilterRange();
                retry_count++;
            } else {
                // Okay we've tried walking, do a seek.
                filter_pos_ = filter_->LowerBound(range.begin);
                break;
            }
        }
        return FilterRange();
    }

    // TODO: Consider adding "seek" (or an absolute bound "get" to range generators to make this walk
    // faster.
    AccessRange FastForwardGen(const AccessRange &range) {
        auto gen_range = GenRange();
        while (!gen_range.empty() && (gen_range.end <= range.begin)) {
            ++gen_;
            gen_range = GenRange();
        }
        return gen_range;
    }

    void SeekBegin() {
        auto gen_range = GenRange();
        if (gen_range.empty()) {
            current_ = {};
            filter_pos_ = filter_->end();
        } else {
            filter_pos_ = filter_->LowerBound(gen_range.begin);
            current_ = gen_range & FilterRange();
        }
    }

    const AccessMap *filter_ = nullptr;
    RangeGen gen_;
    AccessMap::const_iterator filter_pos_;
    AccessRange current_;
};

using EventImageRangeGenerator = FilteredGeneratorGenerator<subresource_adapter::ImageRangeGenerator>;

void BarrierSet::MakeMemoryBarriers(const SyncExecScope &src, const SyncExecScope &dst, uint32_t barrier_count,
                                    const VkMemoryBarrier *barriers) {
    memory_barriers.reserve(std::max<uint32_t>(1, barrier_count));
    for (const VkMemoryBarrier &barrier : vvl::make_span(barriers, barrier_count)) {
        SyncBarrier sync_barrier(src, barrier.srcAccessMask, dst, barrier.dstAccessMask);
        memory_barriers.emplace_back(sync_barrier);
    }

    // Ensure we have a barrier that handles execution dependencies.
    // NOTE: the reason to have execution barrier is explained in details in the comment for Sync2
    // MakeMemoryBarriers overload. The Sync1 implementation is much simpler since execution scopes
    // are the same for all barriers.
    if (barrier_count == 0) {
        memory_barriers.emplace_back(SyncBarrier(src, dst));
    }
    single_exec_scope = true;
    execution_dependency_barrier_count = (barrier_count == 0) ? 1 : 0;
}

void BarrierSet::MakeMemoryBarriers(VkQueueFlags queue_flags, const VkDependencyInfo &dep_info) {
    // Collect unique execution dependencies from buffer and image barriers.
    //
    // NOTE: the reason to collect execution dependencies in addition to original buffer/image
    // barriers is because syncval applies buffer/image barriers to the memory ranges defined
    // by the resource. But execution dependency can affect any resource/memory range, not
    // only the one specified by the barrier. For example, execution dependency synchronizes
    // all READ accesses that are in scope. To emulate this behavior we collect unique
    // execution dependencies and apply them to all memory accesses (don't specify access mask).
    small_vector<std::pair<VkPipelineStageFlags2, VkPipelineStageFlags2>, 4> buffer_image_barrier_exec_deps;
    for (const VkBufferMemoryBarrier2 &buffer_barrier :
         vvl::make_span(dep_info.pBufferMemoryBarriers, dep_info.bufferMemoryBarrierCount)) {
        const auto src_dst = std::make_pair(buffer_barrier.srcStageMask, buffer_barrier.dstStageMask);
        if (!buffer_image_barrier_exec_deps.Contains(src_dst)) {
            buffer_image_barrier_exec_deps.emplace_back(src_dst);
        }
    }
    for (const VkImageMemoryBarrier2 &image_barrier :
         vvl::make_span(dep_info.pImageMemoryBarriers, dep_info.imageMemoryBarrierCount)) {
        const auto src_dst = std::make_pair(image_barrier.srcStageMask, image_barrier.dstStageMask);
        if (!buffer_image_barrier_exec_deps.Contains(src_dst)) {
            buffer_image_barrier_exec_deps.emplace_back(src_dst);
        }
    }

    memory_barriers.reserve(dep_info.memoryBarrierCount + buffer_image_barrier_exec_deps.size());

    // Add global memory barriers specified in VkDependencyInfo
    for (const VkMemoryBarrier2 &barrier : vvl::make_span(dep_info.pMemoryBarriers, dep_info.memoryBarrierCount)) {
        auto src = SyncExecScope::MakeSrc(queue_flags, barrier.srcStageMask);
        auto dst = SyncExecScope::MakeDst(queue_flags, barrier.dstStageMask);
        memory_barriers.emplace_back(SyncBarrier(src, barrier.srcAccessMask, dst, barrier.dstAccessMask));
    }
    // Add execution dependencies from buffer and image barriers
    for (const auto &src_dst : buffer_image_barrier_exec_deps) {
        auto src = SyncExecScope::MakeSrc(queue_flags, src_dst.first);
        auto dst = SyncExecScope::MakeDst(queue_flags, src_dst.second);
        memory_barriers.emplace_back(SyncBarrier(src, dst));
    }
    single_exec_scope = false;
    execution_dependency_barrier_count = (uint32_t)buffer_image_barrier_exec_deps.size();
}

void BarrierSet::MakeBufferMemoryBarriers(const SyncValidator &sync_state, const SyncExecScope &src, const SyncExecScope &dst,
                                          uint32_t barrier_count, const VkBufferMemoryBarrier *barriers) {
    buffer_barriers.reserve(barrier_count);
    for (const VkBufferMemoryBarrier &barrier : vvl::make_span(barriers, barrier_count)) {
        if (auto buffer = sync_state.Get<vvl::Buffer>(barrier.buffer)) {
            const auto range = MakeRange(*buffer, barrier.offset, barrier.size);
            const SyncBarrier sync_barrier(src, barrier.srcAccessMask, dst, barrier.dstAccessMask);
            buffer_barriers.emplace_back(buffer, sync_barrier, range);
        }
    }
}

void BarrierSet::MakeBufferMemoryBarriers(const SyncValidator &sync_state, VkQueueFlags queue_flags, uint32_t barrier_count,
                                          const VkBufferMemoryBarrier2 *barriers) {
    buffer_barriers.reserve(barrier_count);
    for (const VkBufferMemoryBarrier2 &barrier : vvl::make_span(barriers, barrier_count)) {
        auto src = SyncExecScope::MakeSrc(queue_flags, barrier.srcStageMask);
        auto dst = SyncExecScope::MakeDst(queue_flags, barrier.dstStageMask);
        if (auto buffer = sync_state.Get<vvl::Buffer>(barrier.buffer)) {
            const auto range = MakeRange(*buffer, barrier.offset, barrier.size);
            const SyncBarrier sync_barrier(src, barrier.srcAccessMask, dst, barrier.dstAccessMask);
            buffer_barriers.emplace_back(buffer, sync_barrier, range);
        }
    }
}

void BarrierSet::MakeImageMemoryBarriers(const SyncValidator &sync_state, const SyncExecScope &src, const SyncExecScope &dst,
                                         uint32_t barrier_count, const VkImageMemoryBarrier *barriers,
                                         const DeviceExtensions &extensions) {
    image_barriers.reserve(barrier_count);
    for (const auto [index, barrier] : vvl::enumerate(barriers, barrier_count)) {
        if (auto image = sync_state.Get<vvl::Image>(barrier.image)) {
            auto subresource_range = image->NormalizeSubresourceRange(barrier.subresourceRange);

            // VK_REMAINING_ARRAY_LAYERS for sliced 3d image in the context of layout transition means image's depth extent.
            if (barrier.subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS &&
                CanTransitionDepthSlices(extensions, image->create_info)) {
                subresource_range.layerCount = image->create_info.extent.depth - subresource_range.baseArrayLayer;
            }

            const SyncBarrier sync_barrier(src, barrier.srcAccessMask, dst, barrier.dstAccessMask);
            const bool layout_transition = barrier.oldLayout != barrier.newLayout;
            image_barriers.emplace_back(image, sync_barrier, subresource_range, layout_transition, index);
        }
    }
}

void BarrierSet::MakeImageMemoryBarriers(const SyncValidator &sync_state, VkQueueFlags queue_flags, uint32_t barrier_count,
                                         const VkImageMemoryBarrier2 *barriers, const DeviceExtensions &extensions) {
    image_barriers.reserve(barrier_count);
    for (const auto [index, barrier] : vvl::enumerate(barriers, barrier_count)) {
        auto src = SyncExecScope::MakeSrc(queue_flags, barrier.srcStageMask);
        auto dst = SyncExecScope::MakeDst(queue_flags, barrier.dstStageMask);
        auto image = sync_state.Get<vvl::Image>(barrier.image);
        if (image) {
            auto subresource_range = image->NormalizeSubresourceRange(barrier.subresourceRange);

            // VK_REMAINING_ARRAY_LAYERS for sliced 3d image in the context of layout transition means image's depth extent.
            if (barrier.subresourceRange.layerCount == VK_REMAINING_ARRAY_LAYERS &&
                CanTransitionDepthSlices(extensions, image->create_info)) {
                subresource_range.layerCount = image->create_info.extent.depth - subresource_range.baseArrayLayer;
            }

            const SyncBarrier sync_barrier(src, barrier.srcAccessMask, dst, barrier.dstAccessMask);
            const bool layout_transition = barrier.oldLayout != barrier.newLayout;
            image_barriers.emplace_back(image, sync_barrier, subresource_range, layout_transition, index);
        }
    }
}

SyncOpPipelineBarrier::SyncOpPipelineBarrier(vvl::Func command, const SyncValidator &sync_state, VkQueueFlags queue_flags,
                                             VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
                                             uint32_t memory_barrier_count, const VkMemoryBarrier *memory_barriers,
                                             uint32_t buffer_barrier_count, const VkBufferMemoryBarrier *buffer_barriers,
                                             uint32_t image_barrier_count, const VkImageMemoryBarrier *image_barriers)
    : SyncOpBase(command) {
    const auto src_exec_scope = SyncExecScope::MakeSrc(queue_flags, src_stage_mask);
    const auto dst_exec_scope = SyncExecScope::MakeDst(queue_flags, dst_stage_mask);

    barrier_set_.src_exec_scope = src_exec_scope;
    barrier_set_.dst_exec_scope = dst_exec_scope;

    barrier_set_.MakeMemoryBarriers(src_exec_scope, dst_exec_scope, memory_barrier_count, memory_barriers);
    barrier_set_.MakeBufferMemoryBarriers(sync_state, src_exec_scope, dst_exec_scope, buffer_barrier_count, buffer_barriers);
    barrier_set_.MakeImageMemoryBarriers(sync_state, src_exec_scope, dst_exec_scope, image_barrier_count, image_barriers,
                                         sync_state.device_state->extensions);
}

SyncOpPipelineBarrier::SyncOpPipelineBarrier(vvl::Func command, const SyncValidator &sync_state, VkQueueFlags queue_flags,
                                             const VkDependencyInfo &dep_info)
    : SyncOpBase(command) {
    const ExecScopes stage_masks = sync_utils::GetExecScopes(dep_info);

    barrier_set_.src_exec_scope = SyncExecScope::MakeSrc(queue_flags, stage_masks.src);
    barrier_set_.dst_exec_scope = SyncExecScope::MakeDst(queue_flags, stage_masks.dst);

    barrier_set_.MakeMemoryBarriers(queue_flags, dep_info);
    barrier_set_.MakeBufferMemoryBarriers(sync_state, queue_flags, dep_info.bufferMemoryBarrierCount,
                                          dep_info.pBufferMemoryBarriers);
    barrier_set_.MakeImageMemoryBarriers(sync_state, queue_flags, dep_info.imageMemoryBarrierCount, dep_info.pImageMemoryBarriers,
                                         sync_state.device_state->extensions);
}

bool SyncOpPipelineBarrier::Validate(const CommandBufferAccessContext &cb_context) const {
    bool skip = false;
    const auto *context = cb_context.GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    // Validate Image Layout transitions
    for (const auto &image_barrier : barrier_set_.image_barriers) {
        if (!image_barrier.layout_transition) {
            continue;
        }
        const vvl::Image &image_state = *image_barrier.image;
        const bool can_transition_depth_slices =
            CanTransitionDepthSlices(cb_context.GetSyncState().extensions, image_state.create_info);
        const auto hazard = context->DetectImageBarrierHazard(
            image_state, image_barrier.barrier.src_exec_scope.exec_scope, image_barrier.barrier.src_access_scope,
            image_barrier.subresource_range, can_transition_depth_slices, AccessContext::kDetectAll);
        if (hazard.IsHazard()) {
            LogObjectList objlist(cb_context.GetCBState().Handle(), image_state.Handle());
            const Location loc(command_);
            const SyncValidator &sync_state = cb_context.GetSyncState();
            const std::string resource_description = sync_state.FormatHandle(image_state.Handle());
            const std::string error =
                sync_state.error_messages_.ImageBarrierError(hazard, cb_context, command_, resource_description, image_barrier);
            skip |= sync_state.SyncError(hazard.Hazard(), objlist, loc, error);
        }
    }
    return skip;
}

ResourceUsageTag SyncOpPipelineBarrier::Record(CommandBufferAccessContext *cb_context) {
    const auto tag = cb_context->NextCommandTag(command_);
    for (const auto &buffer_barrier : barrier_set_.buffer_barriers) {
        cb_context->AddCommandHandle(tag, buffer_barrier.buffer->Handle());
    }
    for (auto &image_barrier : barrier_set_.image_barriers) {
        if (image_barrier.layout_transition) {
            const auto tag_ex = cb_context->AddCommandHandle(tag, image_barrier.image->Handle());
            image_barrier.handle_index = tag_ex.handle_index;
        }
    }
    ReplayRecord(*cb_context, tag);
    return tag;
}

void SyncOpPipelineBarrier::ApplySingleBufferBarrier(CommandExecutionContext &exec_context, const SyncBufferBarrier &buffer_barrier,
                                                     const SyncBarrier &exec_dep_barrier) const {
    AccessContext *access_context = exec_context.GetCurrentAccessContext();
    const QueueId queue_id = exec_context.GetQueueId();

    if (SimpleBinding(*buffer_barrier.buffer)) {
        const BarrierScope barrier_scope(buffer_barrier.barrier, queue_id);
        ApplySingleBufferBarrierFunctor apply_barrier(*access_context, barrier_scope, buffer_barrier.barrier);

        const VkDeviceSize base_address = ResourceBaseAddress(*buffer_barrier.buffer);
        const AccessRange range = buffer_barrier.range + base_address;

        access_context->UpdateMemoryAccessState(apply_barrier, range);
    }
    access_context->RegisterGlobalBarrier(exec_dep_barrier, queue_id);
}

void SyncOpPipelineBarrier::ApplySingleImageBarrier(CommandExecutionContext &exec_context, const SyncImageBarrier &image_barrier,
                                                    const SyncBarrier &exec_dep_barrier, const ResourceUsageTag exec_tag) const {
    AccessContext *access_context = exec_context.GetCurrentAccessContext();
    const QueueId queue_id = exec_context.GetQueueId();

    const BarrierScope barrier_scope(image_barrier.barrier, queue_id);
    ApplySingleImageBarrierFunctor apply_barrier(*access_context, barrier_scope, image_barrier.barrier,
                                                 image_barrier.layout_transition, image_barrier.handle_index, exec_tag);

    const auto &sub_state = SubState(*image_barrier.image);
    const bool can_transition_depth_slices =
        CanTransitionDepthSlices(exec_context.GetSyncState().extensions, sub_state.base.create_info);
    auto range_gen = sub_state.MakeImageRangeGen(image_barrier.subresource_range, can_transition_depth_slices);

    access_context->UpdateMemoryAccessState(apply_barrier, range_gen);
    access_context->RegisterGlobalBarrier(exec_dep_barrier, queue_id);
}

void SyncOpPipelineBarrier::ApplySingleMemoryBarrier(CommandExecutionContext &exec_context,
                                                     const SyncBarrier &memory_barrier) const {
    AccessContext *access_context = exec_context.GetCurrentAccessContext();
    const QueueId queue_id = exec_context.GetQueueId();
    access_context->RegisterGlobalBarrier(memory_barrier, queue_id);
}

void SyncOpPipelineBarrier::ApplyMultipleBarriers(CommandExecutionContext &exec_context, ResourceUsageTag exec_tag) const {
    AccessContext *access_context = exec_context.GetCurrentAccessContext();
    const QueueId queue_id = exec_context.GetQueueId();

    // Apply markup action.
    // The markup action does not change any access state but it can trim the access map according to the
    // provided range and creates infill ranges if necessary (for layout transitions). The purpose of all
    // this is to ensure that after markup action the topology of access map ranges is finalized so we can
    // safely cache pointers to specific access states with a goal to apply pending barriers in the end.
    //
    // NOTE: it is enough to apply markup action to buffer and image barriers. The global barriers
    // do not use infill operations (no layout transitions) and also do not split access map ranges
    // because global barriers are applied to the full range.
    for (const SyncBufferBarrier &barrier : barrier_set_.buffer_barriers) {
        if (SimpleBinding(*barrier.buffer)) {
            const VkDeviceSize base_address = ResourceBaseAddress(*barrier.buffer);
            const AccessRange range = barrier.range + base_address;
            ApplyMarkupFunctor markup_action(false);
            access_context->UpdateMemoryAccessState(markup_action, range);
        }
    }
    for (const SyncImageBarrier &barrier : barrier_set_.image_barriers) {
        const auto &sub_state = SubState(*barrier.image);
        const bool can_transition_depth_slices =
            CanTransitionDepthSlices(exec_context.GetSyncState().extensions, sub_state.base.create_info);
        auto range_gen = sub_state.MakeImageRangeGen(barrier.subresource_range, can_transition_depth_slices);
        // TODO: check if we need: barrier.layout_transition && (queue_id == kQueueIdInvalid)
        ApplyMarkupFunctor markup_action(barrier.layout_transition);
        access_context->UpdateMemoryAccessState(markup_action, range_gen);
    }

    // Use PendingBarriers to collect barriers that must be applied independently
    PendingBarriers pending_barriers;
    for (const SyncBufferBarrier &barrier : barrier_set_.buffer_barriers) {
        if (SimpleBinding(*barrier.buffer)) {
            const BarrierScope barrier_scope(barrier.barrier, queue_id);
            CollectBarriersFunctor collect_barriers(*access_context, barrier_scope, barrier.barrier, false, vvl::kNoIndex32,
                                                    pending_barriers);

            const VkDeviceSize base_address = ResourceBaseAddress(*barrier.buffer);
            const AccessRange range = barrier.range + base_address;

            access_context->UpdateMemoryAccessState(collect_barriers, range);
        }
    }
    for (const SyncImageBarrier &barrier : barrier_set_.image_barriers) {
        const BarrierScope barrier_scope(barrier.barrier, queue_id);
        CollectBarriersFunctor collect_barriers(*access_context, barrier_scope, barrier.barrier, barrier.layout_transition,
                                                barrier.handle_index, pending_barriers);

        const auto &sub_state = SubState(*barrier.image);
        const bool can_transition_depth_slices =
            CanTransitionDepthSlices(exec_context.GetSyncState().extensions, sub_state.base.create_info);
        auto range_gen = sub_state.MakeImageRangeGen(barrier.subresource_range, can_transition_depth_slices);

        access_context->UpdateMemoryAccessState(collect_barriers, range_gen);
    }

    // Do kFullRange update only when there is multiple memory barriers.
    // For a single barrier we can use global barrier functionality.
    if (barrier_set_.memory_barriers.size() > 1) {
        for (const SyncBarrier &barrier : barrier_set_.memory_barriers) {
            const BarrierScope barrier_scope(barrier, queue_id);
            CollectBarriersFunctor collect_barriers(*access_context, barrier_scope, barrier, false, vvl::kNoIndex32,
                                                    pending_barriers);
            access_context->UpdateMemoryAccessState(collect_barriers, kFullRange);
        }
    }

    // Apply collected barriers to access states
    pending_barriers.Apply(exec_tag);

    // Register global barriers if we have the only memory barrier (likely execution dependency)
    if (barrier_set_.memory_barriers.size() == 1) {
        access_context->RegisterGlobalBarrier(barrier_set_.memory_barriers[0], queue_id);
    }
}

void SyncOpPipelineBarrier::ReplayRecord(CommandExecutionContext &exec_context, const ResourceUsageTag exec_tag) const {
    if (!exec_context.ValidForSyncOps()) {
        return;
    }

    const bool has_buffer_barriers = !barrier_set_.buffer_barriers.empty();
    const bool has_image_barriers = !barrier_set_.image_barriers.empty();

    const bool single_buffer_barrier = barrier_set_.buffer_barriers.size() == 1 &&
                                       barrier_set_.memory_barriers.size() == 1 &&  // buffer barrier exec dependency
                                       !has_image_barriers;

    const bool single_image_barrier = barrier_set_.image_barriers.size() == 1 &&
                                      barrier_set_.memory_barriers.size() == 1 &&  // image barrier exec dependency
                                      !has_buffer_barriers;

    const bool single_memory_barrier = barrier_set_.memory_barriers.size() == 1 && !has_buffer_barriers && !has_image_barriers;

    if (single_buffer_barrier) {
        ApplySingleBufferBarrier(exec_context, barrier_set_.buffer_barriers[0], barrier_set_.memory_barriers[0]);
    } else if (single_image_barrier) {
        ApplySingleImageBarrier(exec_context, barrier_set_.image_barriers[0], barrier_set_.memory_barriers[0], exec_tag);
    } else if (single_memory_barrier) {
        ApplySingleMemoryBarrier(exec_context, barrier_set_.memory_barriers[0]);
    } else {
        ApplyMultipleBarriers(exec_context, exec_tag);
    }

    SyncEventsContext *events_context = exec_context.GetCurrentEventsContext();
    if (barrier_set_.single_exec_scope) {
        events_context->ApplyBarrier(barrier_set_.src_exec_scope, barrier_set_.dst_exec_scope, exec_tag);
    } else {
        for (const auto &barrier : barrier_set_.memory_barriers) {
            events_context->ApplyBarrier(barrier.src_exec_scope, barrier.dst_exec_scope, exec_tag);
        }
    }
}

bool SyncOpPipelineBarrier::ReplayValidate(ReplayState &replay, ResourceUsageTag recorded_tag) const {
    // The layout transitions happen at the replay tag
    ResourceUsageRange first_use_range = {recorded_tag, recorded_tag + 1};
    return replay.DetectFirstUseHazard(first_use_range);
}

SyncOpWaitEvents::SyncOpWaitEvents(vvl::Func command, const SyncValidator &sync_state, VkQueueFlags queue_flags,
                                   uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags srcStageMask,
                                   VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount,
                                   const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount,
                                   const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
                                   const VkImageMemoryBarrier *pImageMemoryBarriers)
    : SyncOpBase(command), barrier_sets_(1) {
    auto &barrier_set = barrier_sets_[0];
    const auto src_exec_scope = SyncExecScope::MakeSrc(queue_flags, srcStageMask);
    const auto dst_exec_scope = SyncExecScope::MakeDst(queue_flags, dstStageMask);

    barrier_set.src_exec_scope = src_exec_scope;
    barrier_set.dst_exec_scope = dst_exec_scope;

    barrier_set.MakeMemoryBarriers(src_exec_scope, dst_exec_scope, memoryBarrierCount, pMemoryBarriers);
    barrier_set.MakeBufferMemoryBarriers(sync_state, src_exec_scope, dst_exec_scope, bufferMemoryBarrierCount,
                                         pBufferMemoryBarriers);
    barrier_set.MakeImageMemoryBarriers(sync_state, src_exec_scope, dst_exec_scope, imageMemoryBarrierCount, pImageMemoryBarriers,
                                        sync_state.device_state->extensions);

    MakeEventsList(sync_state, eventCount, pEvents);
}

SyncOpWaitEvents::SyncOpWaitEvents(vvl::Func command, const SyncValidator &sync_state, VkQueueFlags queue_flags,
                                   uint32_t eventCount, const VkEvent *pEvents, const VkDependencyInfo *pDependencyInfo)
    : SyncOpBase(command), barrier_sets_(eventCount) {
    for (uint32_t i = 0; i < eventCount; i++) {
        const auto &dep_info = pDependencyInfo[i];
        auto &barrier_set = barrier_sets_[i];
        auto stage_masks = sync_utils::GetExecScopes(dep_info);

        barrier_set.src_exec_scope = SyncExecScope::MakeSrc(queue_flags, stage_masks.src);
        barrier_set.dst_exec_scope = SyncExecScope::MakeDst(queue_flags, stage_masks.dst);

        barrier_set.MakeMemoryBarriers(queue_flags, dep_info);
        barrier_set.MakeBufferMemoryBarriers(sync_state, queue_flags, dep_info.bufferMemoryBarrierCount,
                                             dep_info.pBufferMemoryBarriers);
        barrier_set.MakeImageMemoryBarriers(sync_state, queue_flags, dep_info.imageMemoryBarrierCount,
                                            dep_info.pImageMemoryBarriers, sync_state.device_state->extensions);
    }
    MakeEventsList(sync_state, eventCount, pEvents);
}

const char *const SyncOpWaitEvents::kIgnored = "Wait operation is ignored for this event.";

bool SyncOpWaitEvents::Validate(const CommandBufferAccessContext &cb_context) const {
    bool skip = false;
    const auto &sync_state = cb_context.GetSyncState();
    const VkCommandBuffer command_buffer_handle = cb_context.GetCBState().VkHandle();

    // This is only interesting at record and not replay (Execute/Submit) time.
    for (size_t barrier_set_index = 0; barrier_set_index < barrier_sets_.size(); barrier_set_index++) {
        const auto &barrier_set = barrier_sets_[barrier_set_index];
        if (barrier_set.single_exec_scope) {
            const Location loc(command_);
            if (barrier_set.src_exec_scope.mask_param & VK_PIPELINE_STAGE_HOST_BIT) {
                const std::string vuid = std::string("SYNC-") + std::string(CmdName()) + std::string("-hostevent-unsupported");
                sync_state.LogInfo(vuid, command_buffer_handle, loc,
                                   "srcStageMask includes %s, unsupported by synchronization validation.",
                                   string_VkPipelineStageFlagBits(VK_PIPELINE_STAGE_HOST_BIT));
            } else {
                const auto &barriers = barrier_set.memory_barriers;
                for (size_t barrier_index = 0; barrier_index < barriers.size(); barrier_index++) {
                    const auto &barrier = barriers[barrier_index];
                    if (barrier.src_exec_scope.mask_param & VK_PIPELINE_STAGE_HOST_BIT) {
                        const std::string vuid =
                            std::string("SYNC-") + std::string(CmdName()) + std::string("-hostevent-unsupported");

                        sync_state.LogInfo(vuid, command_buffer_handle, loc,
                                           "srcStageMask %s of %s %zu, %s %zu, unsupported by synchronization validation.",
                                           string_VkPipelineStageFlagBits(VK_PIPELINE_STAGE_HOST_BIT), "pDependencyInfo",
                                           barrier_set_index, "pMemoryBarriers", barrier_index);
                    }
                }
            }
        }
    }

    // The rest is common to record time and replay time.
    skip |= DoValidate(cb_context, ResourceUsageRecord::kMaxIndex);
    return skip;
}

bool SyncOpWaitEvents::DoValidate(const CommandExecutionContext &exec_context, const ResourceUsageTag base_tag) const {
    bool skip = false;
    const auto &sync_state = exec_context.GetSyncState();
    const QueueId queue_id = exec_context.GetQueueId();

    VkPipelineStageFlags2 event_stage_masks = 0U;
    VkPipelineStageFlags2 barrier_mask_params = 0U;
    bool events_not_found = false;
    const auto *events_context = exec_context.GetCurrentEventsContext();
    assert(events_context);
    size_t barrier_set_index = 0;
    size_t barrier_set_incr = (barrier_sets_.size() == 1) ? 0 : 1;
    const Location loc(command_);
    for (const auto &event : events_) {
        const auto *sync_event = events_context->Get(event.get());
        const auto &barrier_set = barrier_sets_[barrier_set_index];
        if (!sync_event) {
            // NOTE PHASE2: This is where we'll need queue submit time validation to come back and check the srcStageMask bits
            //              or solve this with replay creating the SyncEventState in the queue context... also this will be a
            //              new validation error... wait without previously submitted set event...
            events_not_found = true;  // Demote "extra_stage_bits" error to warning, to avoid false positives at *record time*
            barrier_set_index += barrier_set_incr;
            continue;  // Core, Lifetimes, or Param check needs to catch invalid events.
        }

        // For replay calls, don't revalidate "same command buffer" events
        if (sync_event->last_command_tag >= base_tag) continue;

        const VkEvent event_handle = sync_event->event->VkHandle();
        // TODO add "destroyed" checks

        if (sync_event->first_scope) {
            // Only accumulate barrier and event stages if there is a pending set in the current context
            barrier_mask_params |= barrier_set.src_exec_scope.mask_param;
            event_stage_masks |= sync_event->scope.mask_param;
        }

        const auto &src_exec_scope = barrier_set.src_exec_scope;

        const auto ignore_reason = sync_event->IsIgnoredByWait(command_, src_exec_scope.mask_param);
        if (ignore_reason) {
            switch (ignore_reason) {
                case SyncEventState::ResetWaitRace:
                case SyncEventState::Reset2WaitRace: {
                    // Four permuations of Reset and Wait calls...
                    const char *vuid = (command_ == vvl::Func::vkCmdWaitEvents) ? "VUID-vkCmdResetEvent-event-03834"
                                                                                : "VUID-vkCmdResetEvent-event-03835";
                    if (ignore_reason == SyncEventState::Reset2WaitRace) {
                        vuid = (command_ == vvl::Func::vkCmdWaitEvents) ? "VUID-vkCmdResetEvent2-event-03831"
                                                                        : "VUID-vkCmdResetEvent2-event-03832";
                    }
                    const char *const message =
                        "%s %s operation following %s without intervening execution barrier, may cause race condition. %s";
                    skip |= sync_state.LogError(vuid, event_handle, loc, message, sync_state.FormatHandle(event_handle).c_str(),
                                                CmdName(), vvl::String(sync_event->last_command), kIgnored);
                    break;
                }
                case SyncEventState::SetRace: {
                    // Issue error message that Wait is waiting on an signal subject to race condition, and is thus ignored for
                    // this event
                    const char *const vuid = "SYNC-vkCmdWaitEvents-unsynchronized-setops";
                    const char *const message =
                        "%s Unsychronized %s calls result in race conditions w.r.t. event signalling, %s %s";
                    const char *const reason = "First synchronization scope is undefined.";
                    skip |= sync_state.LogError(vuid, event_handle, loc, message, sync_state.FormatHandle(event_handle).c_str(),
                                                vvl::String(sync_event->last_command), reason, kIgnored);
                    break;
                }
                case SyncEventState::MissingStageBits: {
                    const auto missing_bits = sync_event->scope.mask_param & ~src_exec_scope.mask_param;
                    // Issue error message that event waited for is not in wait events scope
                    const char *const vuid = "VUID-vkCmdWaitEvents-srcStageMask-01158";
                    const char *const message =
                        "%s stageMask %s includes stages not present in srcStageMask %s. Stages missing from srcStageMask: %s. %s";
                    skip |= sync_state.LogError(vuid, event_handle, loc, message, sync_state.FormatHandle(event_handle).c_str(),
                                                sync_utils::StringPipelineStageFlags(sync_event->scope.mask_param).c_str(),
                                                sync_utils::StringPipelineStageFlags(src_exec_scope.mask_param).c_str(),
                                                sync_utils::StringPipelineStageFlags(missing_bits).c_str(), kIgnored);
                    break;
                }
                case SyncEventState::SetVsWait2: {
                    skip |= sync_state.LogError(
                        "VUID-vkCmdWaitEvents2-pEvents-03837", event_handle, loc, "Follows set of %s by %s. Disallowed.",
                        sync_state.FormatHandle(event_handle).c_str(), vvl::String(sync_event->last_command));
                    break;
                }
                case SyncEventState::MissingSetEvent: {
                    // TODO: There are conditions at queue submit time where we can definitively say that
                    // a missing set event is an error.  Add those if not captured in CoreChecks
                    break;
                }
                default:
                    assert(ignore_reason == SyncEventState::NotIgnored);
            }
        } else if (barrier_set.image_barriers.size()) {
            const auto &image_memory_barriers = barrier_set.image_barriers;
            const auto *context = exec_context.GetCurrentAccessContext();
            assert(context);
            for (const auto &image_memory_barrier : image_memory_barriers) {
                if (!image_memory_barrier.layout_transition) continue;
                const auto *image_state = image_memory_barrier.image.get();
                if (!image_state) continue;
                const auto &subresource_range = image_memory_barrier.subresource_range;
                const auto &src_access_scope = image_memory_barrier.barrier.src_access_scope;
                const auto hazard = context->DetectImageBarrierHazard(
                    *image_state, subresource_range, sync_event->scope.exec_scope, src_access_scope, queue_id,
                    sync_event->FirstScope(), sync_event->first_scope_tag, AccessContext::DetectOptions::kDetectAll);
                if (hazard.IsHazard()) {
                    LogObjectList objlist(exec_context.Handle(), image_state->Handle());
                    const std::string resource_description = sync_state.FormatHandle(image_state->Handle());
                    const std::string error = sync_state.error_messages_.ImageBarrierError(
                        hazard, exec_context, command_, resource_description, image_memory_barrier);
                    skip |= sync_state.SyncError(hazard.Hazard(), image_state->Handle(), loc, error);
                    break;
                }
            }
        }
        // TODO:  Add infrastructure for checking pDependencyInfo's vs. CmdSetEvent2 VUID - vkCmdWaitEvents2KHR - pEvents -
        // 03839
        barrier_set_index += barrier_set_incr;
    }

    // Note that we can't check for HOST in pEvents as we don't track that set event type
    const auto extra_stage_bits = (barrier_mask_params & ~VK_PIPELINE_STAGE_2_HOST_BIT) & ~event_stage_masks;
    if (extra_stage_bits) {
        assert(vvl::Func::vkCmdWaitEvents == command_);
        // Issue error message that event waited for is not in wait events scope
        const char *const message =
            "srcStageMask 0x%" PRIx64 " contains stages not present in pEvents stageMask. Extra stages are %s.%s";
        const auto handle = exec_context.Handle();
        if (!events_not_found) {
            skip |= sync_state.LogError("VUID-vkCmdWaitEvents-srcStageMask-01158", handle, loc, message, barrier_mask_params,
                                        sync_utils::StringPipelineStageFlags(extra_stage_bits).c_str(), "");
        }
    }
    return skip;
}

ResourceUsageTag SyncOpWaitEvents::Record(CommandBufferAccessContext *cb_context) {
    const auto tag = cb_context->NextCommandTag(command_);

    ReplayRecord(*cb_context, tag);
    return tag;
}

// Need to restrict to only valid exec and access scope for this event
static SyncBarrier RestrictToEvent(const SyncBarrier &barrier, const SyncEventState &sync_event) {
    SyncBarrier result = barrier;
    result.src_exec_scope.exec_scope = sync_event.scope.exec_scope & barrier.src_exec_scope.exec_scope;
    result.src_access_scope = sync_event.scope.valid_accesses & barrier.src_access_scope;
    return result;
}

void SyncOpWaitEvents::ReplayRecord(CommandExecutionContext &exec_context, ResourceUsageTag exec_tag) const {
    // Unlike PipelineBarrier, WaitEvent is *not* limited to accesses within the current subpass (if any) and thus needs to import
    // all accesses. Can instead import for all first_scopes, or a union of them, if this becomes a performance/memory issue,
    // but with no idea of the performance of the union, nor of whether it even matters... take the simplest approach here,
    if (!exec_context.ValidForSyncOps()) return;
    AccessContext *access_context = exec_context.GetCurrentAccessContext();
    SyncEventsContext *events_context = exec_context.GetCurrentEventsContext();
    const QueueId queue_id = exec_context.GetQueueId();

    access_context->ResolveAllSubpassDependencies();

    assert(barrier_sets_.size() == 1 || (barrier_sets_.size() == events_.size()));

    // Apply markup action.
    // The markup action does not change any access state but it can trim the access map according to the
    // provided range and creates infill ranges if necessary (for layout transitions). The purpose of all
    // this is to ensure that after markup action the topology of access map ranges is finalized for the
    // duration of barrier application (so we can cache pointers to specific access states with a goal
    // to apply pending barriers in the end).
    //
    // NOTE: event's global barriers can split() access map because EventSimpleRangeGenerator filters kFullRange.
    // That's why, in contrast to SyncOpPipelineBarrier, we need apply markup action also to global barriers.
    // TODO: need a test that demonstrates this (when doing some work on syncval events)
    size_t barrier_set_index = 0;
    size_t barrier_set_incr = (barrier_sets_.size() == 1) ? 0 : 1;
    for (auto &event_shared : events_) {
        if (!event_shared.get()) continue;
        auto *sync_event = events_context->GetFromShared(event_shared);

        sync_event->last_command = command_;
        sync_event->last_command_tag = exec_tag;

        const auto &barrier_set = barrier_sets_[barrier_set_index];
        if (!sync_event->IsIgnoredByWait(command_, barrier_set.src_exec_scope.mask_param)) {
            for (const SyncBufferBarrier &barrier : barrier_set.buffer_barriers) {
                if (SimpleBinding(*barrier.buffer)) {
                    const VkDeviceSize base_address = ResourceBaseAddress(*barrier.buffer);
                    const AccessRange range = barrier.range + base_address;
                    EventSimpleRangeGenerator filtered_range_gen(sync_event->FirstScope(), range);
                    ApplyMarkupFunctor markup_action(false);
                    access_context->UpdateMemoryAccessState(markup_action, filtered_range_gen);
                }
            }
            for (const SyncImageBarrier &barrier : barrier_set.image_barriers) {
                const auto &sub_state = SubState(*barrier.image);
                const bool can_transition_depth_slices =
                    CanTransitionDepthSlices(exec_context.GetSyncState().extensions, sub_state.base.create_info);
                ImageRangeGen range_gen = sub_state.MakeImageRangeGen(barrier.subresource_range, can_transition_depth_slices);
                EventImageRangeGenerator filtered_range_gen(sync_event->FirstScope(), range_gen);
                ApplyMarkupFunctor markup_action(barrier.layout_transition);
                access_context->UpdateMemoryAccessState(markup_action, filtered_range_gen);
            }
            auto global_barriers_range_gen = EventSimpleRangeGenerator(sync_event->FirstScope(), kFullRange);
            ApplyMarkupFunctor markup_action(false);
            access_context->UpdateMemoryAccessState(markup_action, global_barriers_range_gen);
        }
        barrier_set_index += barrier_set_incr;
    }

    // Apply barriers independently and store the result in the pending object.
    PendingBarriers pending_barriers;
    barrier_set_index = 0;
    barrier_set_incr = (barrier_sets_.size() == 1) ? 0 : 1;
    for (auto &event_shared : events_) {
        if (!event_shared.get()) continue;
        auto *sync_event = events_context->GetFromShared(event_shared);

        const auto &barrier_set = barrier_sets_[barrier_set_index];
        const auto &dst = barrier_set.dst_exec_scope;
        if (!sync_event->IsIgnoredByWait(command_, barrier_set.src_exec_scope.mask_param)) {
            // These apply barriers one at a time as the are restricted to the resource ranges specified per each barrier,
            // but do not update the dependency chain information (but set the "pending" state) // s.t. the order independence
            // of the barriers is maintained.

            for (const SyncBufferBarrier &barrier : barrier_set.buffer_barriers) {
                if (SimpleBinding(*barrier.buffer)) {
                    const SyncBarrier event_barrier = RestrictToEvent(barrier.barrier, *sync_event);
                    const BarrierScope barrier_scope(event_barrier, queue_id, sync_event->first_scope_tag);
                    CollectBarriersFunctor collect_barriers(*access_context, barrier_scope, event_barrier, false, vvl::kNoIndex32,
                                                            pending_barriers);

                    const VkDeviceSize base_address = ResourceBaseAddress(*barrier.buffer);
                    const AccessRange range = barrier.range + base_address;
                    EventSimpleRangeGenerator range_gen(sync_event->FirstScope(), range);

                    access_context->UpdateMemoryAccessState(collect_barriers, range_gen);
                }
            }
            for (const SyncImageBarrier &barrier : barrier_set.image_barriers) {
                const SyncBarrier event_barrier = RestrictToEvent(barrier.barrier, *sync_event);
                const BarrierScope barrier_scope(event_barrier, queue_id, sync_event->first_scope_tag);
                CollectBarriersFunctor collect_barriers(*access_context, barrier_scope, event_barrier, barrier.layout_transition,
                                                        barrier.handle_index, pending_barriers);

                const auto &sub_state = SubState(*barrier.image);
                const bool can_transition_depth_slices =
                    CanTransitionDepthSlices(exec_context.GetSyncState().extensions, sub_state.base.create_info);
                ImageRangeGen range_gen = sub_state.MakeImageRangeGen(barrier.subresource_range, can_transition_depth_slices);
                EventImageRangeGenerator filtered_range_gen(sync_event->FirstScope(), range_gen);

                access_context->UpdateMemoryAccessState(collect_barriers, filtered_range_gen);
            }
            // TODO: because each iteration applies functor to the same range, investigate if it is
            // beneficial for the functor to support multiple barriers, so we traverse access map once.
            auto global_range_gen = EventSimpleRangeGenerator(sync_event->FirstScope(), kFullRange);
            for (const auto &barrier : barrier_set.memory_barriers) {
                const SyncBarrier event_barrier = RestrictToEvent(barrier, *sync_event);
                const BarrierScope barrier_scope(event_barrier, queue_id, sync_event->first_scope_tag);
                CollectBarriersFunctor collect_barriers(*access_context, barrier_scope, event_barrier, false, vvl::kNoIndex32,
                                                        pending_barriers);

                auto range_gen = global_range_gen;  // intentional copy
                access_context->UpdateMemoryAccessState(collect_barriers, range_gen);
            }

            // Apply the global barrier to the event itself (for race condition tracking)
            // Events don't happen at a stage, so we need to store the unexpanded ALL_COMMANDS if set for inter-event-calls
            sync_event->barriers = dst.mask_param & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
            sync_event->barriers |= dst.exec_scope;
        } else {
            // We ignored this wait, so we don't have any effective synchronization barriers for it.
            sync_event->barriers = 0U;
        }
        barrier_set_index += barrier_set_incr;
    }

    // Update access states with collected barriers
    pending_barriers.Apply(exec_tag);
}

bool SyncOpWaitEvents::ReplayValidate(ReplayState &replay, ResourceUsageTag recorded_tag) const {
    return DoValidate(replay.GetExecutionContext(), replay.GetBaseTag() + recorded_tag);
}

void SyncOpWaitEvents::MakeEventsList(const SyncValidator &sync_state, uint32_t event_count, const VkEvent *events) {
    events_.reserve(event_count);
    for (uint32_t event_index = 0; event_index < event_count; event_index++) {
        events_.emplace_back(sync_state.Get<vvl::Event>(events[event_index]));
    }
}

SyncOpResetEvent::SyncOpResetEvent(vvl::Func command, const SyncValidator &sync_state, VkQueueFlags queue_flags, VkEvent event,
                                   VkPipelineStageFlags2 stageMask)
    : SyncOpBase(command), event_(sync_state.Get<vvl::Event>(event)), exec_scope_(SyncExecScope::MakeSrc(queue_flags, stageMask)) {}

bool SyncOpResetEvent::Validate(const CommandBufferAccessContext &cb_context) const {
    return DoValidate(cb_context, ResourceUsageRecord::kMaxIndex);
}

bool SyncOpResetEvent::DoValidate(const CommandExecutionContext &exec_context, const ResourceUsageTag base_tag) const {
    auto *events_context = exec_context.GetCurrentEventsContext();
    assert(events_context);
    bool skip = false;
    if (!events_context) return skip;

    const auto &sync_state = exec_context.GetSyncState();
    const auto *sync_event = events_context->Get(event_);
    if (!sync_event) return skip;  // Core, Lifetimes, or Param check needs to catch invalid events.

    if (sync_event->last_command_tag > base_tag) return skip;  // if we validated this in recording of the secondary, don't repeat

    const char *const set_wait =
        "%s %s operation following %s without intervening execution barrier, is a race condition and may result in data "
        "hazards.";
    const char *message = set_wait;  // Only one message this call.
    if (!sync_event->HasBarrier(exec_scope_.mask_param, exec_scope_.exec_scope)) {
        const char *vuid = nullptr;
        switch (sync_event->last_command) {
            case vvl::Func::vkCmdSetEvent:
            case vvl::Func::vkCmdSetEvent2KHR:
            case vvl::Func::vkCmdSetEvent2:
                // Needs a barrier between set and reset
                vuid = "SYNC-vkCmdResetEvent-missingbarrier-set";
                break;
            case vvl::Func::vkCmdWaitEvents:
            case vvl::Func::vkCmdWaitEvents2KHR:
            case vvl::Func::vkCmdWaitEvents2: {
                // Needs to be in the barriers chain (either because of a barrier, or because of dstStageMask
                vuid = "SYNC-vkCmdResetEvent-missingbarrier-wait";
                break;
            }
            case vvl::Func::Empty:
            case vvl::Func::vkCmdResetEvent:
            case vvl::Func::vkCmdResetEvent2KHR:
            case vvl::Func::vkCmdResetEvent2:
                break;  // Valid, but nothing to do
            default:
                assert(false);
                break;
        }
        if (vuid) {
            const Location loc(command_);
            skip |= sync_state.LogError(vuid, event_->Handle(), loc, message, sync_state.FormatHandle(event_->Handle()).c_str(),
                                        CmdName(), vvl::String(sync_event->last_command));
        }
    }
    return skip;
}

ResourceUsageTag SyncOpResetEvent::Record(CommandBufferAccessContext *cb_context) {
    const auto tag = cb_context->NextCommandTag(command_);
    ReplayRecord(*cb_context, tag);
    return tag;
}

bool SyncOpResetEvent::ReplayValidate(ReplayState &replay, ResourceUsageTag recorded_tag) const {
    return DoValidate(replay.GetExecutionContext(), replay.GetBaseTag() + recorded_tag);
}

void SyncOpResetEvent::ReplayRecord(CommandExecutionContext &exec_context, ResourceUsageTag exec_tag) const {
    if (!exec_context.ValidForSyncOps()) return;
    SyncEventsContext *events_context = exec_context.GetCurrentEventsContext();

    auto *sync_event = events_context->GetFromShared(event_);
    if (!sync_event) return;  // Core, Lifetimes, or Param check needs to catch invalid events.

    // Update the event state
    sync_event->last_command = command_;
    sync_event->last_command_tag = exec_tag;
    sync_event->unsynchronized_set = vvl::Func::Empty;
    sync_event->ResetFirstScope();
    sync_event->barriers = 0U;
}

SyncOpSetEvent::SyncOpSetEvent(vvl::Func command, const SyncValidator &sync_state, VkQueueFlags queue_flags, VkEvent event,
                               VkPipelineStageFlags2 stageMask, const AccessContext *access_context)
    : SyncOpBase(command),
      event_(sync_state.Get<vvl::Event>(event)),
      src_exec_scope_(SyncExecScope::MakeSrc(queue_flags, stageMask)),
      dep_info_() {
    // Snapshot the current access_context for later inspection at wait time.
    // NOTE: This appears brute force, but given that we only save a "first-last" model of access history, the current
    //       access context (include barrier state for chaining) won't necessarily contain the needed information at Wait
    //       or Submit time reference.
    if (access_context) {
        auto new_context = std::make_shared<AccessContext>(sync_state);
        new_context->InitFrom(*access_context);
        recorded_context_ = new_context;
    }
}

SyncOpSetEvent::SyncOpSetEvent(vvl::Func command, const SyncValidator &sync_state, VkQueueFlags queue_flags, VkEvent event,
                               const VkDependencyInfo &dep_info, const AccessContext *access_context)
    : SyncOpBase(command),
      event_(sync_state.Get<vvl::Event>(event)),
      src_exec_scope_(SyncExecScope::MakeSrc(queue_flags, sync_utils::GetExecScopes(dep_info).src)),
      dep_info_(new vku::safe_VkDependencyInfo(&dep_info)) {
    if (access_context) {
        auto new_context = std::make_shared<AccessContext>(sync_state);
        new_context->InitFrom(*access_context);
        recorded_context_ = new_context;
    }
}

bool SyncOpSetEvent::Validate(const CommandBufferAccessContext &cb_context) const {
    return DoValidate(cb_context, ResourceUsageRecord::kMaxIndex);
}
bool SyncOpSetEvent::ReplayValidate(ReplayState &replay, ResourceUsageTag recorded_tag) const {
    return DoValidate(replay.GetExecutionContext(), replay.GetBaseTag() + recorded_tag);
}

bool SyncOpSetEvent::DoValidate(const CommandExecutionContext &exec_context, const ResourceUsageTag base_tag) const {
    bool skip = false;

    const auto &sync_state = exec_context.GetSyncState();
    auto *events_context = exec_context.GetCurrentEventsContext();
    assert(events_context);
    if (!events_context) return skip;

    const auto *sync_event = events_context->Get(event_);
    if (!sync_event) return skip;  // Core, Lifetimes, or Param check needs to catch invalid events.

    if (sync_event->last_command_tag >= base_tag) return skip;  // for replay we don't want to revalidate internal "last commmand"

    const char *const reset_set =
        "%s %s operation following %s without intervening execution barrier, is a race condition and may result in data "
        "hazards.";
    const char *const wait =
        "%s %s operation following %s without intervening vkCmdResetEvent, may result in data hazard and is ignored.";

    if (!sync_event->HasBarrier(src_exec_scope_.mask_param, src_exec_scope_.exec_scope)) {
        const char *vuid_stem = nullptr;
        const char *message = nullptr;
        switch (sync_event->last_command) {
            case vvl::Func::vkCmdResetEvent:
            case vvl::Func::vkCmdResetEvent2KHR:
            case vvl::Func::vkCmdResetEvent2:
                // Needs a barrier between reset and set
                vuid_stem = "-missingbarrier-reset";
                message = reset_set;
                break;
            case vvl::Func::vkCmdSetEvent:
            case vvl::Func::vkCmdSetEvent2KHR:
            case vvl::Func::vkCmdSetEvent2:
                // Needs a barrier between set and set
                vuid_stem = "-missingbarrier-set";
                message = reset_set;
                break;
            case vvl::Func::vkCmdWaitEvents:
            case vvl::Func::vkCmdWaitEvents2KHR:
            case vvl::Func::vkCmdWaitEvents2:
                // Needs a barrier or is in second execution scope
                vuid_stem = "-missingbarrier-wait";
                message = wait;
                break;
            default:
                // The only other valid last command that wasn't one.
                assert(sync_event->last_command == vvl::Func::Empty);
                break;
        }
        if (vuid_stem) {
            assert(nullptr != message);
            const Location loc(command_);
            std::string vuid("SYNC-");
            vuid.append(CmdName()).append(vuid_stem);
            skip |=
                sync_state.LogError(vuid.c_str(), event_->Handle(), loc, message, sync_state.FormatHandle(event_->Handle()).c_str(),
                                    CmdName(), vvl::String(sync_event->last_command));
        }
    }

    return skip;
}

ResourceUsageTag SyncOpSetEvent::Record(CommandBufferAccessContext *cb_context) {
    const auto tag = cb_context->NextCommandTag(command_);
    auto *events_context = cb_context->GetCurrentEventsContext();
    const QueueId queue_id = cb_context->GetQueueId();
    assert(recorded_context_);
    if (recorded_context_ && events_context) {
        DoRecord(queue_id, tag, recorded_context_, events_context);
    }
    return tag;
}

void SyncOpSetEvent::ReplayRecord(CommandExecutionContext &exec_context, ResourceUsageTag exec_tag) const {
    // Create a copy of the current context, and merge in the state snapshot at record set event time
    // Note: we mustn't change the recorded context copy, as a given CB could be submitted more than once (in generaL)
    if (!exec_context.ValidForSyncOps()) return;
    SyncEventsContext *events_context = exec_context.GetCurrentEventsContext();
    AccessContext *access_context = exec_context.GetCurrentAccessContext();
    const QueueId queue_id = exec_context.GetQueueId();

    // Note: merged_context is a copy of the access_context, combined with the recorded context
    auto merged_context = std::make_shared<AccessContext>(*access_context->validator);
    merged_context->InitFrom(*access_context);
    merged_context->ResolveFromContext(QueueTagOffsetBarrierAction(queue_id, exec_tag), *recorded_context_);
    merged_context->TrimAndClearFirstAccess();  // Ensure the copy is minimal and normalized
    DoRecord(queue_id, exec_tag, merged_context, events_context);
}

void SyncOpSetEvent::DoRecord(QueueId queue_id, ResourceUsageTag tag, const std::shared_ptr<const AccessContext> &access_context,
                              SyncEventsContext *events_context) const {
    auto *sync_event = events_context->GetFromShared(event_);
    if (!sync_event) return;  // Core, Lifetimes, or Param check needs to catch invalid events.

    // NOTE: We're going to simply record the sync scope here, as anything else would be implementation defined/undefined
    //       and we're issuing errors re: missing barriers between event commands, which if the user fixes would fix
    //       any issues caused by naive scope setting here.

    // What happens with two SetEvent is that one cannot know what group of operations will be waited for.
    // Given:
    //     Stuff1; SetEvent; Stuff2; SetEvent; WaitEvents;
    // WaitEvents cannot know which of Stuff1, Stuff2, or both has completed execution.

    if (!sync_event->HasBarrier(src_exec_scope_.mask_param, src_exec_scope_.exec_scope)) {
        sync_event->unsynchronized_set = sync_event->last_command;
        sync_event->ResetFirstScope();
    } else if (!sync_event->first_scope) {
        // We only set the scope if there isn't one
        sync_event->scope = src_exec_scope_;

        // Save the shared_ptr to copy of the access_context present at set time (sent us by the caller)
        sync_event->first_scope = access_context;
        sync_event->unsynchronized_set = vvl::Func::Empty;
        sync_event->first_scope_tag = tag;
    }
    // TODO: Store dep_info_ shared ptr in sync_state for WaitEvents2 validation
    sync_event->last_command = command_;
    sync_event->last_command_tag = tag;
    sync_event->barriers = 0U;
}

SyncOpBeginRenderPass::SyncOpBeginRenderPass(vvl::Func command, const SyncValidator &sync_state,
                                             const VkRenderPassBeginInfo *pRenderPassBegin,
                                             const VkSubpassBeginInfo *pSubpassBeginInfo)
    : SyncOpBase(command), rp_context_(nullptr) {
    if (pRenderPassBegin) {
        rp_state_ = sync_state.Get<vvl::RenderPass>(pRenderPassBegin->renderPass);
        renderpass_begin_info_ = vku::safe_VkRenderPassBeginInfo(pRenderPassBegin);
        auto fb_state = sync_state.Get<vvl::Framebuffer>(pRenderPassBegin->framebuffer);
        if (fb_state) {
            shared_attachments_ = sync_state.device_state->GetAttachmentViews(*renderpass_begin_info_.ptr(), *fb_state);
            // TODO: Revisit this when all attachment validation is through SyncOps to see if we can discard the plain pointer copy
            // Note that this a safe to presist as long as shared_attachments is not cleared
            attachments_.reserve(shared_attachments_.size());
            for (const auto &attachment : shared_attachments_) {
                attachments_.emplace_back(attachment.get());
            }
        }
        if (pSubpassBeginInfo) {
            subpass_begin_info_ = vku::safe_VkSubpassBeginInfo(pSubpassBeginInfo);
        }
    }
}

bool SyncOpBeginRenderPass::Validate(const CommandBufferAccessContext &cb_context) const {
    // Check if any of the layout transitions are hazardous.... but we don't have the renderpass context to work with, so we
    bool skip = false;

    assert(rp_state_.get());
    if (nullptr == rp_state_.get()) return skip;
    auto &rp_state = *rp_state_.get();

    const uint32_t subpass = 0;

    // Construct the state to validate against (since validation is const and RecordCmdBeginRenderPass hasn't happened yet).
    // TODO: investigate if using nullptr in InitFrom is safe (this just follows the initial implementation - it assumes
    // that array of subpass dependencies won't be indexed, but it's not obvious).
    AccessContext temp_context(cb_context.GetSyncState());

    temp_context.InitFrom(subpass, cb_context.GetQueueFlags(), rp_state.subpass_dependency_infos, nullptr,
                          *cb_context.GetCurrentAccessContext());

    // Validate attachment operations
    if (attachments_.empty()) return skip;
    const auto &render_area = renderpass_begin_info_.renderArea;
    const uint32_t render_pass_instance_id = cb_context.GetCurrentRenderPassInstanceId();

    // Since the isn't a valid RenderPassAccessContext until Record, needs to create the view/generator list... we could limit this
    // by predicating on whether subpass 0 uses the attachment if it is too expensive to create the full list redundantly here.
    // More broadly we could look at thread specific state shared between Validate and Record as is done for other heavyweight
    // operations (though it's currently a messy approach)
    const AttachmentViewGenVector view_gens = RenderPassAccessContext::CreateAttachmentViewGen(render_area, attachments_);
    skip |= RenderPassAccessContext::ValidateLayoutTransitions(cb_context, temp_context, rp_state, render_area,
                                                               render_pass_instance_id, subpass, view_gens, command_);

    // Validate load operations if there were no layout transition hazards
    if (!skip) {
        RenderPassAccessContext::RecordLayoutTransitions(rp_state, subpass, view_gens, kInvalidTag, temp_context);
        skip |= RenderPassAccessContext::ValidateLoadOperation(cb_context, temp_context, rp_state, render_area,
                                                               render_pass_instance_id, subpass, view_gens, command_);
    }

    return skip;
}

ResourceUsageTag SyncOpBeginRenderPass::Record(CommandBufferAccessContext *cb_context) {
    assert(rp_state_.get());
    if (nullptr == rp_state_.get()) return cb_context->NextCommandTag(command_);
    const ResourceUsageTag begin_tag =
        cb_context->RecordBeginRenderPass(command_, *rp_state_.get(), renderpass_begin_info_.renderArea, attachments_);

    // Note: this state update must be after RecordBeginRenderPass as there is no current render pass until that function runs
    rp_context_ = cb_context->GetCurrentRenderPassContext();

    return begin_tag;
}

bool SyncOpBeginRenderPass::ReplayValidate(ReplayState &replay, ResourceUsageTag recorded_tag) const {
    CommandExecutionContext &exec_context = replay.GetExecutionContext();
    // this operation is not allowed in secondary command buffers
    assert(exec_context.Handle().type == kVulkanObjectTypeQueue);
    auto &batch_context = static_cast<QueueBatchContext &>(exec_context);
    batch_context.BeginRenderPassReplaySetup(replay, *this);

    // Only the layout transitions happen at the replay tag, loadOp's happen at a subsequent tag
    ResourceUsageRange first_use_range = {recorded_tag, recorded_tag + 1};
    return replay.DetectFirstUseHazard(first_use_range);
}

void SyncOpBeginRenderPass::ReplayRecord(CommandExecutionContext &exec_context, ResourceUsageTag exec_tag) const {
    // All the needed replay state changes (for the layout transition, and context update) have to happen in ReplayValidate
}

SyncOpNextSubpass::SyncOpNextSubpass(vvl::Func command, const SyncValidator &sync_state,
                                     const VkSubpassBeginInfo *pSubpassBeginInfo, const VkSubpassEndInfo *pSubpassEndInfo)
    : SyncOpBase(command) {
    if (pSubpassBeginInfo) {
        subpass_begin_info_.initialize(pSubpassBeginInfo);
    }
    if (pSubpassEndInfo) {
        subpass_end_info_.initialize(pSubpassEndInfo);
    }
}

bool SyncOpNextSubpass::Validate(const CommandBufferAccessContext &cb_context) const {
    bool skip = false;
    const auto *renderpass_context = cb_context.GetCurrentRenderPassContext();
    if (!renderpass_context) return skip;

    skip |= renderpass_context->ValidateNextSubpass(cb_context, command_);
    return skip;
}

ResourceUsageTag SyncOpNextSubpass::Record(CommandBufferAccessContext *cb_context) {
    return cb_context->RecordNextSubpass(command_);
}

bool SyncOpNextSubpass::ReplayValidate(ReplayState &replay, ResourceUsageTag recorded_tag) const {
    // Any store/resolve operations happen before the NextSubpass tag so we can advance to the next subpass state
    CommandExecutionContext &exec_context = replay.GetExecutionContext();
    // this operation is not allowed in secondary command buffers
    assert(exec_context.Handle().type == kVulkanObjectTypeQueue);
    auto &batch_context = static_cast<QueueBatchContext &>(exec_context);
    batch_context.NextSubpassReplaySetup(replay);

    // Only the layout transitions happen at the replay tag, loadOp's happen at a subsequent tag
    ResourceUsageRange first_use_range = {recorded_tag, recorded_tag + 1};
    return replay.DetectFirstUseHazard(first_use_range);
}

void SyncOpNextSubpass::ReplayRecord(CommandExecutionContext &exec_context, ResourceUsageTag exec_tag) const {
    // All the needed replay state changes (for the layout transition, and context update) have to happen in ReplayValidate
}
SyncOpEndRenderPass::SyncOpEndRenderPass(vvl::Func command, const SyncValidator &sync_state,
                                         const VkSubpassEndInfo *pSubpassEndInfo)
    : SyncOpBase(command) {
    if (pSubpassEndInfo) {
        subpass_end_info_.initialize(pSubpassEndInfo);
    }
}

bool SyncOpEndRenderPass::Validate(const CommandBufferAccessContext &cb_context) const {
    bool skip = false;
    const auto *renderpass_context = cb_context.GetCurrentRenderPassContext();

    if (!renderpass_context) return skip;
    skip |= renderpass_context->ValidateEndRenderPass(cb_context, command_);
    return skip;
}

ResourceUsageTag SyncOpEndRenderPass::Record(CommandBufferAccessContext *cb_context) {
    return cb_context->RecordEndRenderPass(command_);
}

bool SyncOpEndRenderPass::ReplayValidate(ReplayState &replay, ResourceUsageTag recorded_tag) const {
    // Any store/resolve operations happen before the EndRenderPass tag so we can ignore them
    // Only the layout transitions happen at the replay tag
    ResourceUsageRange first_use_range = {recorded_tag, recorded_tag + 1};
    bool skip = false;
    skip |= replay.DetectFirstUseHazard(first_use_range);

    // We can cleanup here as the recorded tag represents the final layout transition (which is the last operation or the RP)
    CommandExecutionContext &exec_context = replay.GetExecutionContext();
    // this operation is not allowed in secondary command buffers
    assert(exec_context.Handle().type == kVulkanObjectTypeQueue);
    auto &batch_context = static_cast<QueueBatchContext &>(exec_context);
    batch_context.EndRenderPassReplayCleanup(replay);

    return skip;
}

void SyncOpEndRenderPass::ReplayRecord(CommandExecutionContext &exec_context, ResourceUsageTag exec_tag) const {}

ReplayState::ReplayState(CommandExecutionContext &exec_context, const CommandBufferAccessContext &recorded_context,
                         const ErrorObject &error_obj, uint32_t index, ResourceUsageTag base_tag)
    : exec_context_(exec_context), recorded_context_(recorded_context), error_obj_(error_obj), index_(index), base_tag_(base_tag) {}

AccessContext *ReplayState::ReplayStateRenderPassBegin(VkQueueFlags queue_flags, const SyncOpBeginRenderPass &begin_op,
                                                       const AccessContext &external_context) {
    return rp_replay_.Begin(queue_flags, begin_op, external_context);
}

AccessContext *ReplayState::ReplayStateRenderPassNext() { return rp_replay_.Next(); }

void ReplayState::ReplayStateRenderPassEnd(AccessContext &external_context) { rp_replay_.End(external_context); }

const AccessContext *ReplayState::GetRecordedAccessContext() const {
    if (rp_replay_.begin_op) {
        return rp_replay_.replay_context;
    }
    return recorded_context_.GetCurrentAccessContext();
}

bool ReplayState::DetectFirstUseHazard(const ResourceUsageRange &first_use_range) const {
    bool skip = false;
    if (first_use_range.non_empty()) {
        // We're allowing for the Replay(Validate|Record) to modify the exec_context (e.g. for Renderpass operations), so
        // we need to fetch the current access context each time
        const AccessContext *access_context = GetRecordedAccessContext();

        const HazardResult hazard = access_context->DetectFirstUseHazard(exec_context_.GetQueueId(), first_use_range,
                                                                         *exec_context_.GetCurrentAccessContext());
        if (hazard.IsHazard()) {
            const SyncValidator &sync_state = exec_context_.GetSyncState();
            LogObjectList objlist(exec_context_.Handle(), recorded_context_.Handle());
            const std::string error = sync_state.error_messages_.FirstUseError(hazard, exec_context_, recorded_context_, index_);
            skip |= sync_state.SyncError(hazard.Hazard(), objlist, error_obj_.location, error);
        }
    }
    return skip;
}

bool ReplayState::ValidateFirstUse() {
    if (!exec_context_.ValidForSyncOps()) return false;

    bool skip = false;
    ResourceUsageRange first_use_range = {0, 0};

    for (const auto &sync_op : recorded_context_.GetSyncOps()) {
        // Set the range to cover all accesses until the next sync_op, and validate
        first_use_range.end = sync_op.tag;
        skip |= DetectFirstUseHazard(first_use_range);

        // Call to replay validate support for syncop with non-trivial replay
        skip |= sync_op.sync_op->ReplayValidate(*this, sync_op.tag);

        // Record the barrier into the proxy context.
        sync_op.sync_op->ReplayRecord(exec_context_, base_tag_ + sync_op.tag);
        first_use_range.begin = sync_op.tag + 1;
    }

    // and anything after the last syncop
    first_use_range.end = ResourceUsageRecord::kMaxIndex;
    skip |= DetectFirstUseHazard(first_use_range);

    return skip;
}
AccessContext *ReplayState::RenderPassReplayState::Begin(VkQueueFlags queue_flags, const SyncOpBeginRenderPass &begin_op_,
                                                         const AccessContext &external_context) {
    const RenderPassAccessContext *rp_context = begin_op_.GetRenderPassAccessContext();
    assert(rp_context);

    begin_op = &begin_op_;
    replay_context = &rp_context->GetSubpassContexts()[0];
    subpass = 0;
    subpass_contexts = InitSubpassContexts(queue_flags, *rp_context->GetRenderPassState(), external_context);

    // Replace the Async contexts with the the async context of the "external" context
    // For replay we don't care about async subpasses, just async queue batches
    for (AccessContext &context : GetSubpassContexts()) {
        context.ClearAsyncContexts();
        context.ImportAsyncContexts(external_context);
    }

    return &subpass_contexts[0];
}

AccessContext *ReplayState::RenderPassReplayState::Next() {
    subpass++;

    const RenderPassAccessContext *rp_context = begin_op->GetRenderPassAccessContext();

    replay_context = &rp_context->GetSubpassContexts()[subpass];
    return &subpass_contexts[subpass];
}

void ReplayState::RenderPassReplayState::End(AccessContext &external_context) {
    external_context.ResolveChildContexts(GetSubpassContexts());
    *this = RenderPassReplayState{};
}

vvl::span<AccessContext> ReplayState::RenderPassReplayState::GetSubpassContexts() {
    return vvl::make_span(subpass_contexts.get(),
                          begin_op->GetRenderPassAccessContext()->GetRenderPassState()->create_info.subpassCount);
}

void SyncEventsContext::ApplyBarrier(const SyncExecScope &src, const SyncExecScope &dst, ResourceUsageTag tag) {
    const bool all_commands_bit = 0 != (src.mask_param & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
    for (auto &event_pair : map_) {
        assert(event_pair.second);  // Shouldn't be storing empty
        auto &sync_event = *event_pair.second;
        // Events don't happen at a stage, so we need to check and store the unexpanded ALL_COMMANDS if set for inter-event-calls
        // But only if occuring before the tag
        if (((sync_event.barriers & src.exec_scope) || all_commands_bit) && (sync_event.last_command_tag <= tag)) {
            sync_event.barriers |= dst.exec_scope;
            sync_event.barriers |= dst.mask_param & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
        }
    }
}

void SyncEventsContext::ApplyTaggedWait(VkQueueFlags queue_flags, ResourceUsageTag tag) {
    const SyncExecScope src_scope =
        SyncExecScope::MakeSrc(queue_flags, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_2_HOST_BIT);
    const SyncExecScope dst_scope = SyncExecScope::MakeDst(queue_flags, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
    ApplyBarrier(src_scope, dst_scope, tag);
}

SyncEventsContext &SyncEventsContext::DeepCopy(const SyncEventsContext &from) {
    // We need a deep copy of the const context to update during validation phase
    for (const auto &event : from.map_) {
        map_.emplace(event.first, std::make_shared<SyncEventState>(*event.second));
    }
    return *this;
}

void SyncEventsContext::AddReferencedTags(ResourceUsageTagSet &referenced) const {
    for (const auto &event : map_) {
        const std::shared_ptr<const SyncEventState> &event_state = event.second;
        if (event_state) {
            event_state->AddReferencedTags(referenced);
        }
    }
}

SyncEventState::SyncEventState(const SyncEventState::EventPointer &event_state) : SyncEventState() {
    event = event_state;
    destroyed = (event.get() == nullptr) || event_state->Destroyed();
}

void SyncEventState::ResetFirstScope() {
    first_scope.reset();
    scope = SyncExecScope();
    first_scope_tag = 0;
}

// Keep the "ignore this event" logic in same place for ValidateWait and RecordWait to use
SyncEventState::IgnoreReason SyncEventState::IsIgnoredByWait(vvl::Func command, VkPipelineStageFlags2 srcStageMask) const {
    IgnoreReason reason = NotIgnored;

    if ((vvl::Func::vkCmdWaitEvents2KHR == command || vvl::Func::vkCmdWaitEvents2 == command) &&
        (vvl::Func::vkCmdSetEvent == last_command)) {
        reason = SetVsWait2;
    } else if ((last_command == vvl::Func::vkCmdResetEvent || last_command == vvl::Func::vkCmdResetEvent2KHR) &&
               !HasBarrier(0U, 0U)) {
        reason = (last_command == vvl::Func::vkCmdResetEvent) ? ResetWaitRace : Reset2WaitRace;
    } else if (unsynchronized_set != vvl::Func::Empty) {
        reason = SetRace;
    } else if (first_scope) {
        const VkPipelineStageFlags2 missing_bits = scope.mask_param & ~srcStageMask;
        // Note it is the "not missing bits" path that is the only "NotIgnored" path
        if (missing_bits) reason = MissingStageBits;
    } else {
        reason = MissingSetEvent;
    }

    return reason;
}

bool SyncEventState::HasBarrier(VkPipelineStageFlags2 stageMask, VkPipelineStageFlags2 exec_scope_arg) const {
    return (last_command == vvl::Func::Empty) || (stageMask & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) || (barriers & exec_scope_arg) ||
           (barriers & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}

void SyncEventState::AddReferencedTags(ResourceUsageTagSet &referenced) const {
    if (first_scope) {
        first_scope->AddReferencedTags(referenced);
    }
}

}  // namespace syncval
