/*
 * 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_access_state.h"
#include "sync/sync_stats.h"
#include "utils/hash_util.h"

static bool IsRead(SyncAccessIndex access) { return syncAccessReadMask[access]; }

namespace syncval {

static const std::array<OrderingBarrier, static_cast<size_t>(SyncOrdering::kNumOrderings)> kOrderingRules = {
    {{VK_PIPELINE_STAGE_2_NONE, SyncAccessFlags()},
     {kColorAttachmentExecScope, kColorAttachmentAccessScope},
     {kDepthStencilAttachmentExecScope, kDepthStencilAttachmentAccessScope},
     {kRasterAttachmentExecScope, kRasterAttachmentAccessScope}}};

const OrderingBarrier &GetOrderingRules(SyncOrdering ordering_enum) { return kOrderingRules[static_cast<size_t>(ordering_enum)]; }

static ThreadSafeLookupTable<OrderingBarrier> layout_ordering_barrier_lookup;
ThreadSafeLookupTable<OrderingBarrier> &GetLayoutOrderingBarrierLookup() { return layout_ordering_barrier_lookup; }

bool AttachmentAccess::operator==(const AttachmentAccess &other) const {
    return type == other.type && ordering == other.ordering && render_pass_instance_id == other.render_pass_instance_id &&
           subpass == other.subpass;
}

bool OrderingBarrier::operator==(const OrderingBarrier &rhs) const {
    return exec_scope == rhs.exec_scope && access_scope == rhs.access_scope;
}

size_t OrderingBarrier::Hash() const {
    hash_util::HashCombiner hc;
    hc << exec_scope;
    access_scope.HashCombine(hc);
    return hc.Value();
}

HazardResult AccessState::DetectHazard(const SyncAccessInfo &usage_info) const {
    const auto &usage_stage = usage_info.stage_mask;
    if (IsRead(usage_info.access_index)) {
        if (IsRAWHazard(usage_info)) {
            return HazardResult::HazardVsPriorWrite(this, usage_info, READ_AFTER_WRITE, *last_write);
        }
    } else {
        // Write operation:
        // Check for read operations more recent than last_write (as setting last_write clears reads, that would be *any*
        // If reads exists -- test only against them because either:
        //     * the reads were hazards, and we've reported the hazard, so just test the current write vs. the read operations
        //     * the read weren't hazards, and thus if the write is safe w.r.t. the reads, no hazard vs. last_write is possible if
        //       the current write happens after the reads, so just test the write against the reades
        // Otherwise test against last_write
        //
        // Look for casus belli for WAR
        if (HasReads()) {
            for (const auto &read_access : GetReads()) {
                if (IsReadHazard(usage_stage, read_access)) {
                    return HazardResult::HazardVsPriorRead(this, usage_info, WRITE_AFTER_READ, read_access);
                }
            }
        } else if (last_write.has_value() && last_write->IsWriteHazard(usage_info)) {
            // Write-After-Write check -- if we have a previous write to test against
            return HazardResult::HazardVsPriorWrite(this, usage_info, WRITE_AFTER_WRITE, *last_write);
        }
    }
    return {};
}

HazardResult AccessState::DetectMarkerHazard() const {
    // Check for special case with two consecutive marker acceses.
    // Markers specify memory dependency betweem themselves, so this is not a hazard.
    if (!HasReads() && last_write.has_value() && (last_write->flags & SyncFlag::kMarker) != 0) {
        return {};
    }

    // Go back to regular hazard detection
    const SyncAccessInfo &marker_access_info = GetAccessInfo(SYNC_COPY_TRANSFER_WRITE);
    return DetectHazard(marker_access_info);
}

HazardResult AccessState::DetectHazard(const SyncAccessInfo &usage_info, const OrderingBarrier &ordering,
                                       const AttachmentAccess &attachment_access, SyncFlags flags, QueueId queue_id,
                                       bool detect_load_op_after_store_op_hazards) const {
    const VkPipelineStageFlagBits2 access_stage = usage_info.stage_mask;
    const SyncAccessIndex access_index = usage_info.access_index;

    if (IsRead(usage_info.access_index)) {
        bool is_raw_hazard = IsRAWHazard(usage_info);
        if (is_raw_hazard) {
            const bool access_is_input_attachment = (access_index == SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ);
            const bool input_attachment_ordering = ordering.access_scope[SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ];

            // Check if the ordering rules make a RAW sequence not a hazard.
            // The ordering act as barriers to the last accesses.
            // At first check if the current access is covered by the ordering rules
            const bool access_is_ordered =
                (access_stage & ordering.exec_scope) != 0 || (access_is_input_attachment && input_attachment_ordering);

            if (access_is_ordered) {
                // Check if the most recent write is ordered.
                // Input attachment is ordered against load op but not against regular draws (requires subpass barrier).
                bool most_recent_is_ordered =
                    last_write->IsOrdered(ordering, queue_id) && (!access_is_input_attachment || last_write->IsLoadOp());

                // LoadOp after StoreOp happens only if accesses are from different render pass instances.
                // Such accesses are not implicitly synchronized.
                if (detect_load_op_after_store_op_hazards) {
                    if (last_write->IsStoreOp() && attachment_access.type == AttachmentAccessType::LoadOp) {
                        most_recent_is_ordered = false;
                    }
                }

                // Resolve read is not ordered against accesses from other subpasses
                if (attachment_access.type == AttachmentAccessType::ResolveRead) {
                    if (attachment_access.subpass != last_write->attachment_access.subpass) {
                        most_recent_is_ordered = false;
                    }
                }

                // If most recent write is not ordered then check if subsequent read is ordered
                if (!most_recent_is_ordered) {
                    most_recent_is_ordered = (GetOrderedStages(queue_id, ordering, attachment_access.type) != 0);
                }

                is_raw_hazard = !most_recent_is_ordered;
            }
        }
        if (is_raw_hazard) {
            return HazardResult::HazardVsPriorWrite(this, usage_info, READ_AFTER_WRITE, *last_write);
        }
        return {};
    }

    if (access_index == SyncAccessIndex::SYNC_IMAGE_LAYOUT_TRANSITION) {
        // For Image layout transitions, the barrier represents the first synchronization/access scope of the layout transition
        return DetectBarrierHazard(usage_info, queue_id, ordering.exec_scope, ordering.access_scope);
    }

    // Check WAR before WAW
    const bool usage_write_is_ordered = (usage_info.access_bit & ordering.access_scope).any();
    if (HasReads()) {
        // Look for any WAR hazards outside the ordered set of stages
        VkPipelineStageFlags2 ordered_stages = VK_PIPELINE_STAGE_2_NONE;
        if (usage_write_is_ordered) {
            // If the usage is ordered, we can ignore all ordered read stages w.r.t. WAR)
            ordered_stages = GetOrderedStages(queue_id, ordering, attachment_access.type);
        }
        // If we're tracking any reads that aren't ordered against the current write, got to check 'em all.
        if ((ordered_stages & last_read_stages) != last_read_stages) {
            for (const auto &read_access : GetReads()) {
                if (read_access.stage & ordered_stages) continue;  // but we can skip the ordered ones
                if (IsReadHazard(access_stage, read_access)) {
                    return HazardResult::HazardVsPriorRead(this, usage_info, WRITE_AFTER_READ, read_access);
                }
            }
        }
        return {};
    }

    // Only check for WAW if there are no reads since last_write
    if (last_write.has_value()) {
        // Check if it's two ordered write accesses
        const bool load_op_after_store_op = last_write->IsStoreOp() && attachment_access.type == AttachmentAccessType::LoadOp;
        const bool validate_load_op_after_store_op = detect_load_op_after_store_op_hazards && load_op_after_store_op;
        if (last_write->IsOrdered(ordering, queue_id) && usage_write_is_ordered && !validate_load_op_after_store_op) {
            return {};
        }

        // Special case: marker accesses define memory dependency betweem themsevles
        if ((last_write->flags & SyncFlag::kMarker) != 0 && (flags & SyncFlag::kMarker) != 0) {
            return {};
        }

        // ILT after ILT is a special case where we check the 2nd access scope of the first ILT against the first access
        // scope of the second ILT, which has been passed (smuggled?) in the ordering barrier
        bool ilt_ilt_hazard = false;
        if (access_index == SYNC_IMAGE_LAYOUT_TRANSITION && last_write->access_index == SYNC_IMAGE_LAYOUT_TRANSITION) {
            ilt_ilt_hazard = !(last_write->barriers & ordering.access_scope).any();
        }

        if (ilt_ilt_hazard || last_write->IsWriteHazard(usage_info)) {
            return HazardResult::HazardVsPriorWrite(this, usage_info, WRITE_AFTER_WRITE, *last_write);
        }
    }
    return {};
}

HazardResult AccessState::DetectHazard(const AccessState &recorded_use, QueueId queue_id, const ResourceUsageRange &tag_range,
                                       bool detect_load_op_after_store_op_hazards) const {
    HazardResult hazard;
    const auto &recorded_accesses = recorded_use.first_accesses_;
    uint32_t count = recorded_accesses.size();
    if (count) {
        // First access is only closed if the last is a write
        bool do_write_last = recorded_use.first_access_closed_;
        if (do_write_last) {
            // Note: We know count > 0 so this is alway safe.
            --count;
        }

        for (uint32_t i = 0; i < count; ++i) {
            const auto &first = recorded_accesses[i];
            // Skip and quit logic
            if (first.tag < tag_range.begin) continue;
            if (first.tag >= tag_range.end) {
                do_write_last = false;  // ignore last since we know it can't be in tag_range
                break;
            }

            const auto &first_ordering = GetOrderingRules(first.attachment_access.ordering);
            hazard = DetectHazard(*first.usage_info, first_ordering, first.attachment_access, first.flags, queue_id,
                                  detect_load_op_after_store_op_hazards);
            if (hazard.IsHazard()) {
                hazard.AddRecordedAccess(first);
                return hazard;
            }
        }

        if (do_write_last) {
            // Writes are a bit special... both for the "most recent" access logic, and layout transition specific logic
            const auto &last_access = recorded_accesses.back();
            if (tag_range.includes(last_access.tag)) {
                OrderingBarrier barrier = GetOrderingRules(last_access.attachment_access.ordering);
                if (last_access.usage_info->access_index == SyncAccessIndex::SYNC_IMAGE_LAYOUT_TRANSITION) {
                    // Or in the layout first access scope as a barrier... IFF the usage is an ILT
                    // this was saved off in the "apply barriers" logic to simplify ILT access checks as they straddle
                    // the barrier that applies them
                    const auto &layout_ordering_lookup = GetLayoutOrderingBarrierLookup();
                    const OrderingBarrier layout_ordering =
                        layout_ordering_lookup.GetObject(recorded_use.first_write_layout_ordering_index);

                    barrier.exec_scope |= layout_ordering.exec_scope;
                    barrier.access_scope |= layout_ordering.access_scope;
                }
                // Any read stages present in the recorded context (this) are most recent to the write, and thus mask those stages
                // in the active context
                if (recorded_use.first_read_stages_) {
                    // we need to ignore the first use read stage in the active context (so we add them to the ordering rule),
                    // reads in the active context are not "most recent" as all recorded context operations are *after* them
                    // This suppresses only RAW checks for stages present in the recorded context, but not those only present in the
                    // active context.
                    barrier.exec_scope |= recorded_use.first_read_stages_;
                    // if there are any first use reads, we suppress WAW by injecting the active context write in the ordering rule
                    barrier.access_scope |= last_access.usage_info->access_bit;
                }
                hazard = DetectHazard(*last_access.usage_info, barrier, last_access.attachment_access, last_access.flags, queue_id,
                                      detect_load_op_after_store_op_hazards);
                if (hazard.IsHazard()) {
                    hazard.AddRecordedAccess(last_access);
                    return hazard;
                }
            }
        }
    }
    return {};
}

// Asynchronous Hazards occur between subpasses with no connection through the DAG
HazardResult AccessState::DetectAsyncHazard(const SyncAccessInfo &usage_info, const ResourceUsageTag start_tag,
                                            QueueId queue_id) const {
    // Async checks need to not go back further than the start of the subpass, as we only want to find hazards between the async
    // subpasses.  Anything older than that should have been checked at the start of each subpass, taking into account all of
    // the raster ordering rules.
    if (IsRead(usage_info.access_index)) {
        if (last_write.has_value() && last_write->queue == queue_id && (last_write->tag >= start_tag)) {
            return HazardResult::HazardVsPriorWrite(this, usage_info, READ_RACING_WRITE, *last_write);
        }
    } else {
        if (last_write.has_value() && last_write->queue == queue_id && (last_write->tag >= start_tag)) {
            return HazardResult::HazardVsPriorWrite(this, usage_info, WRITE_RACING_WRITE, *last_write);
        } else if (HasReads()) {
            // Any reads during the other subpass will conflict with this write, so we need to check them all.
            for (const auto &read_access : GetReads()) {
                if (read_access.queue == queue_id && read_access.tag >= start_tag) {
                    return HazardResult::HazardVsPriorRead(this, usage_info, WRITE_RACING_READ, read_access);
                }
            }
        }
    }
    return {};
}

HazardResult AccessState::DetectAsyncHazard(const AccessState &recorded_use, const ResourceUsageRange &tag_range,
                                            ResourceUsageTag start_tag, QueueId queue_id) const {
    for (const auto &first : recorded_use.first_accesses_) {
        // Skip and quit logic
        if (first.tag < tag_range.begin) continue;
        if (first.tag >= tag_range.end) break;

        HazardResult hazard = DetectAsyncHazard(*first.usage_info, start_tag, queue_id);
        if (hazard.IsHazard()) {
            hazard.AddRecordedAccess(first);
            return hazard;
        }
    }
    return {};
}

HazardResult AccessState::DetectBarrierHazard(const SyncAccessInfo &usage_info, QueueId queue_id,
                                              VkPipelineStageFlags2 src_exec_scope, const SyncAccessFlags &src_access_scope) const {
    // Only supporting image layout transitions for now
    assert(usage_info.access_index == SyncAccessIndex::SYNC_IMAGE_LAYOUT_TRANSITION);

    // only test for WAW if there no intervening read operations.
    // See DetectHazard(SyncStagetAccessIndex) above for more details.
    if (HasReads()) {
        // Look at the reads if any
        for (const auto &read_access : GetReads()) {
            if (read_access.IsReadBarrierHazard(queue_id, src_exec_scope, src_access_scope)) {
                return HazardResult::HazardVsPriorRead(this, usage_info, WRITE_AFTER_READ, read_access);
            }
        }
    } else if (last_write.has_value() && IsWriteBarrierHazard(queue_id, src_exec_scope, src_access_scope)) {
        return HazardResult::HazardVsPriorWrite(this, usage_info, WRITE_AFTER_WRITE, *last_write);
    }
    return {};
}

HazardResult AccessState::DetectBarrierHazard(const SyncAccessInfo &usage_info, const AccessState &scope_state,
                                              VkPipelineStageFlags2 src_exec_scope, const SyncAccessFlags &src_access_scope,
                                              QueueId event_queue, ResourceUsageTag event_tag) const {
    // Only supporting image layout transitions for now
    assert(usage_info.access_index == SyncAccessIndex::SYNC_IMAGE_LAYOUT_TRANSITION);

    if (last_write.has_value() && (last_write->tag >= event_tag)) {
        // Any write after the event precludes the possibility of being in the first access scope for the layout transition
        return HazardResult::HazardVsPriorWrite(this, usage_info, WRITE_AFTER_WRITE, *last_write);
    } else {
        // only test for WAW if there no intervening read operations.
        // See DetectHazard(SyncStagetAccessIndex) above for more details.
        if (HasReads()) {
            // Look at the reads if any... if reads exist, they are either the reason the access is in the event
            // first scope, or they are a hazard.
            const uint32_t scope_read_count = scope_state.last_read_count;
            // Since the hasn't been a write:
            //  * The current read state is a superset of the scoped one
            //  * The stage order is the same.
            assert(last_read_count >= scope_read_count);
            for (uint32_t read_idx = 0; read_idx < scope_read_count; ++read_idx) {
                const ReadState &scope_read = scope_state.last_reads[read_idx];
                const ReadState &current_read = last_reads[read_idx];
                assert(scope_read.stage == current_read.stage);
                if (current_read.tag > event_tag) {
                    // The read is more recent than the set event scope, thus no barrier from the wait/ILT.
                    return HazardResult::HazardVsPriorRead(this, usage_info, WRITE_AFTER_READ, current_read);
                } else {
                    // The read is in the events first synchronization scope, so we use a barrier hazard check
                    // If the read stage is not in the src sync scope
                    // *AND* not execution chained with an existing sync barrier (that's the or)
                    // then the barrier access is unsafe (R/W after R)
                    if (scope_read.IsReadBarrierHazard(event_queue, src_exec_scope, src_access_scope)) {
                        return HazardResult::HazardVsPriorRead(this, usage_info, WRITE_AFTER_READ, scope_read);
                    }
                }
            }
            if (last_read_count > scope_read_count) {
                const ReadState &current_read = last_reads[scope_read_count];
                return HazardResult::HazardVsPriorRead(this, usage_info, WRITE_AFTER_READ, current_read);
            }
        } else if (last_write.has_value()) {
            // if there are no reads, the write is either the reason the access is in the event scope... they are a hazard
            // The write is in the first sync scope of the event (sync their aren't any reads to be the reason)
            // So do a normal barrier hazard check
            if (scope_state.IsWriteBarrierHazard(event_queue, src_exec_scope, src_access_scope)) {
                return HazardResult::HazardVsPriorWrite(&scope_state, usage_info, WRITE_AFTER_WRITE, *scope_state.last_write);
            }
        }
    }
    return {};
}

void AccessState::AddRead(const ReadState &read) {
    if (last_read_count == 0) {
        single_last_read = read;
        last_reads = &single_last_read;
        last_read_count = 1;
    } else {  // last_read_count > 0
        auto new_reads = new ReadState[last_read_count + 1];
        std::memcpy(new_reads, last_reads, last_read_count * sizeof(ReadState));
        if (last_read_count > 1) {
            delete[] last_reads;
        }
        new_reads[last_read_count] = read;
        last_reads = new_reads;
        last_read_count++;
    }
}

void AccessState::MergeReads(const AccessState &other) {
    // Merge the read states
    const uint32_t pre_merge_count = last_read_count;
    const auto pre_merge_stages = last_read_stages;
    for (uint32_t other_read_index = 0; other_read_index < other.last_read_count; other_read_index++) {
        auto &other_read = other.last_reads[other_read_index];
        if (pre_merge_stages & other_read.stage) {
            // Merge in the barriers for read stages that exist in *both* this and other
            // TODO: This is N^2 with stages... perhaps the ReadStates should be sorted by stage index.
            //       but we should wait on profiling data for that.
            for (uint32_t my_read_index = 0; my_read_index < pre_merge_count; my_read_index++) {
                auto &my_read = last_reads[my_read_index];
                if (other_read.stage == my_read.stage) {
                    if (my_read.tag < other_read.tag) {
                        // Other is more recent, copy in the state
                        my_read.access_index = other_read.access_index;
                        my_read.tag = other_read.tag;
                        my_read.handle_index = other_read.handle_index;
                        my_read.queue = other_read.queue;
                        // TODO: Phase 2 -- review the state merge logic to avoid false positive from overwriting the barriers
                        //                  May require tracking more than one access per stage.
                        my_read.barriers = other_read.barriers;
                        my_read.sync_stages = other_read.sync_stages;
                        if (my_read.stage == VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT) {
                            // Since I'm overwriting the fragement stage read, also update the input attachment info
                            // as this is the only stage that affects it.
                            input_attachment_read = other.input_attachment_read;
                        }
                    } else if (other_read.tag == my_read.tag) {
                        // The read tags match so merge the barriers
                        my_read.barriers |= other_read.barriers;
                        my_read.sync_stages |= other_read.sync_stages;
                    }

                    break;
                }
            }
        } else {
            // The other read stage doesn't exist in this, so add it.
            AddRead(other_read);
            last_read_stages |= other_read.stage;
            if (other_read.stage == VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT) {
                input_attachment_read = other.input_attachment_read;
            }
        }
    }
    read_execution_barriers |= other.read_execution_barriers;
}

// The logic behind resolves is the same as update, we assume that earlier hazards have be reported, and that no
// tranistive hazard can exists with a hazard between the earlier operations.  Yes, an early hazard can mask that another
// exists, but if you fix *that* hazard it either fixes or unmasks the subsequent ones.
void AccessState::Resolve(const AccessState &other) {
    bool skip_first = false;
    if (last_write.has_value()) {
        if (other.last_write.has_value()) {
            if (last_write->tag < other.last_write->tag) {
                // NOTE: Both last and other have writes, and thus first access is "closed". We are selecting other's
                //       first_access state, but it and this can only differ if there are async hazards
                //       error state.
                //
                // If this is a later write, we've reported any exsiting hazard, and we can just overwrite as the more recent
                // operation
                Assign(other);
                skip_first = true;
            } else if (last_write->tag == other.last_write->tag) {
                // In the *equals* case for write operations, we merged the write barriers and the read state (but without the
                // dependency chaining logic or any stage expansion)
                last_write->MergeBarriers(*other.last_write);
                MergeReads(other);
            } else {
                // other write is before this write... in which case we keep this instead of other
                // and can skip the "first_access" merge, since first_access has been closed since other write tag or before
                skip_first = true;
            }
        } else {
            // this has a write and other doesn't -- at best async read in other, which have been reported, and will be dropped
            // Since this has a write first access is closed and shouldn't be updated by other
            skip_first = true;
        }
    } else if (other.last_write.has_value()) {  // && not this->last_write
        // Other has write and this doesn't, thus keep it, See first access NOTE above
        Assign(other);
        skip_first = true;
    } else {  // not this->last_write OR other.last_write
        // Neither state has a write, just merge the reads
        MergeReads(other);
    }

    // Merge first access information by merging this and other first accesses (similar to how merge sort works)
    if (!skip_first && !(first_accesses_ == other.first_accesses_) && !other.first_accesses_.empty()) {
        FirstAccesses firsts(std::move(first_accesses_));

        // Make a copy because ClearFirstUse clears first access state
        const uint32_t this_first_write_layout_ordering_index = first_write_layout_ordering_index;

        // Select layout transition barrier from the write that goes first (the later write will be
        // ignored since the first access gets closed after the first write).
        const bool resolve_to_this_layout_ordering =
            !other.first_access_closed_ || (first_access_closed_ && firsts.back().tag < other.first_accesses_.back().tag);

        ClearFirstUse();

        first_write_layout_ordering_index =
            resolve_to_this_layout_ordering ? this_first_write_layout_ordering_index : other.first_write_layout_ordering_index;

        auto a = firsts.begin();
        auto a_end = firsts.end();
        for (auto &b : other.first_accesses_) {
            // TODO: Determine whether some tag offset will be needed for PHASE II
            while ((a != a_end) && (a->tag < b.tag)) {
                UpdateFirst(a->TagEx(), *a->usage_info, a->attachment_access, a->flags);
                ++a;
            }
            UpdateFirst(b.TagEx(), *b.usage_info, b.attachment_access, b.flags);
        }
        for (; a != a_end; ++a) {
            UpdateFirst(a->TagEx(), *a->usage_info, a->attachment_access, a->flags);
        }
    }
}

void AccessState::Update(const SyncAccessInfo &usage_info, const AttachmentAccess &attachment_access, ResourceUsageTagEx tag_ex,
                         SyncFlags flags) {
    const VkPipelineStageFlagBits2 usage_stage = usage_info.stage_mask;
    if (IsRead(usage_info.access_index)) {
        // Mulitple outstanding reads may be of interest and do dependency chains independently
        // However, for purposes of barrier tracking, only one read per pipeline stage matters
        if (usage_stage & last_read_stages) {
            const auto not_usage_stage = ~usage_stage;
            for (auto &read_access : GetReads()) {
                if (read_access.stage == usage_stage) {
                    read_access.Set(usage_stage, usage_info.access_index, tag_ex);
                } else if (read_access.barriers & usage_stage) {
                    // If the current access is barriered to this stage, mark it as "known to happen after"
                    read_access.sync_stages |= usage_stage;
                } else {
                    // If the current access is *NOT* barriered to this stage it needs to be cleared.
                    // Note: this is possible because semaphores can *clear* effective barriers, so the assumption
                    //       that sync_stages is a subset of barriers may not apply.
                    read_access.sync_stages &= not_usage_stage;
                }
            }
        } else {
            for (auto &read_access : GetReads()) {
                if (read_access.barriers & usage_stage) {
                    read_access.sync_stages |= usage_stage;
                }
            }
            ReadState new_read_state;
            new_read_state.Set(usage_stage, usage_info.access_index, tag_ex);
            AddRead(new_read_state);
            last_read_stages |= usage_stage;
        }

        // Fragment shader reads come in two flavors, and we need to track if the one we're tracking is the special one.
        if (usage_stage == VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT) {
            // TODO Revisit re: multiple reads for a given stage
            input_attachment_read = (usage_info.access_index == SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ);
        }
    } else {
        SetWrite(usage_info.access_index, attachment_access, tag_ex, flags);
    }
    UpdateFirst(tag_ex, usage_info, attachment_access, flags);
}

HazardResult HazardResult::HazardVsPriorWrite(const AccessState *access_state, const SyncAccessInfo &usage_info, SyncHazard hazard,
                                              const WriteState &prior_write) {
    HazardResult result;
    result.state_.emplace(access_state, usage_info, hazard, prior_write.access_index, prior_write.TagEx());
    return result;
}

HazardResult HazardResult::HazardVsPriorRead(const AccessState *access_state, const SyncAccessInfo &usage_info, SyncHazard hazard,
                                             const ReadState &prior_read) {
    assert(prior_read.access_index != SYNC_ACCESS_INDEX_NONE);
    HazardResult result;
    result.state_.emplace(access_state, usage_info, hazard, prior_read.access_index, prior_read.TagEx());
    return result;
}

void HazardResult::AddRecordedAccess(const FirstAccess &first_access) {
    assert(state_.has_value());
    state_->recorded_access = std::make_unique<const FirstAccess>(first_access);
}
bool HazardResult::IsWAWHazard() const {
    assert(state_.has_value());
    assert(state_->prior_access_index != SYNC_ACCESS_INDEX_NONE);
    return (state_->hazard == WRITE_AFTER_WRITE) && (state_->prior_access_index == state_->access_index);
}

// Clobber last read and all barriers... because all we have is DANGER, DANGER, WILL ROBINSON!!!
// if the last_reads/last_write were unsafe, we've reported them, in either case the prior access is irrelevant.
// We can overwrite them as *this* write is now after them.
void AccessState::SetWrite(SyncAccessIndex access_index, const AttachmentAccess &attachment_access, ResourceUsageTagEx tag_ex,
                           SyncFlags flags) {
    ClearRead();
    if (!last_write.has_value()) {
        last_write.emplace();
    }
    last_write->Set(access_index, attachment_access, tag_ex, flags);
}

void AccessState::ClearWrite() { last_write.reset(); }

void AccessState::ClearReadStates() {
    if (last_read_count > 1) {
        delete[] last_reads;
    }
    last_reads = nullptr;
    last_read_count = 0;
}

void AccessState::ClearRead() {
    ClearReadStates();
    last_read_stages = VK_PIPELINE_STAGE_2_NONE;
    read_execution_barriers = VK_PIPELINE_STAGE_2_NONE;
    input_attachment_read = false;  // Denotes no outstanding input attachment read after the last write.
}

void AccessState::ClearFirstUse() {
    first_accesses_.clear();
    first_read_stages_ = VK_PIPELINE_STAGE_2_NONE;
    first_write_layout_ordering_index = vvl::kNoIndex32;
    first_access_closed_ = false;
}

bool AccessState::ApplyBarrier(const BarrierScope &barrier_scope, const SyncBarrier &barrier, bool layout_transition,
                               uint32_t layout_transition_handle_index, ResourceUsageTag layout_transition_tag) {
    // Dedicated layout transition barrier logic
    if (layout_transition) {
        const SyncAccessInfo &layout_transition_access_info = GetAccessInfo(SYNC_IMAGE_LAYOUT_TRANSITION);
        const ResourceUsageTagEx tag_ex = ResourceUsageTagEx{layout_transition_tag, layout_transition_handle_index};
        const OrderingBarrier layout_ordering{barrier.src_exec_scope.exec_scope, barrier.src_access_scope};

        // Register write access that models layout transition writes
        SetWrite(SYNC_IMAGE_LAYOUT_TRANSITION, AttachmentAccess::NonAttachment(), tag_ex);
        UpdateFirst(tag_ex, layout_transition_access_info, AttachmentAccess::NonAttachment());
        TouchupFirstForLayoutTransition(layout_transition_tag, layout_ordering);

        last_write->barriers |= barrier.dst_access_scope;
        last_write->dependency_chain |= barrier.dst_exec_scope.exec_scope;
        return true;
    }

    bool barrier_applied = false;

    // Apply barriers over write access
    if (last_write.has_value() && last_write->InBarrierSourceScope(barrier_scope)) {
        last_write->barriers |= barrier.dst_access_scope;
        last_write->dependency_chain |= barrier.dst_exec_scope.exec_scope;
        barrier_applied = true;
    }
    // Apply barriers over read accesses
    VkPipelineStageFlags2 stages_in_scope = VK_PIPELINE_STAGE_2_NONE;
    for (ReadState &read_access : GetReads()) {
        // The | implements the "dependency chain" logic for this access,
        // as the barriers field stores the second sync scope
        if (read_access.InBarrierSourceScope(barrier_scope)) {
            // We will apply the barrier in the next loop to have this in one place
            stages_in_scope |= read_access.stage;
        }
    }
    for (ReadState &read_access : GetReads()) {
        if ((read_access.stage | read_access.sync_stages) & stages_in_scope) {
            // If this stage, or any stage known to be synchronized after it are in scope, apply the barrier to this read.
            // NOTE: Forwarding barriers to known prior stages changes the sync_stages from shallow to deep, because the
            // barriers used to determine sync_stages have been propagated to all known earlier stages
            read_access.barriers |= barrier.dst_exec_scope.exec_scope;
            read_execution_barriers |= barrier.dst_exec_scope.exec_scope;
            barrier_applied = true;
        }
    }
    return barrier_applied;
}

void AccessState::CollectPendingBarriers(const BarrierScope &barrier_scope, const SyncBarrier &barrier, bool layout_transition,
                                         uint32_t layout_transition_handle_index, PendingBarriers &pending_barriers) {
    if (layout_transition) {
        // Schedule layout transition first: layout transition creates WriteState if necessary
        const OrderingBarrier layout_transition_ordering_barrier{barrier.src_exec_scope.exec_scope, barrier.src_access_scope};
        pending_barriers.AddLayoutTransition(this, layout_transition_ordering_barrier, layout_transition_handle_index);

        // Apply barrier over layout trasition's write access
        pending_barriers.AddWriteBarrier(this, barrier);
        return;
    }

    // Collect barriers over write accesses
    if (last_write.has_value() && last_write->InBarrierSourceScope(barrier_scope)) {
        pending_barriers.AddWriteBarrier(this, barrier);
    }

    // Collect barriers over read accesses
    VkPipelineStageFlags2 stages_in_scope = VK_PIPELINE_STAGE_2_NONE;
    for (ReadState &read_access : GetReads()) {
        // The | implements the "dependency chain" logic for this access,
        // as the barriers field stores the second sync scope
        if (read_access.InBarrierSourceScope(barrier_scope)) {
            // We will apply the barrier in the next loop to have this in one place
            stages_in_scope |= read_access.stage;
        }
    }
    for (ReadState &read_access : GetReads()) {
        if ((read_access.stage | read_access.sync_stages) & stages_in_scope) {
            // If this stage, or any stage known to be synchronized after it are in scope, apply the barrier to this read.
            // NOTE: Forwarding barriers to known prior stages changes the sync_stages from shallow to deep, because the
            // barriers used to determine sync_stages have been propagated to all known earlier stages
            pending_barriers.AddReadBarrier(this, (uint32_t)(&read_access - last_reads), barrier);
        }
    }
}

void PendingBarriers::AddReadBarrier(AccessState *access_state, uint32_t last_reads_index, const SyncBarrier &barrier) {
    size_t barrier_index = 0;
    for (; barrier_index < read_barriers.size(); barrier_index++) {
        const PendingReadBarrier &pending = read_barriers[barrier_index];
        if (pending.barriers == barrier.dst_exec_scope.exec_scope && pending.last_reads_index == last_reads_index) {
            break;
        }
    }
    if (barrier_index == read_barriers.size()) {
        PendingReadBarrier &pending = read_barriers.emplace_back();
        pending.barriers = barrier.dst_exec_scope.exec_scope;
        pending.last_reads_index = last_reads_index;
    }
    PendingBarrierInfo &info = infos.emplace_back();
    info.type = PendingBarrierType::ReadAccessBarrier;
    info.index = (uint32_t)barrier_index;
    info.access_state = access_state;
}

void PendingBarriers::AddWriteBarrier(AccessState *access_state, const SyncBarrier &barrier) {
    size_t barrier_index = 0;
    for (; barrier_index < write_barriers.size(); barrier_index++) {
        const PendingWriteBarrier &pending = write_barriers[barrier_index];
        if (pending.barriers == barrier.dst_access_scope && pending.dependency_chain == barrier.dst_exec_scope.exec_scope) {
            break;
        }
    }
    if (barrier_index == write_barriers.size()) {
        PendingWriteBarrier &pending = write_barriers.emplace_back();
        pending.barriers = barrier.dst_access_scope;
        pending.dependency_chain = barrier.dst_exec_scope.exec_scope;
    }
    PendingBarrierInfo &info = infos.emplace_back();
    info.type = PendingBarrierType::WriteAccessBarrier;
    info.index = (uint32_t)barrier_index;
    info.access_state = access_state;
}

void PendingBarriers::AddLayoutTransition(AccessState *access_state, const OrderingBarrier &layout_transition_ordering_barrier,
                                          uint32_t layout_transition_handle_index) {
    // NOTE: in contrast to read/write barriers, we don't do reuse search here,
    // mostly because we didn't see a beneficial use case yet.
    // Storing handle index can be a hint it would be harder to find duplicates.
    PendingBarrierInfo &info = infos.emplace_back();
    info.type = PendingBarrierType::LayoutTransition;
    info.index = (uint32_t)layout_transitions.size();
    info.access_state = access_state;

    PendingLayoutTransition &layout_transition = layout_transitions.emplace_back();
    layout_transition.ordering = layout_transition_ordering_barrier;
    layout_transition.handle_index = layout_transition_handle_index;
}

void PendingBarriers::Apply(const ResourceUsageTag exec_tag) {
    for (const PendingBarrierInfo &info : infos) {
        if (info.type == PendingBarrierType::ReadAccessBarrier) {
            const PendingReadBarrier &read_barrier = read_barriers[info.index];
            info.access_state->ApplyPendingReadBarrier(read_barrier, exec_tag);
        } else if (info.type == PendingBarrierType::WriteAccessBarrier) {
            const PendingWriteBarrier &write_barrier = write_barriers[info.index];
            info.access_state->ApplyPendingWriteBarrier(write_barrier);
        } else {
            assert(info.type == PendingBarrierType::LayoutTransition);
            const PendingLayoutTransition &layout_transition = layout_transitions[info.index];
            info.access_state->ApplyPendingLayoutTransition(layout_transition, exec_tag);
        }
    }
}

void ApplyBarriers(AccessState &access_state, const std::vector<SyncBarrier> &barriers, bool layout_transition,
                   ResourceUsageTag layout_transition_tag) {
    // The common case of a single barrier.
    // The pending barrier helper is unnecessary because there are no independent barriers to track.
    // The barrier can be applied directly to the access state.
    if (barriers.size() == 1) {
        access_state.ApplyBarrier(BarrierScope(barriers[0]), barriers[0], layout_transition, vvl::kNoIndex32,
                                  layout_transition_tag);
        return;
    }

    PendingBarriers pending_barriers;
    if (layout_transition) {
        // When layout transition is bundled with multiple barriers (e.g. multiple subpass dependencies
        // can be associated with the same layout transition) we need to ensure that AddLayoutTransition()
        // is called only once (it resets write state including applied barriers). That's the reason
        // CollectPendingBarriers can't be used in this scenario.
        // NOTE: CollectPendingBarriers works correctly for a common case when layout transition is defined
        // by a single barrier
        OrderingBarrier layout_ordering_barrier;
        for (const SyncBarrier &barrier : barriers) {
            layout_ordering_barrier.exec_scope |= barrier.src_exec_scope.exec_scope;
            layout_ordering_barrier.access_scope |= barrier.src_access_scope;
        }
        pending_barriers.AddLayoutTransition(&access_state, layout_ordering_barrier, vvl::kNoIndex32);

        for (const SyncBarrier &barrier : barriers) {
            pending_barriers.AddWriteBarrier(&access_state, barrier);
        }
    } else {
        // There are multiple barriers. We can't apply them sequentially because they can form dependencies
        // between themselves (result of the previous barrier might affect application of the next barrier).
        // The APIs we are dealing require that the barriers in a set of barriers are applied independently.
        // That's the intended use case of PendingBarriers helper.
        for (const SyncBarrier &barrier : barriers) {
            access_state.CollectPendingBarriers(BarrierScope(barrier), barrier, false, vvl::kNoIndex32, pending_barriers);
        }
    }
    pending_barriers.Apply(layout_transition_tag);
}

BarrierScope::BarrierScope(const SyncBarrier &barrier, QueueId scope_queue, ResourceUsageTag scope_tag)
    : src_exec_scope(barrier.src_exec_scope.exec_scope),
      src_access_scope(barrier.src_access_scope),
      scope_queue(scope_queue),
      scope_tag(scope_tag) {}

void AccessState::ApplyPendingReadBarrier(const PendingReadBarrier &read_barrier, ResourceUsageTag tag) {
    // Do not register read barriers if layout transition has been registered for the same barrier API command.
    // The layout transition resets the read state (if any) and sets a write instead. By definition of our
    // implementation the read barriers are the barriers we apply to read accesses, so without read accesses we
    // don't need read barriers.
    if (last_write.has_value() && last_write->tag == tag && last_write->access_index == SYNC_IMAGE_LAYOUT_TRANSITION) {
        return;
    }

    ReadState &read_state = last_reads[read_barrier.last_reads_index];
    read_state.barriers |= read_barrier.barriers;
    read_execution_barriers |= read_barrier.barriers;
}

void AccessState::ApplyPendingWriteBarrier(const PendingWriteBarrier &write_barrier) {
    if (last_write.has_value()) {
        last_write->dependency_chain |= write_barrier.dependency_chain;
        last_write->barriers |= write_barrier.barriers;
    }
}

void AccessState::ApplyPendingLayoutTransition(const PendingLayoutTransition &layout_transition, ResourceUsageTag tag) {
    const SyncAccessInfo &layout_usage_info = GetAccessInfo(SYNC_IMAGE_LAYOUT_TRANSITION);
    const ResourceUsageTagEx tag_ex = ResourceUsageTagEx{tag, layout_transition.handle_index};
    SetWrite(SYNC_IMAGE_LAYOUT_TRANSITION, AttachmentAccess::NonAttachment(), tag_ex);
    UpdateFirst(tag_ex, layout_usage_info, AttachmentAccess::NonAttachment());
    TouchupFirstForLayoutTransition(tag, layout_transition.ordering);
}

// Assumes signal queue != wait queue
void AccessState::ApplySemaphore(const SemaphoreScope &signal, const SemaphoreScope &wait) {
    // Semaphores only guarantee the first scope of the signal is before the second scope of the wait.
    // If any access isn't in the first scope, there are no guarantees, thus those barriers are cleared
    assert(signal.queue != wait.queue);
    for (auto &read_access : GetReads()) {
        if (read_access.ReadOrDependencyChainInSourceScope(signal.queue, signal.exec_scope)) {
            // Deflects WAR on wait queue
            read_access.barriers = wait.exec_scope;
        } else {
            // Leave sync stages alone. Update method will clear unsynchronized stages on subsequent reads as needed.
            read_access.barriers = VK_PIPELINE_STAGE_2_NONE;
        }
    }
    if (last_write.has_value() &&
        last_write->WriteOrDependencyChainInSourceScope(signal.queue, signal.exec_scope, signal.valid_accesses)) {
        // Will deflect RAW wait queue, WAW needs a chained barrier on wait queue
        read_execution_barriers = wait.exec_scope;
        last_write->barriers = wait.valid_accesses;
    } else {
        read_execution_barriers = VK_PIPELINE_STAGE_2_NONE;
        if (last_write.has_value()) last_write->barriers.reset();
    }
    if (last_write.has_value()) last_write->dependency_chain = read_execution_barriers;
}

ResourceUsageRange AccessState::GetFirstAccessRange() const {
    if (first_accesses_.empty()) {
        return {};
    }
    return ResourceUsageRange(first_accesses_.front().tag, first_accesses_.back().tag + 1);
}

bool AccessState::FirstAccessInTagRange(const ResourceUsageRange &tag_range) const {
    if (first_accesses_.empty()) {
        return false;
    }
    const ResourceUsageRange first_access_range = GetFirstAccessRange();
    return tag_range.intersects(first_access_range);
}

void AccessState::OffsetTag(ResourceUsageTag offset) {
    if (last_write.has_value()) {
        last_write->tag += offset;
    }
    for (auto &read_access : GetReads()) {
        read_access.tag += offset;
    }
    for (auto &first : first_accesses_) {
        first.tag += offset;
    }
}

// Copies everything except read states which need custom logic
void AccessState::CopySimpleMembers(const AccessState &other) {
    next_global_barrier_index = other.next_global_barrier_index;

    last_write = other.last_write;

    last_read_stages = other.last_read_stages;
    read_execution_barriers = other.read_execution_barriers;

    first_accesses_ = other.first_accesses_;
    first_read_stages_ = other.first_read_stages_;
    first_write_layout_ordering_index = other.first_write_layout_ordering_index;
    first_access_closed_ = other.first_access_closed_;

    input_attachment_read = other.input_attachment_read;
}

AccessState::AccessState(const AccessState &other) { Assign(other); }

void AccessState::Assign(const AccessState &other) {
    CopySimpleMembers(other);
    ClearReadStates();
    for (const ReadState &read : other.GetReads()) {
        AddRead(read);
    }
}

AccessState::AccessState(AccessState &&other) { Assign(std::move(other)); }

void AccessState::Assign(AccessState &&other) {
    CopySimpleMembers(other);

    last_read_count = other.last_read_count;
    single_last_read = other.single_last_read;

    if (other.last_read_count == 1) {
        last_reads = &single_last_read;
    } else {
        last_reads = other.last_reads;
    }
    other.last_reads = nullptr;
    other.last_read_count = 0;
}

AccessState ::~AccessState() {
    ClearReadStates();  // free allocated memory for multi-read access state
}

VkPipelineStageFlags2 AccessState::GetReadBarriers(SyncAccessIndex access_index) const {
    for (const auto &read_access : GetReads()) {
        if (read_access.access_index == access_index) {
            return read_access.barriers;
        }
    }
    return VK_PIPELINE_STAGE_2_NONE;
}

void AccessState::SetQueueId(QueueId id) {
    for (auto &read_access : GetReads()) {
        if (read_access.queue == kQueueIdInvalid) {
            read_access.queue = id;
        }
    }
    if (last_write.has_value()) {
        last_write->SetQueueId(id);
    }
}

bool AccessState::IsWriteBarrierHazard(QueueId queue_id, VkPipelineStageFlags2 src_exec_scope,
                                       const SyncAccessFlags &src_access_scope) const {
    return last_write.has_value() && last_write->IsWriteBarrierHazard(queue_id, src_exec_scope, src_access_scope);
}

// As ReadStates must be unique by stage, this is as good a sort as needed
bool operator<(const ReadState &lhs, const ReadState &rhs) { return lhs.stage < rhs.stage; }

void AccessState::Normalize() {
    std::sort(last_reads, last_reads + last_read_count);
    ClearFirstUse();
}

void AccessState::GatherReferencedTags(ResourceUsageTagSet &used) const {
    if (last_write.has_value()) {
        used.CachedInsert(last_write->tag);
    }

    for (const auto &read_access : GetReads()) {
        used.CachedInsert(read_access.tag);
    }
}

const WriteState &AccessState::LastWrite() const {
    assert(last_write.has_value());
    return *last_write;
}

void AccessState::UpdateStats(AccessContextStats &stats) const {
#if VVL_ENABLE_SYNCVAL_STATS != 0
    stats.read_states += last_read_count;
    stats.write_states += last_write.has_value();
    stats.first_accesses += first_accesses_.size();
    stats.access_states_with_multiple_reads += (last_read_count > 1);
    stats.access_states_with_multiple_firsts += (first_accesses_.size() > 1);

    bool is_dynamic_allocation = false;
    // check if last reads allocate
    if (last_read_count > 1) {
        stats.access_states_dynamic_allocation_size += uint64_t(sizeof(ReadState) * last_read_count);
        is_dynamic_allocation = true;
    }
    // check if first accesses allocate
    if (first_accesses_.size() > first_accesses_.kSmallCapacity) {
        stats.access_states_dynamic_allocation_size += uint64_t(sizeof(FirstAccess) * first_accesses_.size());
        is_dynamic_allocation = true;
    }
    stats.access_states_with_dynamic_allocations += is_dynamic_allocation;
    stats.max_first_accesses_size = std::max(stats.max_first_accesses_size, (uint32_t)first_accesses_.size());
    stats.max_last_reads_count = std::max(stats.max_last_reads_count, last_read_count);
#endif
}

bool AccessState::IsRAWHazard(const SyncAccessInfo &usage_info) const {
    assert(IsRead(usage_info.access_index));
    // Only RAW vs. last_write if it doesn't happen-after any other read because either:
    //    * the previous reads are not hazards, and thus last_write must be visible and available to
    //      any reads that happen after.
    //    * the previous reads *are* hazards to last_write, have been reported, and if that hazard is fixed
    //      the current read will be also not be a hazard, thus reporting a hazard here adds no needed information.
    return last_write.has_value() && (0 == (read_execution_barriers & usage_info.stage_mask)) &&
           last_write->IsWriteHazard(usage_info);
}

VkPipelineStageFlags2 AccessState::GetOrderedStages(QueueId queue_id, const OrderingBarrier &ordering,
                                                    AttachmentAccessType attachment_access_type) const {
    // At apply queue submission order limits on the effect of ordering
    VkPipelineStageFlags2 non_qso_stages = VK_PIPELINE_STAGE_2_NONE;
    if (queue_id != kQueueIdInvalid) {
        for (const auto &read_access : GetReads()) {
            if (read_access.queue != queue_id) {
                non_qso_stages |= read_access.stage;
            }
        }
    }
    // Whether the stage are in the ordering scope only matters if the current write is ordered
    const VkPipelineStageFlags2 read_stages_in_qso = last_read_stages & ~non_qso_stages;
    VkPipelineStageFlags2 ordered_stages = read_stages_in_qso & ordering.exec_scope;
    // Special input attachment handling as always (not encoded in exec_scop)
    const bool input_attachment_ordering = ordering.access_scope[SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ];
    if (input_attachment_ordering && input_attachment_read && attachment_access_type == AttachmentAccessType::StoreOp) {
        // If we have an input attachment in last_reads and input attachments are ordered we all that stage
        ordered_stages |= VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
    }

    return ordered_stages;
}

void AccessState::UpdateFirst(const ResourceUsageTagEx tag_ex, const SyncAccessInfo &usage_info,
                              const AttachmentAccess &attachment_access, SyncFlags flags) {
    // Only record until we record a write.
    if (!first_access_closed_) {
        const bool is_read = IsRead(usage_info.access_index);
        const VkPipelineStageFlags2 usage_stage = is_read ? usage_info.stage_mask : 0U;
        if (0 == (usage_stage & first_read_stages_)) {
            // If this is a read we haven't seen or a write, record.
            // We always need to know what stages were found prior to write
            first_read_stages_ |= usage_stage;
            if (0 == (read_execution_barriers & usage_stage)) {
                // If this stage isn't masked then we add it (since writes map to usage_stage 0, this also records writes)
                first_accesses_.emplace_back(usage_info, tag_ex, attachment_access, flags);
                first_access_closed_ = !is_read;
            }
        }
    }
}

void AccessState::TouchupFirstForLayoutTransition(ResourceUsageTag tag, const OrderingBarrier &layout_ordering) {
    // Only call this after recording an image layout transition
    assert(first_accesses_.size());
    if (first_accesses_.back().tag == tag) {
        // If this layout transition is the the first write, add the additional ordering rules that guard the ILT
        assert(first_accesses_.back().usage_info->access_index == SyncAccessIndex::SYNC_IMAGE_LAYOUT_TRANSITION);
        auto &layout_ordering_lookup = GetLayoutOrderingBarrierLookup();
        first_write_layout_ordering_index = layout_ordering_lookup.GetIndexAndMaybeInsert(layout_ordering);
    }
}

void ReadState::Set(VkPipelineStageFlagBits2 stage, SyncAccessIndex access_index, ResourceUsageTagEx tag_ex) {
    assert(access_index != SYNC_ACCESS_INDEX_NONE);
    this->stage = stage;
    this->access_index = access_index;
    barriers = VK_PIPELINE_STAGE_2_NONE;
    sync_stages = VK_PIPELINE_STAGE_2_NONE;
    tag = tag_ex.tag;
    handle_index = tag_ex.handle_index;
    queue = kQueueIdInvalid;
}

// Scope test including "queue submission order" effects.  Specifically, accesses from a different queue are not
// considered to be in "queue submission order" with barriers, events, or semaphore signalling, but any barriers
// that have bee applied (via semaphore) to those accesses can be chained off of.
bool ReadState::ReadOrDependencyChainInSourceScope(QueueId scope_queue, VkPipelineStageFlags2 src_exec_scope) const {
    VkPipelineStageFlags2 effective_stages = barriers | ((scope_queue == queue) ? stage : VK_PIPELINE_STAGE_2_NONE);

    // Special case. AS copy operations (e.g., vkCmdCopyAccelerationStructureKHR) can be synchronized using
    // the ACCELERATION_STRUCTURE_COPY stage, but it's also valid to use ACCELERATION_STRUCTURE_BUILD stage.
    // Internally, AS copy accesses are represented via ACCELERATION_STRUCTURE_COPY stage. The logic below
    // ensures that ACCELERATION_STRUCTURE_COPY accesses can be protected by the barrier that specifies the
    // ACCELERATION_STRUCTURE_BUILD state.
    if (access_index == SYNC_ACCELERATION_STRUCTURE_COPY_ACCELERATION_STRUCTURE_READ) {
        effective_stages |= VK_PIPELINE_STAGE_2_ACCELERATION_STRUCTURE_BUILD_BIT_KHR;
    }

    return (src_exec_scope & effective_stages) != 0;
}

bool ReadState::InBarrierSourceScope(const BarrierScope &barrier_scope) const {
    // TODO: the following comment is from the initial implementation. Check it during Event rework.
    // NOTE: That's not really correct... this read stage might *not* have been included in the SetEvent,
    // and the barriers representing the chain might have changed since then (that would be an odd usage),
    // so as a first approximation we'll assume the barriers *haven't* been changed since (if the tag hasn't),
    // and while this could be a false positive in the case of Set; SomeBarrier; Wait; we'll live with it
    // until we can add more state to the first scope capture (the specific write and read stages that
    // *were* in scope at the moment of SetEvents.
    if (tag > barrier_scope.scope_tag) {
        return false;
    }

    return ReadOrDependencyChainInSourceScope(barrier_scope.scope_queue, barrier_scope.src_exec_scope);
}

void WriteState::Set(SyncAccessIndex access_index, const AttachmentAccess &attachment_access, ResourceUsageTagEx tag_ex,
                     SyncFlags flags) {
    this->access_index = access_index;
    this->attachment_access = attachment_access;
    barriers.reset();
    dependency_chain = VK_PIPELINE_STAGE_2_NONE;
    tag = tag_ex.tag;
    handle_index = tag_ex.handle_index;
    queue = kQueueIdInvalid;
    this->flags = flags;
}

void WriteState::SetQueueId(QueueId id) {
    // TODO: investigate if we need to check for invalid queue before assignment.
    // Currently no tests fail if we do uncoditional assignment, but in theory this might
    // be part of submit time logic that prevents already initialize ids from being overwritten.
    // If we don't need this check then SetQueueId can be removed.
    if (queue == kQueueIdInvalid) {
        queue = id;
    }
}

bool WriteState::operator==(const WriteState &rhs) const {
    return (access_index == rhs.access_index) && (barriers == rhs.barriers) && (tag == rhs.tag) && (queue == rhs.queue) &&
           (dependency_chain == rhs.dependency_chain);
}

bool WriteState::IsWriteHazard(const SyncAccessInfo &usage_info) const { return !barriers[usage_info.access_index]; }

bool WriteState::IsOrdered(const OrderingBarrier &ordering, QueueId queue_id) const {
    return (queue == queue_id) && ordering.access_scope[access_index];
}

bool WriteState::IsWriteBarrierHazard(QueueId queue_id, VkPipelineStageFlags2 src_exec_scope,
                                      const SyncAccessFlags &src_access_scope) const {
    // Current implementation relies on TOP_OF_PIPE constant due to the fact that it's non-zero value
    // and AND-ing with it can create execution dependency when necessary. One example, it allows the
    // ALL_COMMANDS stage to guard all accesses even if NONE/TOP_OF_PIPE is used. When NONE constant is
    // used, which has numerical value of zero, then AND-ing with it always results in 0 which means
    // "no barrier", so it's not possible to use NONE internally in equivalent way to TOP_OF_PIPE.
    // Here we replace NONE with TOP_OF_PIPE in the scenarios where they are equivalent according to the spec.
    //
    // If we update implementation to get rid of deprecated TOP_OF_PIPE/BOTTOM_OF_PIPE then we must
    // invert the condition below and exchange TOP_OF_PIPE and NONE roles, so deprecated stages would
    // not propagate into implementation internals.
    if (src_exec_scope == VK_PIPELINE_STAGE_2_NONE && src_access_scope.none()) {
        src_exec_scope = VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT;
    }

    // Special rules for sequential ILT's
    if (access_index == SYNC_IMAGE_LAYOUT_TRANSITION) {
        if (queue == queue_id) {
            // In queue, they are implicitly ordered
            return false;
        } else {
            // In dep chain means that the ILT is *available*
            return !DependencyChainInSourceScope(src_exec_scope);
        }
    }
    // In dep chain means that the write is *available*.
    // Available writes are automatically made visible and can't cause hazards during transition.
    if (DependencyChainInSourceScope(src_exec_scope)) {
        return false;
    }
    // The write is not in chain (previous call), so need only to check if the write is in access scope.
    return !WriteInSourceScope(src_access_scope);
}

void WriteState::MergeBarriers(const WriteState &other) {
    barriers |= other.barriers;
    dependency_chain |= other.dependency_chain;
}

bool WriteState::DependencyChainInSourceScope(VkPipelineStageFlags2 src_exec_scope) const {
    return (dependency_chain & src_exec_scope) != 0;
}

bool WriteState::WriteInSourceScope(const SyncAccessFlags &src_access_scope) const { return src_access_scope[access_index]; }

bool WriteState::WriteOrDependencyChainInSourceScope(QueueId queue_id, VkPipelineStageFlags2 src_exec_scope,
                                                     const SyncAccessFlags &src_access_scope) const {
    return DependencyChainInSourceScope(src_exec_scope) || (queue == queue_id && WriteInSourceScope(src_access_scope));
}

bool WriteState::InBarrierSourceScope(const BarrierScope &barrier_scope) const {
    if (tag > barrier_scope.scope_tag) {
        return false;
    }

    QueueId scope_queue = barrier_scope.scope_queue;

    // Ensure that queue test in InSourceScope passes when barrier scope does not define a queue
    if (scope_queue == kQueueIdInvalid) {
        scope_queue = queue;
    }

    return WriteOrDependencyChainInSourceScope(scope_queue, barrier_scope.src_exec_scope, barrier_scope.src_access_scope);
}

HazardResult::HazardState::HazardState(const AccessState *access_state_, const SyncAccessInfo &access_info_, SyncHazard hazard_,
                                       SyncAccessIndex prior_access_index, ResourceUsageTagEx tag_ex)
    : access_state(std::make_unique<const AccessState>(*access_state_)),
      recorded_access(),
      access_index(access_info_.access_index),
      prior_access_index(prior_access_index),
      tag(tag_ex.tag),
      handle_index(tag_ex.handle_index),
      hazard(hazard_) {
    assert(prior_access_index != SYNC_ACCESS_INDEX_NONE);
    // Touchup the hazard to reflect "present as release" semantics
    // NOTE: For implementing QFO release/acquire semantics... touch up here as well
    if (access_state->IsLastWriteOp(SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_PRESENTED_SYNCVAL)) {
        if (hazard == SyncHazard::READ_AFTER_WRITE) {
            hazard = SyncHazard::READ_AFTER_PRESENT;
        } else if (hazard == SyncHazard::WRITE_AFTER_WRITE) {
            hazard = SyncHazard::WRITE_AFTER_PRESENT;
        }
    } else if (access_index == SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_PRESENTED_SYNCVAL) {
        if (hazard == SyncHazard::WRITE_AFTER_READ) {
            hazard = SyncHazard::PRESENT_AFTER_READ;
        } else if (hazard == SyncHazard::WRITE_AFTER_WRITE) {
            hazard = SyncHazard::PRESENT_AFTER_WRITE;
        }
    }
}

const char *string_SyncHazardVUID(SyncHazard hazard) {
    switch (hazard) {
        case SyncHazard::NONE:
            return "SYNC-HAZARD-NONE";
            break;
        case SyncHazard::READ_AFTER_WRITE:
            return "SYNC-HAZARD-READ-AFTER-WRITE";
            break;
        case SyncHazard::WRITE_AFTER_READ:
            return "SYNC-HAZARD-WRITE-AFTER-READ";
            break;
        case SyncHazard::WRITE_AFTER_WRITE:
            return "SYNC-HAZARD-WRITE-AFTER-WRITE";
            break;
        case SyncHazard::READ_RACING_WRITE:
            return "SYNC-HAZARD-READ-RACING-WRITE";
            break;
        case SyncHazard::WRITE_RACING_WRITE:
            return "SYNC-HAZARD-WRITE-RACING-WRITE";
            break;
        case SyncHazard::WRITE_RACING_READ:
            return "SYNC-HAZARD-WRITE-RACING-READ";
            break;
        case SyncHazard::READ_AFTER_PRESENT:
            return "SYNC-HAZARD-READ-AFTER-PRESENT";
            break;
        case SyncHazard::WRITE_AFTER_PRESENT:
            return "SYNC-HAZARD-WRITE-AFTER-PRESENT";
            break;
        case SyncHazard::PRESENT_AFTER_WRITE:
            return "SYNC-HAZARD-PRESENT-AFTER-WRITE";
            break;
        case SyncHazard::PRESENT_AFTER_READ:
            return "SYNC-HAZARD-PRESENT-AFTER-READ";
            break;
        default:
            assert(0);
    }
    return "SYNC-HAZARD-INVALID";
}

SyncHazardInfo GetSyncHazardInfo(SyncHazard hazard) {
    switch (hazard) {
        case SyncHazard::NONE:
            return SyncHazardInfo{};
        case SyncHazard::READ_AFTER_WRITE:
            return SyncHazardInfo{false, true};
        case SyncHazard::WRITE_AFTER_READ:
            return SyncHazardInfo{true, false};
        case SyncHazard::WRITE_AFTER_WRITE:
            return SyncHazardInfo{true, true};
        case SyncHazard::READ_RACING_WRITE:
            return SyncHazardInfo{false, true, true};
        case SyncHazard::WRITE_RACING_WRITE:
            return SyncHazardInfo{true, true, true};
        case SyncHazard::WRITE_RACING_READ:
            return SyncHazardInfo{true, false, true};
        case SyncHazard::READ_AFTER_PRESENT:
            return SyncHazardInfo{false, true};
        case SyncHazard::WRITE_AFTER_PRESENT:
            return SyncHazardInfo{true, true};
        case SyncHazard::PRESENT_AFTER_WRITE:
            return SyncHazardInfo{true, true};
        case SyncHazard::PRESENT_AFTER_READ:
            return SyncHazardInfo{true, false};
        default:
            assert(false && "Unhandled SyncHazard value");
            return SyncHazardInfo{};
    }
}

}  // namespace syncval
