/* Copyright (c) 2019-2026 The Khronos Group Inc.
 * 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 <algorithm>
#include <iostream>
#include <memory>
#include <vector>

#include "sync/sync_error_messages.h"
#include "sync/sync_validation.h"
#include "sync/sync_image.h"
#include "state_tracker/buffer_state.h"
#include "state_tracker/ray_tracing_state.h"
#include "utils/convert_utils.h"
#include "utils/ray_tracing_utils.h"
#include "utils/text_utils.h"
#include "vk_layer_config.h"
#include "containers/tls_guard.h"

namespace syncval {

static bool GetShowStatsEnvVar() {
    // Set environment variable as non zero number to enable stats reporting
    const auto show_stats_str = GetEnvironment("VK_SYNCVAL_SHOW_STATS");
    return !show_stats_str.empty() && std::atoi(show_stats_str.c_str()) != 0;
}

SyncValidator::SyncValidator(vvl::dispatch::Device *dev, syncval::Instance *instance_vo)
    : BaseClass(dev, instance_vo, LayerObjectTypeSyncValidation), error_messages_(*this), report_stats_(GetShowStatsEnvVar()) {}

SyncValidator::~SyncValidator() {
    // Instance level SyncValidator does not have much to say
    const bool device_validation_object = (device != nullptr);

    if (device_validation_object && report_stats_) {
        stats.ReportOnDestruction();
    }
}

// Location to add per-queue submit debug info if built with -D DEBUG_CAPTURE_KEYBOARD=ON.
void SyncValidator::DebugCapture() {
    if (report_stats_) {
        stats.UpdateAccessStats(*this);

        // NOTE: mimalloc stats are not updated here - mostly because they are tracked
        // per thread and updating stats only for current thread feels a bit unbalanced.
        // Instead we have specific places to trigger memory stats collection.

        const std::string report = stats.CreateReport();
        std::cout << report;
#ifdef VK_USE_PLATFORM_WIN32_KHR
        OutputDebugString(report.c_str());
#endif
    }
}

bool SyncValidator::SyncError(SyncHazard hazard, const LogObjectList &objlist, const Location &loc,
                              const std::string &error_message) const {
    return LogError(string_SyncHazardVUID(hazard), objlist, loc, "%s", error_message.c_str());
}

ResourceUsageRange SyncValidator::ReserveGlobalTagRange(size_t tag_count) const {
    ResourceUsageRange reserve;
    reserve.begin = tag_limit_.fetch_add(tag_count);
    reserve.end = reserve.begin + tag_count;
    return reserve;
}

void SyncValidator::EnsureTimelineSignalsLimit(uint32_t signals_per_queue_limit, QueueId queue) {
    for (auto &[_, signals] : timeline_signals_) {
        const size_t initial_signal_count = signals.size();
        vvl::unordered_map<QueueId, uint32_t> signals_per_queue;
        for (const SignalInfo &signal : signals) {
            ++signals_per_queue[signal.first_scope.queue];
        }
        const bool filter_queue = queue != kQueueIdInvalid;
        for (auto it = signals.begin(); it != signals.end();) {
            if (filter_queue && it->first_scope.queue != queue) {
                ++it;
                continue;
            }
            auto &counter = signals_per_queue[it->first_scope.queue];
            if (counter > signals_per_queue_limit) {
                it = signals.erase(it);
                --counter;
            } else {
                ++it;
            }
        }
        stats.RemoveTimelineSignals(uint32_t(initial_signal_count - signals.size()));
    }
}

void SyncValidator::ApplySignalsUpdate(SignalsUpdate &update, const QueueBatchContext::Ptr &last_batch) {
    // NOTE: All conserved QueueBatchContexts need to have their access logs reset to use the global
    // logger and the only conserved QBCs are those referenced by unwaited signals and the last batch.

    for (auto &signal_entry : update.binary_signal_requests) {
        auto &signal_batch = signal_entry.second.batch;
        // Batches retained for signalled semaphore don't need to retain
        // event data, unless it's the last batch in the submit
        if (signal_batch != last_batch) {
            signal_batch->ResetEventsContext();
            // Make sure that retained batches are minimal, and trim
            // after the events contexts has been cleared.
            signal_batch->Trim();
        }
        const VkSemaphore semaphore = signal_entry.first;
        SignalInfo &signal_info = signal_entry.second;
        binary_signals_.insert_or_assign(semaphore, std::move(signal_info));
    }
    for (VkSemaphore semaphore : update.binary_unsignal_requests) {
        binary_signals_.erase(semaphore);
    }
    for (auto &[semaphore, new_signals] : update.timeline_signals) {
        std::vector<SignalInfo> &signals = timeline_signals_[semaphore];
        vvl::Append(signals, new_signals);
        stats.AddTimelineSignals((uint32_t)new_signals.size());

        // Update host sync points
        std::deque<TimelineHostSyncPoint> &host_sync_points = host_waitable_semaphores_[semaphore];
        for (SignalInfo &new_signal : new_signals) {
            if (new_signal.batch) {
                // The lifetimes of the semaphore host sync points are managed by vkWaitSemaphores.
                // kMaxTimelineHostSyncPoints limit is used when the program does not use vkWaitSemaphores.
                // We accumulate up to kMaxTimelineHostSyncPoints of the host sync points per semaphore.
                // Dropping old sync points cannot introduce false positives but may miss a sync hazard.
                // The limit is chosen to be large enough comparing to typical numbers of queue submissions
                // between host synchronization points.
                const uint32_t kMaxTimelineHostSyncPoints = 256;  // max ~6 Kb per semaphore
                if (host_sync_points.size() >= kMaxTimelineHostSyncPoints) {
                    host_sync_points.pop_front();
                }
                // Add a host sync point for this signal
                TimelineHostSyncPoint sync_point;
                assert(new_signal.first_scope.queue != kQueueIdInvalid);
                sync_point.queue_id = new_signal.first_scope.queue;
                sync_point.tag = new_signal.batch->GetTagRange().end - 1;
                sync_point.timeline_value = new_signal.timeline_value;
                host_sync_points.emplace_back(sync_point);
            }
        }
    }
    for (const auto &remove_signals_request : update.remove_timeline_signals_requests) {
        auto &signals = timeline_signals_[remove_signals_request.semaphore];
        for (auto it = signals.begin(); it != signals.end();) {
            const SignalInfo &signal = *it;
            if (signal.first_scope.queue == remove_signals_request.queue &&
                signal.timeline_value < remove_signals_request.signal_threshold_value) {
                it = signals.erase(it);
                stats.RemoveTimelineSignals(1);
                continue;
            }
            ++it;
        }
    }

    // Enforce max signals limit in case timeline is signaled multiple times and never/rarely is waited on.
    // This does not introduce errors/false-positives (check EnsureTimelineSignalsLimit documentation)
    const uint32_t kMaxTimelineSignalsPerQueue = 100;
    EnsureTimelineSignalsLimit(kMaxTimelineSignalsPerQueue);
}

void SyncValidator::ApplyTaggedWait(QueueId queue_id, ResourceUsageTag tag,
                                    const LastSynchronizedPresent &last_synchronized_present,
                                    const std::vector<ResourceUsageTag> &queue_sync_tags) {
    assert(queue_id < queue_id_limit_);
    assert(queue_sync_tags.empty() || queue_sync_tags.size() == queue_id_limit_);
    assert(queue_sync_tags.empty() || queue_sync_tags[queue_id] == tag);

    // Create a list of queues that have to be synchronized up to some point.
    // Note that, in general, not only the queue_id queue has to be synchronized.
    // If queue_id was synchronized with other queues through a semaphore wait,
    // then waiting for queue_id also means waiting for those other queues
    std::vector<std::pair<QueueId, ResourceUsageTag>> sync_points;
    if (queue_sync_tags.empty()) {
        sync_points.emplace_back(queue_id, tag);
    } else {
        sync_points.reserve(queue_id_limit_);
        for (const auto [sync_queue, sync_tag] : vvl::enumerate(queue_sync_tags)) {
            if (sync_tag > 0) {
                sync_points.emplace_back((QueueId)sync_queue, sync_tag);
            }
        }
    }

    const auto all_batches = GetAllQueueBatchContexts();
    for (const auto &batch : all_batches) {
        for (const auto &[sync_queue, sync_tag] : sync_points) {
            batch->ApplyTaggedWait(sync_queue, sync_tag, last_synchronized_present);
        }
        batch->Trim();

        // If there is a *pending* last batch then apply tagged wait for its accesses too.
        // A pending last batch might exist if this wait was initiated between QueueSubmit's
        // Validate and Record phases (from a different thread). The pending last batch might
        // contain *imported* accesses that are in the scope of this wait.
        auto batch_queue_state = batch->GetQueueSyncState();
        auto pending_batch = batch_queue_state ? batch_queue_state->PendingLastBatch() : nullptr;
        if (pending_batch) {
            for (const auto &[sync_queue, sync_tag] : sync_points) {
                pending_batch->ApplyTaggedWait(sync_queue, sync_tag, last_synchronized_present);
            }
            pending_batch->Trim();
        }
    }
}

void SyncValidator::ApplyAcquireWait(const AcquiredImage &acquired) {
    for (const auto &batch : GetAllQueueBatchContexts()) {
        batch->ApplyAcquireWait(acquired);
        batch->Trim();
    }
}

std::vector<QueueBatchContext::Ptr> SyncValidator::GetAllQueueBatchContexts() {
    // Get last batch from each queue
    std::vector<QueueBatchContext::Ptr> batch_contexts = GetLastBatches([](auto) { return true; });

    // Get batches from binary signals
    for (auto &[_, signal] : binary_signals_) {
        if (!vvl::Contains(batch_contexts, signal.batch)) {
            batch_contexts.emplace_back(signal.batch);
        }
    }
    // Get batches from timeline signals
    for (auto &[_, signals] : timeline_signals_) {
        for (const auto &signal : signals) {
            if (signal.batch && !vvl::Contains(batch_contexts, signal.batch)) {
                batch_contexts.emplace_back(signal.batch);
            }
        }
    }
    // Get present batches
    device_state->ForEachShared<vvl::Swapchain>([&batch_contexts](const std::shared_ptr<vvl::Swapchain> &swapchain) {
        auto &sync_swapchain = SubState(*swapchain);
        sync_swapchain.GetPresentBatches(batch_contexts);
    });

    return batch_contexts;
}

void SyncValidator::UpdateFenceHostSyncPoint(VkFence fence, FenceHostSyncPoint &&sync_point) {
    std::shared_ptr<const vvl::Fence> fence_state = Get<vvl::Fence>(fence);
    if (!vvl::StateObject::Invalid(fence_state)) {
        waitable_fences_[fence_state->VkHandle()] = std::move(sync_point);
    }
}

void SyncValidator::WaitForFence(VkFence fence) {
    auto fence_it = waitable_fences_.find(fence);
    if (fence_it != waitable_fences_.end()) {
        // The fence may no longer be waitable for several valid reasons.
        FenceHostSyncPoint &wait_for = fence_it->second;
        if (wait_for.acquired.Invalid()) {
            // This is just a normal fence wait
            ApplyTaggedWait(wait_for.queue_id, wait_for.tag, {}, wait_for.queue_sync_tags);
        } else {
            // This a fence wait for a present operation
            ApplyAcquireWait(wait_for.acquired);
        }
        waitable_fences_.erase(fence_it);
    }
}

void SyncValidator::WaitForSemaphore(VkSemaphore semaphore, uint64_t value) {
    std::deque<TimelineHostSyncPoint> *sync_points = vvl::Find(host_waitable_semaphores_, semaphore);
    if (!sync_points) {
        return;
    }
    auto matching_sync_point = [value](const TimelineHostSyncPoint &sync_point) { return sync_point.timeline_value >= value; };
    auto sync_point_it = std::find_if(sync_points->begin(), sync_points->end(), matching_sync_point);
    if (sync_point_it == sync_points->end()) {
        return;
    }

    const TimelineHostSyncPoint &sync_point = *sync_point_it;
    const auto queue_state = GetQueueSyncStateShared(sync_point.queue_id);

    // TODO: specify queue sync tags argument similar to WaitForFence
    ApplyTaggedWait(sync_point.queue_id, sync_point.tag, queue_state->GetLastSynchronizedPresent(), {});

    // Remove signals before the resolving one (keep the resolving signal).
    std::vector<SignalInfo> &signals = timeline_signals_[semaphore];
    const size_t initial_signal_count = signals.size();
    vvl::erase_if(signals, [&sync_point](SignalInfo &signal) {
        return signal.first_scope.queue == sync_point.queue_id && signal.timeline_value < sync_point.timeline_value;
    });
    stats.RemoveTimelineSignals(uint32_t(initial_signal_count - signals.size()));

    // We can remove all sync points that are in the scope of current wait.
    // Subsequent attempts to synchronize on the host with already synchronized
    // timeline values will result in noop.
    sync_points->erase(sync_points->begin(), sync_point_it + 1 /* include resolving sync point too*/);
}

void SyncValidator::UpdateSyncImageMemoryBindState(uint32_t count, const VkBindImageMemoryInfo *infos) {
    for (const auto &info : vvl::make_span(infos, count)) {
        if (VK_NULL_HANDLE == info.image) continue;
        auto image_state = Get<vvl::Image>(info.image);

        // Need to protect if some VkBindMemoryStatus are not VK_SUCCESS
        if (!image_state->HasBeenBound()) continue;

        auto &sub_state = SubState(*image_state);
        if (sub_state.IsTiled()) {
            sub_state.SetOpaqueBaseAddress(*device_state);
        }
    }
}

std::shared_ptr<const QueueSyncState> SyncValidator::GetQueueSyncStateShared(VkQueue queue) const {
    for (const auto &queue_sync_state : queue_sync_states_) {
        if (queue_sync_state->GetQueueState()->VkHandle() == queue) {
            return queue_sync_state;
        }
    }
    return {};
}

std::shared_ptr<const QueueSyncState> SyncValidator::GetQueueSyncStateShared(QueueId queue_id) const {
    for (const auto &queue_sync_state : queue_sync_states_) {
        if (queue_sync_state->GetQueueId() == queue_id) {
            return queue_sync_state;
        }
    }
    return {};
}

void SyncValidator::Created(vvl::CommandBuffer &cb_state) {
    cb_state.SetSubState(container_type, std::make_unique<CommandBufferSubState>(*this, cb_state));
}

void SyncValidator::Created(vvl::Swapchain &swapchain_state) {
    swapchain_state.SetSubState(container_type, std::make_unique<SwapchainSubState>(swapchain_state));
}

void SyncValidator::Created(vvl::Image &image_state) {
    image_state.SetSubState(container_type, std::make_unique<ImageSubState>(image_state));
}

void SyncValidator::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator,
                                               const RecordObject &record_obj) {
    if (const auto buffer_state = Get<vvl::Buffer>(buffer)) {
        const VkDeviceSize base_address = ResourceBaseAddress(*buffer_state);
        const AccessRange buffer_range(base_address, base_address + buffer_state->create_info.size);
        for (const auto &batch : GetAllQueueBatchContexts()) {
            batch->OnResourceDestroyed(buffer_range);
            batch->Trim();
        }
    }
}

void SyncValidator::PreCallRecordDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator,
                                              const RecordObject &record_obj) {
    if (const auto image_state = Get<vvl::Image>(image)) {
        for (const auto &batch : GetAllQueueBatchContexts()) {
            const auto &sub_state = SubState(*image_state);
            ImageRangeGen range_gen = sub_state.MakeImageRangeGen(image_state->full_range, false);
            for (; range_gen->non_empty(); ++range_gen) {
                const AccessRange subresource_range = *range_gen;
                batch->OnResourceDestroyed(subresource_range);
            }
            batch->Trim();
        }
    }
}

void SyncValidator::PreCallRecordDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
                                                     const VkAllocationCallbacks *pAllocator, const RecordObject &record_obj) {
    for (const auto &batch : GetAllQueueBatchContexts()) {
        batch->last_synchronized_present.OnDestroySwapchain(swapchain);
    }
}

bool SyncValidator::PreCallValidateCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
                                                 uint32_t regionCount, const VkBufferCopy *pRegions,
                                                 const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) {
        return false;
    }

    const auto *cb_context = GetAccessContext(*cb_state);
    const auto *context = cb_context->GetCurrentAccessContext();

    // If we have no previous accesses, we have no hazards
    auto src_buffer = Get<vvl::Buffer>(srcBuffer);
    auto dst_buffer = Get<vvl::Buffer>(dstBuffer);

    for (const auto [region_index, copy_region] : vvl::enumerate(pRegions, regionCount)) {
        if (src_buffer) {
            const AccessRange src_range = MakeRange(*src_buffer, copy_region.srcOffset, copy_region.size);
            auto hazard = context->DetectHazard(*src_buffer, SYNC_COPY_TRANSFER_READ, src_range);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, srcBuffer);
                const std::string error = error_messages_.BufferCopyError(hazard, *cb_context, error_obj.location.function,
                                                                          FormatHandle(srcBuffer), region_index, src_range);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
        if (dst_buffer) {
            const AccessRange dst_range = MakeRange(*dst_buffer, copy_region.dstOffset, copy_region.size);
            auto hazard = context->DetectHazard(*dst_buffer, SYNC_COPY_TRANSFER_WRITE, dst_range);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, dstBuffer);
                const std::string error = error_messages_.BufferCopyError(hazard, *cb_context, error_obj.location.function,
                                                                          FormatHandle(dstBuffer), region_index, dst_range);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
        if (skip) {
            break;
        }
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdCopyBuffer2(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2 *pCopyBufferInfo,
                                                  const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);
    const auto *context = cb_context->GetCurrentAccessContext();

    // If we have no previous accesses, we have no hazards
    auto src_buffer = Get<vvl::Buffer>(pCopyBufferInfo->srcBuffer);
    auto dst_buffer = Get<vvl::Buffer>(pCopyBufferInfo->dstBuffer);

    for (const auto [region_index, copy_region] : vvl::enumerate(pCopyBufferInfo->pRegions, pCopyBufferInfo->regionCount)) {
        if (src_buffer) {
            const AccessRange src_range = MakeRange(*src_buffer, copy_region.srcOffset, copy_region.size);
            auto hazard = context->DetectHazard(*src_buffer, SYNC_COPY_TRANSFER_READ, src_range);
            if (hazard.IsHazard()) {
                // TODO -- add tag information to log msg when useful.
                // TODO: there are no tests for this error
                const LogObjectList objlist(commandBuffer, pCopyBufferInfo->srcBuffer);
                const std::string error =
                    error_messages_.BufferCopyError(hazard, *cb_context, error_obj.location.function,
                                                    FormatHandle(pCopyBufferInfo->srcBuffer), region_index, src_range);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
        if (dst_buffer && !skip) {
            const AccessRange dst_range = MakeRange(*dst_buffer, copy_region.dstOffset, copy_region.size);
            auto hazard = context->DetectHazard(*dst_buffer, SYNC_COPY_TRANSFER_WRITE, dst_range);
            if (hazard.IsHazard()) {
                // TODO: there are no tests for this error
                const LogObjectList objlist(commandBuffer, pCopyBufferInfo->dstBuffer);
                const std::string error =
                    error_messages_.BufferCopyError(hazard, *cb_context, error_obj.location.function,
                                                    FormatHandle(pCopyBufferInfo->dstBuffer), region_index, dst_range);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
        if (skip) break;
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdCopyBuffer2KHR(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2KHR *pCopyBufferInfo,
                                                     const ErrorObject &error_obj) const {
    return PreCallValidateCmdCopyBuffer2(commandBuffer, pCopyBufferInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
                                                VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
                                                const VkImageCopy *pRegions, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto src_image = Get<vvl::Image>(srcImage);
    auto dst_image = Get<vvl::Image>(dstImage);
    for (const auto [region_index, copy_region] : vvl::enumerate(pRegions, regionCount)) {
        if (src_image) {
            auto hazard = context->DetectHazard(*src_image, RangeFromLayers(copy_region.srcSubresource), copy_region.srcOffset,
                                                copy_region.extent, SYNC_COPY_TRANSFER_READ);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, srcImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, error_obj.location.function, FormatHandle(srcImage), region_index,
                    copy_region.srcOffset, copy_region.extent, copy_region.srcSubresource);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }

        if (dst_image) {
            auto hazard = context->DetectHazard(*dst_image, RangeFromLayers(copy_region.dstSubresource), copy_region.dstOffset,
                                                copy_region.extent, SYNC_COPY_TRANSFER_WRITE);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, dstImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, error_obj.location.function, FormatHandle(dstImage), region_index,
                    copy_region.dstOffset, copy_region.extent, copy_region.dstSubresource);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
        if (skip) {
            break;
        }
    }

    return skip;
}

bool SyncValidator::PreCallValidateCmdCopyImage2(VkCommandBuffer commandBuffer, const VkCopyImageInfo2 *pCopyImageInfo,
                                                 const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto src_image = Get<vvl::Image>(pCopyImageInfo->srcImage);
    auto dst_image = Get<vvl::Image>(pCopyImageInfo->dstImage);

    for (const auto [region_index, copy_region] : vvl::enumerate(pCopyImageInfo->pRegions, pCopyImageInfo->regionCount)) {
        if (src_image) {
            auto hazard = context->DetectHazard(*src_image, RangeFromLayers(copy_region.srcSubresource), copy_region.srcOffset,
                                                copy_region.extent, SYNC_COPY_TRANSFER_READ);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, pCopyImageInfo->srcImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, error_obj.location.function, FormatHandle(pCopyImageInfo->srcImage), region_index,
                    copy_region.srcOffset, copy_region.extent, copy_region.srcSubresource);
                // TODO: this error not covered by the test
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }

        if (dst_image) {
            auto hazard = context->DetectHazard(*dst_image, RangeFromLayers(copy_region.dstSubresource), copy_region.dstOffset,
                                                copy_region.extent, SYNC_COPY_TRANSFER_WRITE);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, pCopyImageInfo->dstImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, error_obj.location.function, FormatHandle(pCopyImageInfo->dstImage), region_index,
                    copy_region.dstOffset, copy_region.extent, copy_region.dstSubresource);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
            if (skip) break;
        }
    }

    return skip;
}

bool SyncValidator::PreCallValidateCmdCopyImage2KHR(VkCommandBuffer commandBuffer, const VkCopyImageInfo2KHR *pCopyImageInfo,
                                                    const ErrorObject &error_obj) const {
    return PreCallValidateCmdCopyImage2(commandBuffer, pCopyImageInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdPipelineBarrier(
    VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
    VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
    uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
    const VkImageMemoryBarrier *pImageMemoryBarriers, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    SyncOpPipelineBarrier pipeline_barrier(error_obj.location.function, *this, cb_access_context->GetQueueFlags(), srcStageMask,
                                           dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
                                           pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
    stats.OnBarrierCommand(memoryBarrierCount, bufferMemoryBarrierCount, imageMemoryBarrierCount,
                           pipeline_barrier.GetExecutionDependencyBarrierCount());
    skip |= pipeline_barrier.Validate(*cb_access_context);
    return skip;
}

void SyncValidator::PostCallRecordCmdPipelineBarrier(
    VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
    VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
    uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
    const VkImageMemoryBarrier *pImageMemoryBarriers, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_access_context = GetAccessContext(*cb_state);

    cb_access_context->RecordSyncOp<SyncOpPipelineBarrier>(
        record_obj.location.function, *this, cb_access_context->GetQueueFlags(), srcStageMask, dstStageMask, memoryBarrierCount,
        pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
}

bool SyncValidator::PreCallValidateCmdPipelineBarrier2KHR(VkCommandBuffer commandBuffer, const VkDependencyInfoKHR *pDependencyInfo,
                                                          const ErrorObject &error_obj) const {
    return PreCallValidateCmdPipelineBarrier2(commandBuffer, pDependencyInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdPipelineBarrier2(VkCommandBuffer commandBuffer, const VkDependencyInfo *pDependencyInfo,
                                                       const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    SyncOpPipelineBarrier pipeline_barrier(error_obj.location.function, *this, cb_access_context->GetQueueFlags(),
                                           *pDependencyInfo);
    stats.OnBarrierCommand(pDependencyInfo->memoryBarrierCount, pDependencyInfo->bufferMemoryBarrierCount,
                           pDependencyInfo->imageMemoryBarrierCount, pipeline_barrier.GetExecutionDependencyBarrierCount());
    skip |= pipeline_barrier.Validate(*cb_access_context);
    return skip;
}

void SyncValidator::PostCallRecordCmdPipelineBarrier2KHR(VkCommandBuffer commandBuffer, const VkDependencyInfoKHR *pDependencyInfo,
                                                         const RecordObject &record_obj) {
    PostCallRecordCmdPipelineBarrier2(commandBuffer, pDependencyInfo, record_obj);
}

void SyncValidator::PostCallRecordCmdPipelineBarrier2(VkCommandBuffer commandBuffer, const VkDependencyInfo *pDependencyInfo,
                                                      const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_access_context = GetAccessContext(*cb_state);

    cb_access_context->RecordSyncOp<SyncOpPipelineBarrier>(record_obj.location.function, *this, cb_access_context->GetQueueFlags(),
                                                           *pDependencyInfo);
}

void SyncValidator::FinishDeviceSetup(const VkDeviceCreateInfo *pCreateInfo, const Location &loc) {
    // The state tracker sets up the device state
    BaseClass::FinishDeviceSetup(pCreateInfo, loc);

    // Returns queues in the same order as advertised by the driver.
    // This allows to have deterministic QueueId between runs that simplifies debugging.
    auto get_sorted_queues = [this]() {
        std::vector<std::shared_ptr<vvl::Queue>> queues;
        device_state->ForEachShared<vvl::Queue>(
            [&queues](const std::shared_ptr<vvl::Queue> &queue) { queues.emplace_back(queue); });
        std::sort(queues.begin(), queues.end(), [](const auto &q1, const auto &q2) {
            return (q1->queue_family_index < q2->queue_family_index) ||
                   (q1->queue_family_index == q2->queue_family_index && q1->queue_index < q2->queue_index);
        });
        return queues;
    };
    queue_sync_states_.reserve(device_state->Count<vvl::Queue>());
    for (const auto &queue : get_sorted_queues()) {
        queue_sync_states_.emplace_back(std::make_shared<QueueSyncState>(queue, queue_id_limit_++));
    }

    const auto env_debug_command_number = GetEnvironment("VK_SYNCVAL_DEBUG_COMMAND_NUMBER");
    if (!env_debug_command_number.empty()) {
        debug_command_number = static_cast<uint32_t>(std::stoul(env_debug_command_number));
    }
    const auto env_debug_reset_count = GetEnvironment("VK_SYNCVAL_DEBUG_RESET_COUNT");
    if (!env_debug_reset_count.empty()) {
        debug_reset_count = static_cast<uint32_t>(std::stoul(env_debug_reset_count));
    }
    debug_cmdbuf_pattern = GetEnvironment("VK_SYNCVAL_DEBUG_CMDBUF_PATTERN");
    text::ToLower(debug_cmdbuf_pattern);
}

void SyncValidator::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator,
                                               const RecordObject &record_obj) {
    queue_sync_states_.clear();
    binary_signals_.clear();
    timeline_signals_.clear();
    waitable_fences_.clear();
    host_waitable_semaphores_.clear();
}

void SyncValidator::PostCallRecordCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
                                                  const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore,
                                                  const RecordObject &record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    assert(!vvl::Contains(timeline_signals_, *pSemaphore));
}

void SyncValidator::PreCallRecordDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator,
                                                  const RecordObject &record_obj) {
    if (auto sem_state = Get<vvl::Semaphore>(semaphore); sem_state && (sem_state->type == VK_SEMAPHORE_TYPE_TIMELINE)) {
        if (auto it = timeline_signals_.find(semaphore); it != timeline_signals_.end()) {
            stats.RemoveTimelineSignals((uint32_t)it->second.size());
            timeline_signals_.erase(it);
        }
    }
}

bool SyncValidator::ValidateBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
                                            const VkSubpassBeginInfo *pSubpassBeginInfo, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    if (cb_state) {
        SyncOpBeginRenderPass sync_op(error_obj.location.function, *this, pRenderPassBegin, pSubpassBeginInfo);
        skip |= sync_op.Validate(*GetAccessContext(*cb_state));
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
                                                      VkSubpassContents contents, const ErrorObject &error_obj) const {
    VkSubpassBeginInfo subpass_begin_info = vku::InitStructHelper();
    subpass_begin_info.contents = contents;
    return ValidateBeginRenderPass(commandBuffer, pRenderPassBegin, &subpass_begin_info, error_obj);
}

bool SyncValidator::PreCallValidateCmdBeginRenderPass2(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
                                                       const VkSubpassBeginInfo *pSubpassBeginInfo,
                                                       const ErrorObject &error_obj) const {
    return ValidateBeginRenderPass(commandBuffer, pRenderPassBegin, pSubpassBeginInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer,
                                                          const VkRenderPassBeginInfo *pRenderPassBegin,
                                                          const VkSubpassBeginInfo *pSubpassBeginInfo,
                                                          const ErrorObject &error_obj) const {
    return PreCallValidateCmdBeginRenderPass2(commandBuffer, pRenderPassBegin, pSubpassBeginInfo, error_obj);
}

bool SyncValidator::ValidateCmdNextSubpass(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo *pSubpassBeginInfo,
                                           const VkSubpassEndInfo *pSubpassEndInfo, const ErrorObject &error_obj) const {
    bool skip = false;

    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);
    SyncOpNextSubpass sync_op(error_obj.location.function, *this, pSubpassBeginInfo, pSubpassEndInfo);
    return sync_op.Validate(*cb_context);
}

bool SyncValidator::PreCallValidateCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents,
                                                  const ErrorObject &error_obj) const {
    // Convert to a NextSubpass2
    VkSubpassBeginInfo subpass_begin_info = vku::InitStructHelper();
    subpass_begin_info.contents = contents;
    VkSubpassEndInfo subpass_end_info = vku::InitStructHelper();
    return ValidateCmdNextSubpass(commandBuffer, &subpass_begin_info, &subpass_end_info, error_obj);
}

bool SyncValidator::PreCallValidateCmdNextSubpass2KHR(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo *pSubpassBeginInfo,
                                                      const VkSubpassEndInfo *pSubpassEndInfo, const ErrorObject &error_obj) const {
    return PreCallValidateCmdNextSubpass2(commandBuffer, pSubpassBeginInfo, pSubpassEndInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdNextSubpass2(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo *pSubpassBeginInfo,
                                                   const VkSubpassEndInfo *pSubpassEndInfo, const ErrorObject &error_obj) const {
    return ValidateCmdNextSubpass(commandBuffer, pSubpassBeginInfo, pSubpassEndInfo, error_obj);
}

bool SyncValidator::ValidateCmdEndRenderPass(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo,
                                             const ErrorObject &error_obj) const {
    bool skip = false;

    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    auto *cb_context = GetAccessContext(*cb_state);

    SyncOpEndRenderPass sync_op(error_obj.location.function, *this, pSubpassEndInfo);
    skip |= sync_op.Validate(*cb_context);
    return skip;
}

bool SyncValidator::PreCallValidateCmdEndRenderPass(VkCommandBuffer commandBuffer, const ErrorObject &error_obj) const {
    return ValidateCmdEndRenderPass(commandBuffer, nullptr, error_obj);
}

bool SyncValidator::PreCallValidateCmdEndRenderPass2(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo,
                                                     const ErrorObject &error_obj) const {
    return ValidateCmdEndRenderPass(commandBuffer, pSubpassEndInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo,
                                                        const ErrorObject &error_obj) const {
    return PreCallValidateCmdEndRenderPass2(commandBuffer, pSubpassEndInfo, error_obj);
}

// Simple heuristic rule to detect WAW operations representing algorithmically safe or increment
// updates to a resource which do not conflict at the byte level.
// TODO: Revisit this rule to see if it needs to be tighter or looser
// TODO: Add programatic control over suppression heuristics
bool SyncValidator::SuppressedBoundDescriptorWAW(const HazardResult &hazard) const {
    assert(hazard.IsHazard());
    return hazard.IsWAWHazard();
}

bool SyncValidator::PreCallValidateCmdBeginRenderingKHR(VkCommandBuffer commandBuffer, const VkRenderingInfoKHR *pRenderingInfo,
                                                        const ErrorObject &error_obj) const {
    return PreCallValidateCmdBeginRendering(commandBuffer, pRenderingInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdBeginRendering(VkCommandBuffer commandBuffer, const VkRenderingInfo *pRenderingInfo,
                                                     const ErrorObject &error_obj) const {
    bool skip = false;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state || !pRenderingInfo) return skip;

    vvl::TlsGuard<BeginRenderingCmdState> cmd_state(&skip, std::move(cb_state));
    cmd_state->AddRenderingInfo(*this, *pRenderingInfo);

    // We need to set skip, because the TlsGuard destructor is looking at the skip value for RAII cleanup.
    skip |= GetAccessContext(*cmd_state->cb_state)->ValidateBeginRendering(error_obj, *cmd_state);
    return skip;
}

void SyncValidator::PostCallRecordCmdBeginRenderingKHR(VkCommandBuffer commandBuffer, const VkRenderingInfoKHR *pRenderingInfo,
                                                       const RecordObject &record_obj) {
    PostCallRecordCmdBeginRendering(commandBuffer, pRenderingInfo, record_obj);
}

void SyncValidator::PostCallRecordCmdBeginRendering(VkCommandBuffer commandBuffer, const VkRenderingInfo *pRenderingInfo,
                                                    const RecordObject &record_obj) {
    vvl::TlsGuard<BeginRenderingCmdState> cmd_state;

    assert(cmd_state && cmd_state->cb_state && (cmd_state->cb_state->VkHandle() == commandBuffer));
    // Note: for fine grain locking need to to something other than cast.
    auto cb_state = std::const_pointer_cast<vvl::CommandBuffer>(cmd_state->cb_state);
    GetAccessContext(*cb_state)->RecordBeginRendering(*cmd_state, record_obj.location);
}

bool SyncValidator::PreCallValidateCmdEndRenderingKHR(VkCommandBuffer commandBuffer, const ErrorObject &error_obj) const {
    return PreCallValidateCmdEndRendering(commandBuffer, error_obj);
}

bool SyncValidator::PreCallValidateCmdEndRendering(VkCommandBuffer commandBuffer, const ErrorObject &error_obj) const {
    bool skip = false;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;

    skip |= GetAccessContext(*cb_state)->ValidateEndRendering(error_obj);
    return skip;
}

void SyncValidator::PreCallRecordCmdEndRenderingKHR(VkCommandBuffer commandBuffer, const RecordObject &record_obj) {
    PreCallRecordCmdEndRendering(commandBuffer, record_obj);
}

void SyncValidator::PreCallRecordCmdEndRendering(VkCommandBuffer commandBuffer, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;

    GetAccessContext(*cb_state)->RecordEndRendering(record_obj);
}

template <typename RegionType>
bool SyncValidator::ValidateCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
                                                 VkImageLayout dstImageLayout, uint32_t regionCount, const RegionType *pRegions,
                                                 const Location &loc) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto src_buffer = Get<vvl::Buffer>(srcBuffer);
    auto dst_image = Get<vvl::Image>(dstImage);

    for (const auto [region_index, copy_region] : vvl::enumerate(pRegions, regionCount)) {
        HazardResult hazard;
        if (dst_image) {
            if (src_buffer) {
                AccessRange src_range = MakeRange(copy_region.bufferOffset, dst_image->GetBufferSizeFromCopyImage(copy_region));
                hazard = context->DetectHazard(*src_buffer, SYNC_COPY_TRANSFER_READ, src_range);
                if (hazard.IsHazard()) {
                    // PHASE1 TODO -- add tag information to log msg when useful.
                    const LogObjectList objlist(commandBuffer, srcBuffer);
                    const std::string error = error_messages_.BufferCopyError(hazard, *cb_access_context, loc.function,
                                                                              FormatHandle(srcBuffer), region_index, src_range);
                    skip |= SyncError(hazard.Hazard(), objlist, loc, error);
                }
            }

            hazard = context->DetectHazard(*dst_image, RangeFromLayers(copy_region.imageSubresource), copy_region.imageOffset,
                                           copy_region.imageExtent, SYNC_COPY_TRANSFER_WRITE);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, dstImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, loc.function, FormatHandle(dstImage), region_index, copy_region.imageOffset,
                    copy_region.imageExtent, copy_region.imageSubresource);
                skip |= SyncError(hazard.Hazard(), objlist, loc, error);
            }
            if (skip) break;
        }
        if (skip) break;
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
                                                        VkImageLayout dstImageLayout, uint32_t regionCount,
                                                        const VkBufferImageCopy *pRegions, const ErrorObject &error_obj) const {
    return ValidateCmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions,
                                        error_obj.location);
}

bool SyncValidator::PreCallValidateCmdCopyBufferToImage2KHR(VkCommandBuffer commandBuffer,
                                                            const VkCopyBufferToImageInfo2KHR *pCopyBufferToImageInfo,
                                                            const ErrorObject &error_obj) const {
    return PreCallValidateCmdCopyBufferToImage2(commandBuffer, pCopyBufferToImageInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdCopyBufferToImage2(VkCommandBuffer commandBuffer,
                                                         const VkCopyBufferToImageInfo2 *pCopyBufferToImageInfo,
                                                         const ErrorObject &error_obj) const {
    return ValidateCmdCopyBufferToImage(commandBuffer, pCopyBufferToImageInfo->srcBuffer, pCopyBufferToImageInfo->dstImage,
                                        pCopyBufferToImageInfo->dstImageLayout, pCopyBufferToImageInfo->regionCount,
                                        pCopyBufferToImageInfo->pRegions, error_obj.location.dot(Field::pCopyBufferToImageInfo));
}

template <typename RegionType>
bool SyncValidator::ValidateCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
                                                 VkBuffer dstBuffer, uint32_t regionCount, const RegionType *pRegions,
                                                 const Location &loc) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto src_image = Get<vvl::Image>(srcImage);
    auto dst_buffer = Get<vvl::Buffer>(dstBuffer);
    const VkDeviceMemory dst_memory = (dst_buffer && !dst_buffer->sparse) ? dst_buffer->MemoryState()->VkHandle() : VK_NULL_HANDLE;
    for (const auto [region_index, copy_region] : vvl::enumerate(pRegions, regionCount)) {
        if (src_image) {
            auto hazard = context->DetectHazard(*src_image, RangeFromLayers(copy_region.imageSubresource), copy_region.imageOffset,
                                                copy_region.imageExtent, SYNC_COPY_TRANSFER_READ);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, srcImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, loc.function, FormatHandle(srcImage), region_index, copy_region.imageOffset,
                    copy_region.imageExtent, copy_region.imageSubresource);
                skip |= SyncError(hazard.Hazard(), objlist, loc, error);
            }
            if (dst_memory != VK_NULL_HANDLE) {
                AccessRange dst_range = MakeRange(copy_region.bufferOffset, src_image->GetBufferSizeFromCopyImage(copy_region));
                hazard = context->DetectHazard(*dst_buffer, SYNC_COPY_TRANSFER_WRITE, dst_range);
                if (hazard.IsHazard()) {
                    const LogObjectList objlist(commandBuffer, dstBuffer);
                    const std::string error = error_messages_.BufferCopyError(hazard, *cb_access_context, loc.function,
                                                                              FormatHandle(dstBuffer), region_index, dst_range);
                    skip |= SyncError(hazard.Hazard(), objlist, loc, error);
                }
            }
        }
        if (skip) break;
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
                                                        VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount,
                                                        const VkBufferImageCopy *pRegions, const ErrorObject &error_obj) const {
    return ValidateCmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions,
                                        error_obj.location);
}

bool SyncValidator::PreCallValidateCmdCopyImageToBuffer2KHR(VkCommandBuffer commandBuffer,
                                                            const VkCopyImageToBufferInfo2KHR *pCopyImageToBufferInfo,
                                                            const ErrorObject &error_obj) const {
    return PreCallValidateCmdCopyImageToBuffer2(commandBuffer, pCopyImageToBufferInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdCopyImageToBuffer2(VkCommandBuffer commandBuffer,
                                                         const VkCopyImageToBufferInfo2 *pCopyImageToBufferInfo,
                                                         const ErrorObject &error_obj) const {
    return ValidateCmdCopyImageToBuffer(commandBuffer, pCopyImageToBufferInfo->srcImage, pCopyImageToBufferInfo->srcImageLayout,
                                        pCopyImageToBufferInfo->dstBuffer, pCopyImageToBufferInfo->regionCount,
                                        pCopyImageToBufferInfo->pRegions, error_obj.location.dot(Field::pCopyImageToBufferInfo));
}

template <typename RegionType>
bool SyncValidator::ValidateCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
                                         VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
                                         const RegionType *pRegions, VkFilter filter, const Location &loc) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto src_image = Get<vvl::Image>(srcImage);
    auto dst_image = Get<vvl::Image>(dstImage);

    for (const auto [region_index, blit_region] : vvl::enumerate(pRegions, regionCount)) {
        if (src_image) {
            VkOffset3D offset = {std::min(blit_region.srcOffsets[0].x, blit_region.srcOffsets[1].x),
                                 std::min(blit_region.srcOffsets[0].y, blit_region.srcOffsets[1].y),
                                 std::min(blit_region.srcOffsets[0].z, blit_region.srcOffsets[1].z)};
            VkExtent3D extent = {static_cast<uint32_t>(abs(blit_region.srcOffsets[1].x - blit_region.srcOffsets[0].x)),
                                 static_cast<uint32_t>(abs(blit_region.srcOffsets[1].y - blit_region.srcOffsets[0].y)),
                                 static_cast<uint32_t>(abs(blit_region.srcOffsets[1].z - blit_region.srcOffsets[0].z))};
            auto hazard = context->DetectHazard(*src_image, RangeFromLayers(blit_region.srcSubresource), offset, extent,
                                                SYNC_BLIT_TRANSFER_READ);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, srcImage);
                const std::string error =
                    error_messages_.ImageCopyResolveBlitError(hazard, *cb_access_context, loc.function, FormatHandle(srcImage),
                                                              region_index, offset, extent, blit_region.srcSubresource);
                skip |= SyncError(hazard.Hazard(), objlist, loc, error);
            }
        }

        if (dst_image) {
            VkOffset3D offset = {std::min(blit_region.dstOffsets[0].x, blit_region.dstOffsets[1].x),
                                 std::min(blit_region.dstOffsets[0].y, blit_region.dstOffsets[1].y),
                                 std::min(blit_region.dstOffsets[0].z, blit_region.dstOffsets[1].z)};
            VkExtent3D extent = {static_cast<uint32_t>(abs(blit_region.dstOffsets[1].x - blit_region.dstOffsets[0].x)),
                                 static_cast<uint32_t>(abs(blit_region.dstOffsets[1].y - blit_region.dstOffsets[0].y)),
                                 static_cast<uint32_t>(abs(blit_region.dstOffsets[1].z - blit_region.dstOffsets[0].z))};
            auto hazard = context->DetectHazard(*dst_image, RangeFromLayers(blit_region.dstSubresource), offset, extent,
                                                SYNC_BLIT_TRANSFER_WRITE);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, dstImage);
                const std::string error =
                    error_messages_.ImageCopyResolveBlitError(hazard, *cb_access_context, loc.function, FormatHandle(dstImage),
                                                              region_index, offset, extent, blit_region.dstSubresource);
                skip |= SyncError(hazard.Hazard(), objlist, loc, error);
            }
            if (skip) break;
        }
    }

    return skip;
}

bool SyncValidator::PreCallValidateCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
                                                VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
                                                const VkImageBlit *pRegions, VkFilter filter, const ErrorObject &error_obj) const {
    return ValidateCmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter,
                                error_obj.location);
}

bool SyncValidator::PreCallValidateCmdBlitImage2KHR(VkCommandBuffer commandBuffer, const VkBlitImageInfo2KHR *pBlitImageInfo,
                                                    const ErrorObject &error_obj) const {
    return PreCallValidateCmdBlitImage2(commandBuffer, pBlitImageInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdBlitImage2(VkCommandBuffer commandBuffer, const VkBlitImageInfo2 *pBlitImageInfo,
                                                 const ErrorObject &error_obj) const {
    return ValidateCmdBlitImage(commandBuffer, pBlitImageInfo->srcImage, pBlitImageInfo->srcImageLayout, pBlitImageInfo->dstImage,
                                pBlitImageInfo->dstImageLayout, pBlitImageInfo->regionCount, pBlitImageInfo->pRegions,
                                pBlitImageInfo->filter, error_obj.location.dot(Field::pBlitImageInfo));
}

bool SyncValidator::ValidateIndirectBuffer(const CommandBufferAccessContext &cb_context, const AccessContext &context,
                                           const VkDeviceSize struct_size, const VkBuffer buffer, const VkDeviceSize offset,
                                           const uint32_t drawCount, const uint32_t stride, const Location &loc) const {
    bool skip = false;
    if (drawCount == 0) return skip;

    auto buf_state = Get<vvl::Buffer>(buffer);
    VkDeviceSize size = struct_size;
    if (drawCount == 1 || stride == size) {
        if (drawCount > 1) size *= drawCount;
        const AccessRange range = MakeRange(offset, size);
        auto hazard = context.DetectHazard(*buf_state, SYNC_DRAW_INDIRECT_INDIRECT_COMMAND_READ, range);
        if (hazard.IsHazard()) {
            const LogObjectList objlist(cb_context.GetCBState().Handle(), buf_state->Handle());
            const std::string resource_description = "indirect " + FormatHandle(buffer);
            const auto error = error_messages_.BufferError(hazard, cb_context, loc.function, resource_description, range);
            skip |= SyncError(hazard.Hazard(), objlist, loc, error);
        }
    } else {
        for (uint32_t i = 0; i < drawCount; ++i) {
            const AccessRange range = MakeRange(offset + i * stride, size);
            auto hazard = context.DetectHazard(*buf_state, SYNC_DRAW_INDIRECT_INDIRECT_COMMAND_READ, range);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(cb_context.GetCBState().Handle(), buf_state->Handle());
                const std::string resource_description = "indirect " + FormatHandle(buffer);
                const auto error = error_messages_.BufferError(hazard, cb_context, loc.function, resource_description, range);
                skip |= SyncError(hazard.Hazard(), objlist, loc, error);
                break;
            }
        }
    }
    return skip;
}

void SyncValidator::RecordIndirectBuffer(CommandBufferAccessContext &cb_context, const ResourceUsageTag tag,
                                         const VkDeviceSize struct_size, const VkBuffer buffer, const VkDeviceSize offset,
                                         const uint32_t drawCount, uint32_t stride) {
    auto buf_state = Get<vvl::Buffer>(buffer);
    auto tag_ex = buf_state ? cb_context.AddCommandHandle(tag, buf_state->Handle()) : ResourceUsageTagEx{tag};

    VkDeviceSize size = struct_size;
    AccessContext &context = *cb_context.GetCurrentAccessContext();
    if (drawCount == 1 || stride == size) {
        if (drawCount > 1) size *= drawCount;
        const AccessRange range = MakeRange(offset, size);
        context.UpdateAccessState(*buf_state, SYNC_DRAW_INDIRECT_INDIRECT_COMMAND_READ, range, tag_ex);
    } else {
        for (uint32_t i = 0; i < drawCount; ++i) {
            const AccessRange range = MakeRange(offset + i * stride, size);
            context.UpdateAccessState(*buf_state, SYNC_DRAW_INDIRECT_INDIRECT_COMMAND_READ, range, tag_ex);
        }
    }
}

bool SyncValidator::ValidateCountBuffer(const CommandBufferAccessContext &cb_context, const AccessContext &context, VkBuffer buffer,
                                        VkDeviceSize offset, const Location &loc) const {
    bool skip = false;

    auto count_buf_state = Get<vvl::Buffer>(buffer);
    const AccessRange range = MakeRange(offset, 4);
    auto hazard = context.DetectHazard(*count_buf_state, SYNC_DRAW_INDIRECT_INDIRECT_COMMAND_READ, range);
    if (hazard.IsHazard()) {
        const LogObjectList objlist(cb_context.GetCBState().Handle(), count_buf_state->Handle());
        const std::string resource_description = "draw count " + FormatHandle(buffer);
        const auto error = error_messages_.BufferError(hazard, cb_context, loc.function, resource_description, range);
        skip |= SyncError(hazard.Hazard(), objlist, loc, error);
    }
    return skip;
}

void SyncValidator::RecordCountBuffer(CommandBufferAccessContext &cb_context, const ResourceUsageTag tag, VkBuffer buffer,
                                      VkDeviceSize offset) {
    auto count_buf_state = Get<vvl::Buffer>(buffer);
    const AccessRange range = MakeRange(offset, 4);
    const ResourceUsageTagEx tag_ex = cb_context.AddCommandHandle(tag, count_buf_state->Handle());
    AccessContext &context = *cb_context.GetCurrentAccessContext();
    context.UpdateAccessState(*count_buf_state, SYNC_DRAW_INDIRECT_INDIRECT_COMMAND_READ, range, tag_ex);
}

bool SyncValidator::PreCallValidateCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z,
                                               const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    skip |= GetAccessContext(*cb_state)->ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE,
                                                                                       error_obj.location);
    return skip;
}

void SyncValidator::PostCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z,
                                              const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(record_obj.location.function);

    cb_access_context->RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, tag);
}

bool SyncValidator::PreCallValidateCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                       const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);

    const auto *context = cb_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    skip |= cb_context->ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, error_obj.location);
    skip |= ValidateIndirectBuffer(*cb_context, *context, sizeof(VkDispatchIndirectCommand), buffer, offset, 1,
                                   sizeof(VkDispatchIndirectCommand), error_obj.location);
    return skip;
}

void SyncValidator::PostCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                      const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(record_obj.location.function);

    cb_access_context->RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, tag);
    RecordIndirectBuffer(*cb_access_context, tag, sizeof(VkDispatchIndirectCommand), buffer, offset, 1,
                         sizeof(VkDispatchIndirectCommand));
}

bool SyncValidator::PreCallValidateCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
                                                   uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
                                                   uint32_t groupCountZ, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    skip |= GetAccessContext(*cb_state)->ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, error_obj.location);
    return skip;
}

bool SyncValidator::PreCallValidateCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
                                                      uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
                                                      uint32_t groupCountZ, const ErrorObject &error_obj) const {
    return PreCallValidateCmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ,
                                          error_obj);
}

void SyncValidator::PostCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
                                                  uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
                                                  uint32_t groupCountZ, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN(cb_state);
    auto cb_access_context = GetAccessContext(*cb_state);
    const ResourceUsageTag tag = cb_access_context->NextCommandTag(record_obj.location.function);
    cb_access_context->RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, tag);
}

void SyncValidator::PostCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY,
                                                     uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY,
                                                     uint32_t groupCountZ, const RecordObject &record_obj) {
    PostCallRecordCmdDispatchBase(commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ,
                                  record_obj);
}

bool SyncValidator::PreCallValidateCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
                                           uint32_t firstVertex, uint32_t firstInstance, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    skip |= cb_access_context->ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, error_obj.location);
    skip |= cb_access_context->ValidateDrawVertex(vertexCount, firstVertex, error_obj.location);
    skip |= cb_access_context->ValidateDrawAttachment(error_obj.location);
    return skip;
}

void SyncValidator::PostCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
                                          uint32_t firstVertex, uint32_t firstInstance, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(record_obj.location.function);

    cb_access_context->RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, tag);
    cb_access_context->RecordDrawVertex(vertexCount, firstVertex, tag);
    cb_access_context->RecordDrawAttachment(tag);
}

bool SyncValidator::PreCallValidateCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
                                                  uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance,
                                                  const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    skip |= cb_access_context->ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, error_obj.location);
    skip |= cb_access_context->ValidateDrawVertexIndex(indexCount, firstIndex, error_obj.location);
    skip |= cb_access_context->ValidateDrawAttachment(error_obj.location);
    return skip;
}

void SyncValidator::PostCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
                                                 uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance,
                                                 const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(record_obj.location.function);

    cb_access_context->RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, tag);
    cb_access_context->RecordDrawVertexIndex(indexCount, firstIndex, tag);
    cb_access_context->RecordDrawAttachment(tag);
}

bool SyncValidator::PreCallValidateCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                   uint32_t drawCount, uint32_t stride, const ErrorObject &error_obj) const {
    bool skip = false;
    if (drawCount == 0) return skip;

    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    skip |= cb_access_context->ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, error_obj.location);
    skip |= cb_access_context->ValidateDrawAttachment(error_obj.location);
    skip |= ValidateIndirectBuffer(*cb_access_context, *context, sizeof(VkDrawIndirectCommand), buffer, offset, drawCount, stride,
                                   error_obj.location);
    // TODO: Shader instrumentation support is needed to read indirect buffer content (new syncval mode)
    // skip |= cb_access_context->ValidateDrawVertex(?, ?, error_obj.location);
    return skip;
}

void SyncValidator::PostCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                  uint32_t drawCount, uint32_t stride, const RecordObject &record_obj) {
    if (drawCount == 0) return;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(record_obj.location.function);

    cb_access_context->RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, tag);
    cb_access_context->RecordDrawAttachment(tag);
    RecordIndirectBuffer(*cb_access_context, tag, sizeof(VkDrawIndirectCommand), buffer, offset, drawCount, stride);

    // TODO: Shader instrumentation support is needed to read indirect buffer content (new syncval mode)
    // cb_access_context->RecordDrawVertex(?, ?, tag);
}

bool SyncValidator::PreCallValidateCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                          uint32_t drawCount, uint32_t stride, const ErrorObject &error_obj) const {
    bool skip = false;
    if (drawCount == 0) return skip;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    skip |= cb_access_context->ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, error_obj.location);
    skip |= cb_access_context->ValidateDrawAttachment(error_obj.location);
    skip |= ValidateIndirectBuffer(*cb_access_context, *context, sizeof(VkDrawIndexedIndirectCommand), buffer, offset, drawCount,
                                   stride, error_obj.location);

    // TODO: Shader instrumentation support is needed to read indirect buffer content (new syncval mode)
    // skip |= cb_access_context->ValidateDrawVertexIndex(?, ?, error_obj.location);
    return skip;
}

void SyncValidator::PostCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                         uint32_t drawCount, uint32_t stride, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(record_obj.location.function);

    cb_access_context->RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, tag);
    cb_access_context->RecordDrawAttachment(tag);
    RecordIndirectBuffer(*cb_access_context, tag, sizeof(VkDrawIndexedIndirectCommand), buffer, offset, drawCount, stride);

    // TODO: Shader instrumentation support is needed to read indirect buffer content (new syncval mode)
    // cb_access_context->RecordDrawVertexIndex(?, ?, tag);
}

bool SyncValidator::PreCallValidateCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                        VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                                        uint32_t stride, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    skip |= cb_access_context->ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, error_obj.location);
    skip |= cb_access_context->ValidateDrawAttachment(error_obj.location);
    skip |= ValidateIndirectBuffer(*cb_access_context, *context, sizeof(VkDrawIndirectCommand), buffer, offset, maxDrawCount,
                                   stride, error_obj.location);
    skip |= ValidateCountBuffer(*cb_access_context, *context, countBuffer, countBufferOffset, error_obj.location);

    // TODO: Shader instrumentation support is needed to read indirect buffer content (new syncval mode)
    // skip |= cb_access_context->ValidateDrawVertex(?, ?, error_obj.location);
    return skip;
}

void SyncValidator::RecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                               VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                               uint32_t stride, Func command) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(command);

    cb_access_context->RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, tag);
    cb_access_context->RecordDrawAttachment(tag);
    RecordIndirectBuffer(*cb_access_context, tag, sizeof(VkDrawIndirectCommand), buffer, offset, 1, stride);
    RecordCountBuffer(*cb_access_context, tag, countBuffer, countBufferOffset);

    // TODO: Shader instrumentation support is needed to read indirect buffer content (new syncval mode)
    // cb_access_context->RecordDrawVertex(?, ?, tag);
}

void SyncValidator::PostCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                       VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                                       uint32_t stride, const RecordObject &record_obj) {
    RecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride,
                               record_obj.location.function);
}
bool SyncValidator::PreCallValidateCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                           VkBuffer countBuffer, VkDeviceSize countBufferOffset,
                                                           uint32_t maxDrawCount, uint32_t stride,
                                                           const ErrorObject &error_obj) const {
    return PreCallValidateCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride,
                                               error_obj);
}

void SyncValidator::PostCallRecordCmdDrawIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                          VkBuffer countBuffer, VkDeviceSize countBufferOffset,
                                                          uint32_t maxDrawCount, uint32_t stride, const RecordObject &record_obj) {
    PostCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride,
                                       record_obj);
}

bool SyncValidator::PreCallValidateCmdDrawIndirectCountAMD(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                           VkBuffer countBuffer, VkDeviceSize countBufferOffset,
                                                           uint32_t maxDrawCount, uint32_t stride,
                                                           const ErrorObject &error_obj) const {
    return PreCallValidateCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride,
                                               error_obj);
}

void SyncValidator::PostCallRecordCmdDrawIndirectCountAMD(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                          VkBuffer countBuffer, VkDeviceSize countBufferOffset,
                                                          uint32_t maxDrawCount, uint32_t stride, const RecordObject &record_obj) {
    PostCallRecordCmdDrawIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride,
                                       record_obj);
}

bool SyncValidator::PreCallValidateCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                               VkBuffer countBuffer, VkDeviceSize countBufferOffset,
                                                               uint32_t maxDrawCount, uint32_t stride,
                                                               const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    skip |= cb_access_context->ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, error_obj.location);
    skip |= cb_access_context->ValidateDrawAttachment(error_obj.location);
    skip |= ValidateIndirectBuffer(*cb_access_context, *context, sizeof(VkDrawIndexedIndirectCommand), buffer, offset, maxDrawCount,
                                   stride, error_obj.location);
    skip |= ValidateCountBuffer(*cb_access_context, *context, countBuffer, countBufferOffset, error_obj.location);

    // TODO: Shader instrumentation support is needed to read indirect buffer content (new syncval mode)
    // skip |= cb_access_context->ValidateDrawVertexIndex(?, ?, error_obj.location);
    return skip;
}

void SyncValidator::RecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                      VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                                      uint32_t stride, Func command) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(command);

    cb_access_context->RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, tag);
    cb_access_context->RecordDrawAttachment(tag);
    RecordIndirectBuffer(*cb_access_context, tag, sizeof(VkDrawIndexedIndirectCommand), buffer, offset, 1, stride);
    RecordCountBuffer(*cb_access_context, tag, countBuffer, countBufferOffset);

    // TODO: Shader instrumentation support is needed to read indirect buffer content (new syncval mode)
    // cb_access_context->RecordDrawVertexIndex(?, ?, tag);
}

void SyncValidator::PostCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                              VkBuffer countBuffer, VkDeviceSize countBufferOffset,
                                                              uint32_t maxDrawCount, uint32_t stride,
                                                              const RecordObject &record_obj) {
    RecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride,
                                      record_obj.location.function);
}

bool SyncValidator::PreCallValidateCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                                                  VkDeviceSize offset, VkBuffer countBuffer,
                                                                  VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                                                  uint32_t stride, const ErrorObject &error_obj) const {
    return PreCallValidateCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount,
                                                      stride, error_obj);
}

void SyncValidator::PostCallRecordCmdDrawIndexedIndirectCountKHR(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                                                 VkDeviceSize offset, VkBuffer countBuffer,
                                                                 VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                                                 uint32_t stride, const RecordObject &record_obj) {
    PostCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride,
                                              record_obj);
}

bool SyncValidator::PreCallValidateCmdDrawIndexedIndirectCountAMD(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                                                  VkDeviceSize offset, VkBuffer countBuffer,
                                                                  VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                                                  uint32_t stride, const ErrorObject &error_obj) const {
    return PreCallValidateCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount,
                                                      stride, error_obj);
}

void SyncValidator::PostCallRecordCmdDrawIndexedIndirectCountAMD(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                                                 VkDeviceSize offset, VkBuffer countBuffer,
                                                                 VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                                                 uint32_t stride, const RecordObject &record_obj) {
    PostCallRecordCmdDrawIndexedIndirectCount(commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride,
                                              record_obj);
}

bool SyncValidator::PreCallValidateCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
                                                      const VkClearColorValue *pColor, uint32_t rangeCount,
                                                      const VkImageSubresourceRange *pRanges, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    if (auto image_state = Get<vvl::Image>(image)) {
        for (const auto [range_index, range] : vvl::enumerate(pRanges, rangeCount)) {
            auto hazard = context->DetectHazard(*image_state, range, SYNC_CLEAR_TRANSFER_WRITE);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, image);
                const auto error = error_messages_.ImageClearError(hazard, *cb_access_context, error_obj.location.function,
                                                                   FormatHandle(image), range_index, range);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image,
                                                             VkImageLayout imageLayout,
                                                             const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
                                                             const VkImageSubresourceRange *pRanges,
                                                             const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    if (auto image_state = Get<vvl::Image>(image)) {
        for (const auto [range_index, range] : vvl::enumerate(pRanges, rangeCount)) {
            auto hazard = context->DetectHazard(*image_state, range, SYNC_CLEAR_TRANSFER_WRITE);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, image);
                const auto error = error_messages_.ImageClearError(hazard, *cb_access_context, error_obj.location.function,
                                                                   FormatHandle(image), range_index, range);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
                                                       const VkClearAttachment *pAttachments, uint32_t rectCount,
                                                       const VkClearRect *pRects, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);

    for (const VkClearAttachment &attachment : vvl::make_span(pAttachments, attachmentCount)) {
        for (const auto [rect_index, rect] : vvl::enumerate(pRects, rectCount)) {
            skip |= GetAccessContext(*cb_state)->ValidateClearAttachment(error_obj.location, attachment, rect_index, rect);
        }
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
                                                           uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer,
                                                           VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags,
                                                           const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto dst_buffer = Get<vvl::Buffer>(dstBuffer);

    if (dst_buffer && queryCount > 0) {
        const uint32_t query_size = (flags & VK_QUERY_RESULT_64_BIT) ? 8 : 4;
        const VkDeviceSize range_size = (queryCount - 1) * stride + query_size;
        const AccessRange range = MakeRange(dstOffset, range_size);
        auto hazard = context->DetectHazard(*dst_buffer, SYNC_COPY_TRANSFER_WRITE, range);
        if (hazard.IsHazard()) {
            const LogObjectList objlist(commandBuffer, queryPool, dstBuffer);
            const std::string resource_description = "dstBuffer " + FormatHandle(dstBuffer);
            const auto error =
                error_messages_.BufferError(hazard, *cb_access_context, error_obj.location.function, resource_description, range);
            skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
        }
    }

    // TODO:Track VkQueryPool
    return skip;
}

bool SyncValidator::PreCallValidateCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
                                                 VkDeviceSize size, uint32_t data, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto dst_buffer = Get<vvl::Buffer>(dstBuffer);

    if (dst_buffer) {
        const AccessRange range = MakeRange(*dst_buffer, dstOffset, size);
        auto hazard = context->DetectHazard(*dst_buffer, SYNC_CLEAR_TRANSFER_WRITE, range);
        if (hazard.IsHazard()) {
            const LogObjectList objlist(commandBuffer, dstBuffer);
            const std::string resource_description = "dstBuffer " + FormatHandle(dstBuffer);
            const auto error =
                error_messages_.BufferError(hazard, *cb_access_context, error_obj.location.function, resource_description, range);
            skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
        }
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
                                                   VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
                                                   const VkImageResolve *pRegions, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto src_image = Get<vvl::Image>(srcImage);
    auto dst_image = Get<vvl::Image>(dstImage);

    for (const auto [region_index, resolve_region] : vvl::enumerate(pRegions, regionCount)) {
        if (src_image) {
            auto hazard = context->DetectHazard(*src_image, RangeFromLayers(resolve_region.srcSubresource),
                                                resolve_region.srcOffset, resolve_region.extent, SYNC_RESOLVE_TRANSFER_READ);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, srcImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, error_obj.location.function, FormatHandle(srcImage), region_index,
                    resolve_region.srcOffset, resolve_region.extent, resolve_region.srcSubresource);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }

        if (dst_image) {
            auto hazard = context->DetectHazard(*dst_image, RangeFromLayers(resolve_region.dstSubresource),
                                                resolve_region.dstOffset, resolve_region.extent, SYNC_RESOLVE_TRANSFER_WRITE);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, dstImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, error_obj.location.function, FormatHandle(dstImage), region_index,
                    resolve_region.dstOffset, resolve_region.extent, resolve_region.dstSubresource);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
            if (skip) break;
        }
    }

    return skip;
}

bool SyncValidator::PreCallValidateCmdResolveImage2(VkCommandBuffer commandBuffer, const VkResolveImageInfo2 *pResolveImageInfo,
                                                    const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    const Location image_info_loc = error_obj.location.dot(Field::pResolveImageInfo);
    auto src_image = Get<vvl::Image>(pResolveImageInfo->srcImage);
    auto dst_image = Get<vvl::Image>(pResolveImageInfo->dstImage);

    for (const auto [region_index, resolve_region] : vvl::enumerate(pResolveImageInfo->pRegions, pResolveImageInfo->regionCount)) {
        const Location region_loc = image_info_loc.dot(Field::pRegions, region_index);
        if (src_image) {
            auto hazard = context->DetectHazard(*src_image, RangeFromLayers(resolve_region.srcSubresource),
                                                resolve_region.srcOffset, resolve_region.extent, SYNC_RESOLVE_TRANSFER_READ);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, pResolveImageInfo->srcImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, error_obj.location.function, FormatHandle(pResolveImageInfo->srcImage),
                    region_index, resolve_region.srcOffset, resolve_region.extent, resolve_region.srcSubresource);
                // TODO: this error is not covered by the test
                skip |= SyncError(hazard.Hazard(), objlist, region_loc, error);
            }
        }

        if (dst_image) {
            auto hazard = context->DetectHazard(*dst_image, RangeFromLayers(resolve_region.dstSubresource),
                                                resolve_region.dstOffset, resolve_region.extent, SYNC_RESOLVE_TRANSFER_WRITE);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, pResolveImageInfo->dstImage);
                const std::string error = error_messages_.ImageCopyResolveBlitError(
                    hazard, *cb_access_context, error_obj.location.function, FormatHandle(pResolveImageInfo->dstImage),
                    region_index, resolve_region.dstOffset, resolve_region.extent, resolve_region.dstSubresource);
                // TODO: this error is not covered by the test
                skip |= SyncError(hazard.Hazard(), objlist, region_loc, error);
            }
            if (skip) break;
        }
    }

    return skip;
}

bool SyncValidator::PreCallValidateCmdResolveImage2KHR(VkCommandBuffer commandBuffer,
                                                       const VkResolveImageInfo2KHR *pResolveImageInfo,
                                                       const ErrorObject &error_obj) const {
    return PreCallValidateCmdResolveImage2(commandBuffer, pResolveImageInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
                                                   VkDeviceSize dataSize, const void *pData, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto dst_buffer = Get<vvl::Buffer>(dstBuffer);

    if (dst_buffer) {
        // VK_WHOLE_SIZE not allowed
        const AccessRange range = MakeRange(dstOffset, dataSize);
        auto hazard = context->DetectHazard(*dst_buffer, SYNC_CLEAR_TRANSFER_WRITE, range);
        if (hazard.IsHazard()) {
            const LogObjectList objlist(commandBuffer, dstBuffer);
            const std::string resource_description = "dstBuffer " + FormatHandle(dstBuffer);
            const auto error =
                error_messages_.BufferError(hazard, *cb_access_context, error_obj.location.function, resource_description, range);
            skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
        }
    }
    return skip;
}

bool SyncValidator::PreCallValidateCmdWriteBufferMarkerAMD(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage,
                                                           VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker,
                                                           const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    const auto *cb_access_context = GetAccessContext(*cb_state);
    const AccessContext &context = *cb_access_context->GetCurrentAccessContext();

    if (auto dst_buffer = Get<vvl::Buffer>(dstBuffer)) {
        const AccessRange range = MakeRange(dstOffset, 4);
        auto hazard = context.DetectMarkerHazard(*dst_buffer, range);
        if (hazard.IsHazard()) {
            const std::string resource_description = "dstBuffer " + FormatHandle(dstBuffer);
            const auto error =
                error_messages_.BufferError(hazard, *cb_access_context, error_obj.location.function, resource_description, range);
            skip |= SyncError(hazard.Hazard(), dstBuffer, error_obj.location, error);
        }
    }
    return skip;
}

void SyncValidator::PostCallRecordCmdWriteBufferMarkerAMD(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage,
                                                          VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker,
                                                          const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN(cb_state);
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(record_obj.location.function);
    AccessContext &context = *cb_access_context->GetCurrentAccessContext();

    if (auto dst_buffer = Get<vvl::Buffer>(dstBuffer)) {
        const AccessRange range = MakeRange(dstOffset, 4);
        const ResourceUsageTagEx tag_ex = cb_access_context->AddCommandHandle(tag, dst_buffer->Handle());
        context.UpdateAccessState(*dst_buffer, SYNC_COPY_TRANSFER_WRITE, range, tag_ex, SyncFlag::kMarker);
    }
}

bool SyncValidator::PreCallValidateCmdDecodeVideoKHR(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR *pDecodeInfo,
                                                     const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    const auto vs_state = cb_state->bound_video_session.get();
    if (!vs_state) return skip;

    auto src_buffer = Get<vvl::Buffer>(pDecodeInfo->srcBuffer);
    if (src_buffer) {
        const AccessRange src_range = MakeRange(*src_buffer, pDecodeInfo->srcBufferOffset, pDecodeInfo->srcBufferRange);
        auto hazard = context->DetectHazard(*src_buffer, SYNC_VIDEO_DECODE_VIDEO_DECODE_READ, src_range);
        if (hazard.IsHazard()) {
            const std::string resource_description = "bitstream buffer " + FormatHandle(pDecodeInfo->srcBuffer);
            // TODO: there are no tests for this error
            const auto error = error_messages_.BufferError(hazard, *cb_access_context, error_obj.location.function,
                                                           resource_description, src_range);
            skip |= SyncError(hazard.Hazard(), src_buffer->Handle(), error_obj.location, error);
        }
    }

    auto dst_resource = vvl::VideoPictureResource(*device_state, pDecodeInfo->dstPictureResource);
    if (dst_resource) {
        auto hazard = context->DetectVideoHazard(*vs_state, dst_resource, SYNC_VIDEO_DECODE_VIDEO_DECODE_WRITE);
        if (hazard.IsHazard()) {
            std::ostringstream ss;
            ss << "decode output picture ";
            ss << Location(Func::Empty, Field::pDecodeInfo).dot(Field::dstPictureResource).Fields();
            ss << " ";
            FormatVideoPictureResouce(*this, pDecodeInfo->dstPictureResource, ss);
            const std::string resouce_description = ss.str();
            const std::string error =
                error_messages_.VideoError(hazard, *cb_access_context, error_obj.location.function, resouce_description);
            skip |= SyncError(hazard.Hazard(), dst_resource.image_view_state->Handle(), error_obj.location, error);
        }
    }

    if (pDecodeInfo->pSetupReferenceSlot != nullptr && pDecodeInfo->pSetupReferenceSlot->pPictureResource != nullptr) {
        const VkVideoPictureResourceInfoKHR &video_picture = *pDecodeInfo->pSetupReferenceSlot->pPictureResource;
        auto setup_resource = vvl::VideoPictureResource(*device_state, video_picture);
        if (setup_resource && (setup_resource != dst_resource)) {
            auto hazard = context->DetectVideoHazard(*vs_state, setup_resource, SYNC_VIDEO_DECODE_VIDEO_DECODE_WRITE);
            if (hazard.IsHazard()) {
                std::ostringstream ss;
                ss << "reconstructed picture ";
                ss << Location(Func::Empty, Field::pDecodeInfo)
                          .dot(Field::pSetupReferenceSlot)
                          .dot(Field::pPictureResource)
                          .Fields();
                ss << " ";
                FormatVideoPictureResouce(*this, video_picture, ss);
                const std::string resouce_description = ss.str();
                const std::string error =
                    error_messages_.VideoError(hazard, *cb_access_context, error_obj.location.function, resouce_description);
                skip |= SyncError(hazard.Hazard(), setup_resource.image_view_state->Handle(), error_obj.location, error);
            }
        }
    }

    for (uint32_t i = 0; i < pDecodeInfo->referenceSlotCount; ++i) {
        if (pDecodeInfo->pReferenceSlots[i].pPictureResource != nullptr) {
            const VkVideoPictureResourceInfoKHR &video_picture = *pDecodeInfo->pReferenceSlots[i].pPictureResource;
            auto reference_resource = vvl::VideoPictureResource(*device_state, video_picture);
            if (reference_resource) {
                auto hazard = context->DetectVideoHazard(*vs_state, reference_resource, SYNC_VIDEO_DECODE_VIDEO_DECODE_READ);
                if (hazard.IsHazard()) {
                    std::ostringstream ss;
                    ss << "reference picture " << i << " ";
                    ss << Location(Func::Empty, Field::pDecodeInfo)
                              .dot(Field::pReferenceSlots, i)
                              .dot(Field::pPictureResource)
                              .Fields();
                    ss << " ";
                    FormatVideoPictureResouce(*this, video_picture, ss);
                    const std::string resouce_description = ss.str();
                    const std::string error =
                        error_messages_.VideoError(hazard, *cb_access_context, error_obj.location.function, resouce_description);
                    skip |= SyncError(hazard.Hazard(), reference_resource.image_view_state->Handle(), error_obj.location, error);
                }
            }
        }
    }

    return skip;
}

bool SyncValidator::PreCallValidateCmdEncodeVideoKHR(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR *pEncodeInfo,
                                                     const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    const auto vs_state = cb_state->bound_video_session.get();
    if (!vs_state) return skip;

    auto dst_buffer = Get<vvl::Buffer>(pEncodeInfo->dstBuffer);
    if (dst_buffer) {
        const AccessRange dst_range = MakeRange(*dst_buffer, pEncodeInfo->dstBufferOffset, pEncodeInfo->dstBufferRange);
        auto hazard = context->DetectHazard(*dst_buffer, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_WRITE, dst_range);
        if (hazard.IsHazard()) {
            const std::string resource_description = "bitstream buffer " + FormatHandle(pEncodeInfo->dstBuffer);
            const auto error = error_messages_.BufferError(hazard, *cb_access_context, error_obj.location.function,
                                                           resource_description, dst_range);
            skip |= SyncError(hazard.Hazard(), dst_buffer->Handle(), error_obj.location, error);
        }
    }

    if (auto src_resource = vvl::VideoPictureResource(*device_state, pEncodeInfo->srcPictureResource)) {
        auto hazard = context->DetectVideoHazard(*vs_state, src_resource, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_READ);
        if (hazard.IsHazard()) {
            std::ostringstream ss;
            ss << "encode input picture ";
            ss << Location(Func::Empty, Field::pEncodeInfo).dot(Field::srcPictureResource).Fields();
            ss << " ";
            FormatVideoPictureResouce(*this, pEncodeInfo->srcPictureResource, ss);
            const std::string resouce_description = ss.str();
            // TODO: there are no tests for this error
            const std::string error =
                error_messages_.VideoError(hazard, *cb_access_context, error_obj.location.function, resouce_description);
            skip |= SyncError(hazard.Hazard(), src_resource.image_view_state->Handle(), error_obj.location, error);
        }
    }

    if (pEncodeInfo->pSetupReferenceSlot != nullptr && pEncodeInfo->pSetupReferenceSlot->pPictureResource != nullptr) {
        const VkVideoPictureResourceInfoKHR &video_picture = *pEncodeInfo->pSetupReferenceSlot->pPictureResource;
        auto setup_resource = vvl::VideoPictureResource(*device_state, video_picture);
        if (setup_resource) {
            auto hazard = context->DetectVideoHazard(*vs_state, setup_resource, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_WRITE);
            if (hazard.IsHazard()) {
                std::ostringstream ss;
                ss << "reconstructed picture ";
                ss << Location(Func::Empty, Field::pEncodeInfo)
                          .dot(Field::pSetupReferenceSlot)
                          .dot(Field::pPictureResource)
                          .Fields();
                ss << " ";
                FormatVideoPictureResouce(*this, video_picture, ss);
                const std::string resouce_description = ss.str();
                const std::string error =
                    error_messages_.VideoError(hazard, *cb_access_context, error_obj.location.function, resouce_description);
                skip |= SyncError(hazard.Hazard(), setup_resource.image_view_state->Handle(), error_obj.location, error);
            }
        }
    }

    for (uint32_t i = 0; i < pEncodeInfo->referenceSlotCount; ++i) {
        if (pEncodeInfo->pReferenceSlots[i].pPictureResource != nullptr) {
            const VkVideoPictureResourceInfoKHR &video_picture = *pEncodeInfo->pReferenceSlots[i].pPictureResource;
            auto reference_resource = vvl::VideoPictureResource(*device_state, video_picture);
            if (reference_resource) {
                auto hazard = context->DetectVideoHazard(*vs_state, reference_resource, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_READ);
                if (hazard.IsHazard()) {
                    std::ostringstream ss;
                    ss << "reference picture " << i << " ";
                    ss << Location(Func::Empty, Field::pEncodeInfo)
                              .dot(Field::pReferenceSlots, i)
                              .dot(Field::pPictureResource)
                              .Fields();
                    ss << " ";
                    FormatVideoPictureResouce(*this, video_picture, ss);
                    const std::string resource_description = ss.str();
                    const std::string error =
                        error_messages_.VideoError(hazard, *cb_access_context, error_obj.location.function, resource_description);
                    skip |= SyncError(hazard.Hazard(), reference_resource.image_view_state->Handle(), error_obj.location, error);
                }
            }
        }
    }

    if (pEncodeInfo->flags & (VK_VIDEO_ENCODE_WITH_QUANTIZATION_DELTA_MAP_BIT_KHR | VK_VIDEO_ENCODE_WITH_EMPHASIS_MAP_BIT_KHR)) {
        auto quantization_map_info = vku::FindStructInPNextChain<VkVideoEncodeQuantizationMapInfoKHR>(pEncodeInfo->pNext);
        if (quantization_map_info) {
            auto image_view_state = Get<vvl::ImageView>(quantization_map_info->quantizationMap);
            if (image_view_state) {
                VkOffset3D offset = {0, 0, 0};
                VkExtent3D extent = {quantization_map_info->quantizationMapExtent.width,
                                     quantization_map_info->quantizationMapExtent.height, 1};
                auto hazard = context->DetectHazard(*image_view_state, offset, extent, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_READ);
                if (hazard.IsHazard()) {
                    std::ostringstream ss;
                    ss << "quantization map ";
                    ss << Location(Func::Empty, Field::pEncodeInfo).dot(Field::quantizationMap).Fields();
                    ss << " ";
                    FormatVideoQuantizationMap(*this, *quantization_map_info, ss);
                    const std::string resource_description = ss.str();
                    const std::string error =
                        error_messages_.VideoError(hazard, *cb_access_context, error_obj.location.function, resource_description);
                    skip |= SyncError(hazard.Hazard(), image_view_state->Handle(), error_obj.location, error);
                }
            }
        }
    }

    return skip;
}

bool SyncValidator::PreCallValidateCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask,
                                               const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);
    const auto *access_context = cb_context->GetCurrentAccessContext();
    assert(access_context);
    if (!access_context) return skip;

    SyncOpSetEvent set_event_op(error_obj.location.function, *this, cb_context->GetQueueFlags(), event, stageMask, nullptr);
    return set_event_op.Validate(*cb_context);
}

void SyncValidator::PostCallRecordCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask,
                                              const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_context = GetAccessContext(*cb_state);

    cb_context->RecordSyncOp<SyncOpSetEvent>(record_obj.location.function, *this, cb_context->GetQueueFlags(), event, stageMask,
                                             cb_context->GetCurrentAccessContext());
}

bool SyncValidator::PreCallValidateCmdSetEvent2KHR(VkCommandBuffer commandBuffer, VkEvent event,
                                                   const VkDependencyInfoKHR *pDependencyInfo, const ErrorObject &error_obj) const {
    return PreCallValidateCmdSetEvent2(commandBuffer, event, pDependencyInfo, error_obj);
}

bool SyncValidator::PreCallValidateCmdSetEvent2(VkCommandBuffer commandBuffer, VkEvent event,
                                                const VkDependencyInfo *pDependencyInfo, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);
    if (!pDependencyInfo) return skip;

    const auto *access_context = cb_context->GetCurrentAccessContext();
    assert(access_context);
    if (!access_context) return skip;

    SyncOpSetEvent set_event_op(error_obj.location.function, *this, cb_context->GetQueueFlags(), event, *pDependencyInfo, nullptr);
    return set_event_op.Validate(*cb_context);
}

void SyncValidator::PostCallRecordCmdSetEvent2KHR(VkCommandBuffer commandBuffer, VkEvent event,
                                                  const VkDependencyInfoKHR *pDependencyInfo, const RecordObject &record_obj) {
    PostCallRecordCmdSetEvent2(commandBuffer, event, pDependencyInfo, record_obj);
}

void SyncValidator::PostCallRecordCmdSetEvent2(VkCommandBuffer commandBuffer, VkEvent event,
                                               const VkDependencyInfo *pDependencyInfo, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_context = GetAccessContext(*cb_state);
    if (!pDependencyInfo) return;

    cb_context->RecordSyncOp<SyncOpSetEvent>(record_obj.location.function, *this, cb_context->GetQueueFlags(), event,
                                             *pDependencyInfo, cb_context->GetCurrentAccessContext());
}

bool SyncValidator::PreCallValidateCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask,
                                                 const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);

    SyncOpResetEvent reset_event_op(error_obj.location.function, *this, cb_context->GetQueueFlags(), event, stageMask);
    return reset_event_op.Validate(*cb_context);
}

void SyncValidator::PostCallRecordCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask,
                                                const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_context = GetAccessContext(*cb_state);

    cb_context->RecordSyncOp<SyncOpResetEvent>(record_obj.location.function, *this, cb_context->GetQueueFlags(), event, stageMask);
}

bool SyncValidator::PreCallValidateCmdResetEvent2(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask,
                                                  const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);

    SyncOpResetEvent reset_event_op(error_obj.location.function, *this, cb_context->GetQueueFlags(), event, stageMask);
    return reset_event_op.Validate(*cb_context);
    return PreCallValidateCmdResetEvent2(commandBuffer, event, stageMask, error_obj);
}

bool SyncValidator::PreCallValidateCmdResetEvent2KHR(VkCommandBuffer commandBuffer, VkEvent event,
                                                     VkPipelineStageFlags2KHR stageMask, const ErrorObject &error_obj) const {
    return PreCallValidateCmdResetEvent2(commandBuffer, event, stageMask, error_obj);
}

void SyncValidator::PostCallRecordCmdResetEvent2KHR(VkCommandBuffer commandBuffer, VkEvent event,
                                                    VkPipelineStageFlags2KHR stageMask, const RecordObject &record_obj) {
    PostCallRecordCmdResetEvent2(commandBuffer, event, stageMask, record_obj);
}

void SyncValidator::PostCallRecordCmdResetEvent2(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask,
                                                 const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_context = GetAccessContext(*cb_state);

    cb_context->RecordSyncOp<SyncOpResetEvent>(record_obj.location.function, *this, cb_context->GetQueueFlags(), event, stageMask);
}

bool SyncValidator::PreCallValidateCmdWaitEvents(VkCommandBuffer commandBuffer, 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,
                                                 const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);

    SyncOpWaitEvents wait_events_op(error_obj.location.function, *this, cb_context->GetQueueFlags(), eventCount, pEvents,
                                    srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
                                    pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
    return wait_events_op.Validate(*cb_context);
}

void SyncValidator::PostCallRecordCmdWaitEvents(VkCommandBuffer commandBuffer, 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,
                                                const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_context = GetAccessContext(*cb_state);

    cb_context->RecordSyncOp<SyncOpWaitEvents>(record_obj.location.function, *this, cb_context->GetQueueFlags(), eventCount,
                                               pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers,
                                               bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount,
                                               pImageMemoryBarriers);
}

bool SyncValidator::PreCallValidateCmdWaitEvents2KHR(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
                                                     const VkDependencyInfoKHR *pDependencyInfos,
                                                     const ErrorObject &error_obj) const {
    return PreCallValidateCmdWaitEvents2(commandBuffer, eventCount, pEvents, pDependencyInfos, error_obj);
}

void SyncValidator::PostCallRecordCmdWaitEvents2KHR(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
                                                    const VkDependencyInfoKHR *pDependencyInfos, const RecordObject &record_obj) {
    PostCallRecordCmdWaitEvents2(commandBuffer, eventCount, pEvents, pDependencyInfos, record_obj);
}

bool SyncValidator::PreCallValidateCmdWaitEvents2(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
                                                  const VkDependencyInfo *pDependencyInfos, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);

    SyncOpWaitEvents wait_events_op(error_obj.location.function, *this, cb_context->GetQueueFlags(), eventCount, pEvents,
                                    pDependencyInfos);
    skip |= wait_events_op.Validate(*cb_context);
    return skip;
}

void SyncValidator::PostCallRecordCmdWaitEvents2(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents,
                                                 const VkDependencyInfo *pDependencyInfos, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_context = GetAccessContext(*cb_state);

    cb_context->RecordSyncOp<SyncOpWaitEvents>(record_obj.location.function, *this, cb_context->GetQueueFlags(), eventCount,
                                               pEvents, pDependencyInfos);
}

bool SyncValidator::PreCallValidateCmdWriteBufferMarker2AMD(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR pipelineStage,
                                                            VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker,
                                                            const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_access_context = GetAccessContext(*cb_state);

    const auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);
    if (!context) return skip;

    auto dst_buffer = Get<vvl::Buffer>(dstBuffer);

    if (dst_buffer) {
        const AccessRange range = MakeRange(dstOffset, 4);
        auto hazard = context->DetectHazard(*dst_buffer, SYNC_COPY_TRANSFER_WRITE, range);
        if (hazard.IsHazard()) {
            const std::string resource_description = "dstBuffer " + FormatHandle(dstBuffer);
            // TODO: there are no tests for this error
            const auto error =
                error_messages_.BufferError(hazard, *cb_access_context, error_obj.location.function, resource_description, range);
            skip |= SyncError(hazard.Hazard(), dstBuffer, error_obj.location, error);
        }
    }
    return skip;
}

void SyncValidator::PostCallRecordCmdWriteBufferMarker2AMD(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR pipelineStage,
                                                           VkBuffer dstBuffer, VkDeviceSize dstOffset, uint32_t marker,
                                                           const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return;
    auto *cb_access_context = GetAccessContext(*cb_state);
    const auto tag = cb_access_context->NextCommandTag(record_obj.location.function);
    auto *context = cb_access_context->GetCurrentAccessContext();
    assert(context);

    auto dst_buffer = Get<vvl::Buffer>(dstBuffer);

    if (dst_buffer) {
        const AccessRange range = MakeRange(dstOffset, 4);
        const ResourceUsageTagEx tag_ex = cb_access_context->AddCommandHandle(tag, dst_buffer->Handle());
        context->UpdateAccessState(*dst_buffer, SYNC_COPY_TRANSFER_WRITE, range, tag_ex);
    }
}

bool SyncValidator::PreCallValidateCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount,
                                                      const VkCommandBuffer *pCommandBuffers, const ErrorObject &error_obj) const {
    bool skip = false;
    const auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    assert(cb_state);
    if (!cb_state) return skip;
    const auto *cb_context = GetAccessContext(*cb_state);

    // Heavyweight, but we need a proxy copy of the active command buffer access context
    CommandBufferAccessContext proxy_cb_context(*cb_context, CommandBufferAccessContext::AsProxyContext());

    auto &proxy_label_commands = proxy_cb_context.GetProxyLabelCommands();
    proxy_label_commands = cb_state->GetLabelCommands();

    // Make working copies of the access and events contexts
    for (uint32_t cb_index = 0; cb_index < commandBufferCount; ++cb_index) {
        if (cb_index == 0) {
            proxy_cb_context.NextCommandTag(error_obj.location.function, ResourceUsageRecord::SubcommandType::kIndex);
        } else {
            proxy_cb_context.NextSubcommandTag(error_obj.location.function, ResourceUsageRecord::SubcommandType::kIndex);
        }

        const auto recorded_cb = Get<vvl::CommandBuffer>(pCommandBuffers[cb_index]);
        if (!recorded_cb) continue;
        const auto *recorded_cb_context = GetAccessContext(*recorded_cb);
        assert(recorded_cb_context);

        const ResourceUsageTag base_tag = proxy_cb_context.GetTagCount();
        skip |= ReplayState(proxy_cb_context, *recorded_cb_context, error_obj, cb_index, base_tag).ValidateFirstUse();

        // Update proxy label commands so they can be used by ImportRecordedAccessLog
        const auto &recorded_label_commands = recorded_cb->GetLabelCommands();
        proxy_label_commands.insert(proxy_label_commands.end(), recorded_label_commands.begin(), recorded_label_commands.end());

        // The barriers have already been applied in ValidatFirstUse
        proxy_cb_context.ImportRecordedAccessLog(*recorded_cb_context);
        proxy_cb_context.ResolveExecutedCommandBuffer(*recorded_cb_context->GetCurrentAccessContext(), base_tag);
    }
    proxy_label_commands.clear();

    return skip;
}

void SyncValidator::PostCallRecordBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset,
                                                  const RecordObject &record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    VkBindImageMemoryInfo bind_info = vku::InitStructHelper();
    bind_info.image = image;
    bind_info.memory = memory;
    bind_info.memoryOffset = memoryOffset;
    UpdateSyncImageMemoryBindState(1, &bind_info);
}

void SyncValidator::PostCallRecordBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo *pBindInfos,
                                                   const RecordObject &record_obj) {
    // Don't check |record_obj.result| as some binds might still be valid
    UpdateSyncImageMemoryBindState(bindInfoCount, pBindInfos);
}

void SyncValidator::PostCallRecordBindImageMemory2KHR(VkDevice device, uint32_t bindInfoCount,
                                                      const VkBindImageMemoryInfo *pBindInfos, const RecordObject &record_obj) {
    PostCallRecordBindImageMemory2(device, bindInfoCount, pBindInfos, record_obj);
}

void SyncValidator::PostCallRecordQueueWaitIdle(VkQueue queue, const RecordObject &record_obj) {
    if (record_obj.result != VK_SUCCESS || !syncval_settings.submit_time_validation || queue == VK_NULL_HANDLE) {
        return;
    }
    const auto queue_state = GetQueueSyncStateShared(queue);
    if (!queue_state) return;  // Invalid queue
    QueueId waited_queue = queue_state->GetQueueId();
    ApplyTaggedWait(waited_queue, ResourceUsageRecord::kMaxIndex, queue_state->GetLastSynchronizedPresent(), {});

    // For each timeline, remove all signals signaled on the waited queue, except the last one.
    // The last signal is needed to represent the current timeline state.
    EnsureTimelineSignalsLimit(1, waited_queue);

    // Eliminate host waitable objects from the current queue.
    vvl::EraseIf(waitable_fences_, [waited_queue](const auto &sf) { return sf.second.queue_id == waited_queue; });
    for (auto &[semaphore, sync_points] : host_waitable_semaphores_) {
        vvl::EraseIf(sync_points, [waited_queue](const auto &sync_point) { return sync_point.queue_id == waited_queue; });
    }
}

void SyncValidator::PostCallRecordDeviceWaitIdle(VkDevice device, const RecordObject &record_obj) {
    const auto batches = GetAllQueueBatchContexts();

    // Collect information about last synchronized present over all queues
    LastSynchronizedPresent global_last_synchronized_present;
    for (const auto &batch : batches) {
        global_last_synchronized_present.Merge(batch->last_synchronized_present);
    }

    // Device wait will preserve unsynchronized present operations.
    for (const auto &batch : batches) {
        batch->ApplyDeviceWait(global_last_synchronized_present);
    }

    // For each timeline keep only the last signal per queue.
    // The last signal is needed to represent the current timeline state.
    EnsureTimelineSignalsLimit(1);

    // As we we've waited for everything on device, any waits are mooted. (except for acquires)
    vvl::EraseIf(waitable_fences_, [](const auto &waitable) { return waitable.second.acquired.Invalid(); });
    host_waitable_semaphores_.clear();
}

struct QueuePresentCmdState {
    std::shared_ptr<const QueueSyncState> queue;
    SignalsUpdate signals_update;
    PresentedImages presented_images;
    QueuePresentCmdState(const SyncValidator &sync_validator) : signals_update(sync_validator) {}
};

bool SyncValidator::PreCallValidateQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo,
                                                   const ErrorObject &error_obj) const {
    bool skip = false;

    // Since this early return is above the TlsGuard, the Record phase must also be.
    if (!syncval_settings.submit_time_validation) return skip;

    ClearPending();

    vvl::TlsGuard<QueuePresentCmdState> cmd_state(&skip, *this);
    cmd_state->queue = GetQueueSyncStateShared(queue);
    if (!cmd_state->queue) return skip;  // Invalid Queue

    // The submit id is a mutable automic which is not recoverable on a skip == true condition
    uint64_t submit_id = cmd_state->queue->ReserveSubmitId();

    QueueBatchContext::ConstPtr last_batch = cmd_state->queue->LastBatch();
    QueueBatchContext::Ptr batch(std::make_shared<QueueBatchContext>(*this, *cmd_state->queue));

    uint32_t present_tag_count = SetupPresentInfo(*pPresentInfo, batch, cmd_state->presented_images);

    const auto wait_semaphores = vvl::make_span(pPresentInfo->pWaitSemaphores, pPresentInfo->waitSemaphoreCount);

    auto resolved_batches = batch->ResolvePresentWaits(wait_semaphores, cmd_state->presented_images, cmd_state->signals_update);

    // Import the previous batch information
    if (last_batch && !vvl::Contains(resolved_batches, last_batch)) {
        batch->ResolveLastBatch(last_batch);
        resolved_batches.emplace_back(std::move(last_batch));
    }

    // The purpose of keeping return value is to ensure async batches are alive during validation.
    // Validation accesses raw pointer to async contexts stored in AsyncReference.
    const auto async_batches = batch->RegisterAsyncContexts(resolved_batches);

    const ResourceUsageTag global_range_start = batch->SetupBatchTags(present_tag_count);
    // Update the present tags (convert to global range)
    for (auto &presented : cmd_state->presented_images) {
        presented.tag += global_range_start;
    }

    skip |= batch->DoQueuePresentValidate(error_obj.location, cmd_state->presented_images);
    batch->DoPresentOperations(cmd_state->presented_images);
    batch->LogPresentOperations(cmd_state->presented_images, submit_id);

    if (!skip) {
        cmd_state->queue->SetPendingLastBatch(std::move(batch));
    }
    return skip;
}

uint32_t SyncValidator::SetupPresentInfo(const VkPresentInfoKHR &present_info, QueueBatchContext::Ptr &batch,
                                         PresentedImages &presented_images) const {
    const VkSwapchainKHR *const swapchains = present_info.pSwapchains;
    const uint32_t *const image_indices = present_info.pImageIndices;
    const uint32_t swapchain_count = present_info.swapchainCount;

    // Create the working list of presented images
    presented_images.reserve(swapchain_count);
    for (uint32_t present_index = 0; present_index < swapchain_count; present_index++) {
        // Note: Given the "EraseIf" implementation for acquire fence waits, each presentation needs a unique tag.
        const ResourceUsageTag tag = presented_images.size();
        presented_images.emplace_back(const_cast<SyncValidator &>(*this), batch, swapchains[present_index],
                                      image_indices[present_index], present_index, tag);
        if (presented_images.back().Invalid()) {
            presented_images.pop_back();
        }
    }
    // Present is tagged for each swapchain.
    return static_cast<uint32_t>(presented_images.size());
}

void SyncValidator::PostCallRecordQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo,
                                                  const RecordObject &record_obj) {
    stats.UpdateAccessStats(*this);
    stats.UpdateMemoryStats();

    if (!syncval_settings.submit_time_validation) {
        return;
    }

    // The earliest return (when enabled), must be *after* the TlsGuard, as it is the TlsGuard that cleans up the cmd_state
    // static payload
    vvl::TlsGuard<QueuePresentCmdState> cmd_state;

    // See vvl::Device::PostCallRecordQueuePresentKHR for spec excerpt supporting
    if (record_obj.result == VK_ERROR_OUT_OF_HOST_MEMORY || record_obj.result == VK_ERROR_OUT_OF_DEVICE_MEMORY ||
        record_obj.result == VK_ERROR_DEVICE_LOST) {
        return;
    }

    // Update the state with the data from the validate phase
    std::shared_ptr<QueueSyncState> queue_state = std::const_pointer_cast<QueueSyncState>(std::move(cmd_state->queue));
    if (!queue_state) return;  // Invalid Queue
    ApplySignalsUpdate(cmd_state->signals_update, queue_state->PendingLastBatch());
    for (auto &presented : cmd_state->presented_images) {
        presented.ExportToSwapchain(*this);
    }
    queue_state->ApplyPendingLastBatch();
}

void SyncValidator::PostCallRecordAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout,
                                                      VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex,
                                                      const RecordObject &record_obj) {
    if (!syncval_settings.submit_time_validation) return;
    RecordAcquireNextImageState(device, swapchain, timeout, semaphore, fence, pImageIndex, record_obj);
}

void SyncValidator::PostCallRecordAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR *pAcquireInfo,
                                                       uint32_t *pImageIndex, const RecordObject &record_obj) {
    if (!syncval_settings.submit_time_validation) return;
    RecordAcquireNextImageState(device, pAcquireInfo->swapchain, pAcquireInfo->timeout, pAcquireInfo->semaphore,
                                pAcquireInfo->fence, pImageIndex, record_obj);
}

void SyncValidator::RecordAcquireNextImageState(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore,
                                                VkFence fence, uint32_t *pImageIndex, const RecordObject &record_obj) {
    if ((VK_SUCCESS != record_obj.result) && (VK_SUBOPTIMAL_KHR != record_obj.result)) return;

    // Get the image out of the presented list and create apppropriate fences/semaphores.
    auto swapchain_base = Get<vvl::Swapchain>(swapchain);
    if (vvl::StateObject::Invalid(swapchain_base)) return;  // Invalid acquire calls to be caught in CoreCheck/Parameter validation

    auto &swapchain_state = SubState(*swapchain_base);

    PresentedImage presented = swapchain_state.MovePresentedImage(*pImageIndex);
    if (presented.Invalid()) return;

    // No way to make access safe, so nothing to record
    if ((semaphore == VK_NULL_HANDLE) && (fence == VK_NULL_HANDLE)) return;

    // We create a queue-less QBC for the Semaphore and fences to wait on

    // Note: this is a heavyweight way to deal with the fact that all operation logs live in the QueueBatchContext... and
    // acquire doesn't happen on a queue, but we need a place to put the acquire operation access record.
    auto batch = std::make_shared<QueueBatchContext>(*this);
    batch->SetupAccessContext(presented);
    const ResourceUsageTag acquire_tag = batch->SetupBatchTags(1);
    batch->DoAcquireOperation(presented);
    batch->LogAcquireOperation(presented, record_obj.location.function);

    // Now swap out the present queue batch with the acquired one.
    // Note that fence and signal will read the acquire batch from presented, so this needs to be done before
    // setting up the synchronization
    presented.batch = std::move(batch);

    if (semaphore != VK_NULL_HANDLE) {
        std::shared_ptr<const vvl::Semaphore> sem_state = Get<vvl::Semaphore>(semaphore);
        if (sem_state) {
            // This will ignore any duplicated signal (emplace does not update existing entry),
            // and the core validation reports and error in this case.
            binary_signals_.emplace(sem_state->VkHandle(), SignalInfo(sem_state, presented, acquire_tag));
        }
    }
    if (fence != VK_NULL_HANDLE) {
        FenceHostSyncPoint sync_point;
        sync_point.tag = acquire_tag;
        sync_point.acquired = AcquiredImage(presented, acquire_tag);
        UpdateFenceHostSyncPoint(fence, std::move(sync_point));
    }
}

bool SyncValidator::PreCallValidateQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence,
                                               const ErrorObject &error_obj) const {
    SubmitInfoConverter submit_info(pSubmits, submitCount);
    return ValidateQueueSubmit(queue, submitCount, submit_info.submit_infos2.data(), fence, error_obj);
}

static std::vector<CommandBufferConstPtr> GetCommandBuffers(const vvl::DeviceState &device_state,
                                                            const VkSubmitInfo2 &submit_info) {
    // Collected command buffers have the same indexing as in the input VkSubmitInfo2 for reporting purposes.
    // If Get query returns null, it is stored in the result array to keep original indexing.
    std::vector<CommandBufferConstPtr> command_buffers;
    command_buffers.reserve(submit_info.commandBufferInfoCount);
    for (const auto &cb_info : vvl::make_span(submit_info.pCommandBufferInfos, submit_info.commandBufferInfoCount)) {
        command_buffers.emplace_back(device_state.Get<vvl::CommandBuffer>(cb_info.commandBuffer));
    }
    return command_buffers;
}

bool SyncValidator::ValidateQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2 *pSubmits, VkFence fence,
                                        const ErrorObject &error_obj) const {
    bool skip = false;

    // Since this early return is above the TlsGuard, the Record phase must also be.
    if (!syncval_settings.submit_time_validation) return skip;

    std::lock_guard lock_guard(queue_submit_mutex_);

    ClearPending();

    QueueSubmitCmdState cmd_state_obj(*this);
    QueueSubmitCmdState* cmd_state = &cmd_state_obj;

    cmd_state->queue = GetQueueSyncStateShared(queue);
    if (!cmd_state->queue) return skip;  // Invalid Queue

    auto &queue_sync_state = cmd_state->queue;
    SignalsUpdate &signals_update = cmd_state->signals_update;

    // The submit id is a mutable automic which is not recoverable on a skip == true condition
    uint64_t submit_id = queue_sync_state->ReserveSubmitId();

    // Update label stack as we progress through batches and command buffers
    auto current_label_stack = queue_sync_state->GetQueueState()->cmdbuf_label_stack;

    BatchContextConstPtr last_batch = queue_sync_state->LastBatch();
    bool has_unresolved_batches = !queue_sync_state->UnresolvedBatches().empty();

    BatchContextPtr new_last_batch;
    std::vector<UnresolvedBatch> new_unresolved_batches;
    bool new_timeline_signals = false;

    for (uint32_t batch_idx = 0; batch_idx < submitCount; batch_idx++) {
        const VkSubmitInfo2 &submit = pSubmits[batch_idx];
        auto batch = std::make_shared<QueueBatchContext>(*this, *queue_sync_state);

        const auto wait_semaphores = vvl::make_span(submit.pWaitSemaphoreInfos, submit.waitSemaphoreInfoCount);
        std::vector<VkSemaphoreSubmitInfo> unresolved_waits;
        auto resolved_batches = batch->ResolveSubmitWaits(wait_semaphores, unresolved_waits, signals_update);

        // Add unresolved batch
        if (has_unresolved_batches || !unresolved_waits.empty()) {
            UnresolvedBatch unresolved_batch;
            unresolved_batch.batch = std::move(batch);
            unresolved_batch.submit_index = submit_id;
            unresolved_batch.batch_index = batch_idx;
            unresolved_batch.command_buffers = GetCommandBuffers(*device_state, submit);
            unresolved_batch.unresolved_waits = std::move(unresolved_waits);
            unresolved_batch.resolved_dependencies = std::move(resolved_batches);
            if (submit.pSignalSemaphoreInfos && submit.signalSemaphoreInfoCount) {
                const auto last_info = submit.pSignalSemaphoreInfos + submit.signalSemaphoreInfoCount;
                unresolved_batch.signals.assign(submit.pSignalSemaphoreInfos, last_info);
            }
            unresolved_batch.label_stack = current_label_stack;
            new_unresolved_batches.emplace_back(std::move(unresolved_batch));
            has_unresolved_batches = true;
            stats.AddUnresolvedBatch();
            continue;
        }
        new_last_batch = batch;

        // Import the previous batch information
        if (last_batch && !vvl::Contains(resolved_batches, last_batch)) {
            batch->ResolveLastBatch(last_batch);
            resolved_batches.emplace_back(std::move(last_batch));
        }

        // The purpose of keeping return value is to ensure async batches are alive during validation.
        // Validation accesses raw pointer to async contexts stored in AsyncReference.
        // TODO: All syncval tests pass when the return value is ignored. Write a regression test that fails/crashes in this case.
        const auto async_batches = batch->RegisterAsyncContexts(resolved_batches);

        const auto command_buffers = GetCommandBuffers(*device_state, submit);
        skip |= batch->ValidateSubmit(command_buffers, submit_id, batch_idx, current_label_stack, error_obj);

        const auto submit_signals = vvl::make_span(submit.pSignalSemaphoreInfos, submit.signalSemaphoreInfoCount);
        new_timeline_signals |= signals_update.RegisterSignals(batch, submit_signals);

        // Unless the previous batch was referenced by a signal it will self destruct
        // in the record phase when the last batch is updated.
        last_batch = batch;
    }

    // Schedule state update
    if (new_last_batch) {
        queue_sync_state->SetPendingLastBatch(std::move(new_last_batch));
    }
    if (!new_unresolved_batches.empty()) {
        auto unresolved_batches = queue_sync_state->UnresolvedBatches();
        vvl::Append(unresolved_batches, new_unresolved_batches);
        queue_sync_state->SetPendingUnresolvedBatches(std::move(unresolved_batches));
    }

    // Check if timeline signals resolve existing wait-before-signal dependencies
    if (new_timeline_signals) {
        skip |= PropagateTimelineSignals(signals_update, error_obj);
    }

    if (!skip) {
        const_cast<SyncValidator *>(this)->RecordQueueSubmit(queue, fence, cmd_state);
    }

    // Note that if we skip, guard cleans up for us, but cannot release the reserved tag range
    return skip;
}

bool SyncValidator::PropagateTimelineSignals(SignalsUpdate &signals_update, const ErrorObject &error_obj) const {
    bool skip = false;
    // Initialize per-queue unresolved batches state.
    std::vector<UnresolvedQueue> queues;
    for (const auto &queue_state : queue_sync_states_) {
        if (!queue_state->PendingUnresolvedBatches().empty()) {
            // Pending request defines the final unresolved list (current + new unresolved batches)
            queues.emplace_back(UnresolvedQueue{queue_state, queue_state->PendingUnresolvedBatches()});
        } else if (!queue_state->UnresolvedBatches().empty()) {
            queues.emplace_back(UnresolvedQueue{queue_state, queue_state->UnresolvedBatches()});
        }
    }

    // Each iteration uses registered timeline signals to resolve existing unresolved batches.
    // Each resolved batch can generate new timeline signals which can resolve more unresolved batches on the next iteration.
    // This finishes when all unresolved batches are resolved or when iteration does not generate new timeline signals.
    while (PropagateTimelineSignalsIteration(queues, signals_update, skip, error_obj)) {
        ;
    }

    // Schedule unresolved state update
    for (UnresolvedQueue &queue : queues) {
        if (queue.update_unresolved) {
            queue.queue_state->SetPendingUnresolvedBatches(std::move(queue.unresolved_batches));
        }
    }
    return skip;
}

bool SyncValidator::PropagateTimelineSignalsIteration(std::vector<UnresolvedQueue> &queues, SignalsUpdate &signals_update,
                                                      bool &skip, const ErrorObject &error_obj) const {
    bool has_new_timeline_signals = false;
    for (auto &queue : queues) {
        if (queue.unresolved_batches.empty()) {
            continue;  // all batches for this queue were resolved by previous iterations
        }

        BatchContextPtr last_batch =
            queue.queue_state->PendingLastBatch() ? queue.queue_state->PendingLastBatch() : queue.queue_state->LastBatch();
        const BatchContextPtr initial_last_batch = last_batch;

        while (!queue.unresolved_batches.empty()) {
            auto &unresolved_batch = queue.unresolved_batches.front();

            has_new_timeline_signals |= ProcessUnresolvedBatch(unresolved_batch, signals_update, last_batch, skip, error_obj);

            // Remove processed batch from the (local) unresolved list
            queue.unresolved_batches.erase(queue.unresolved_batches.begin());

            // Propagate change into the queue's (global) unresolved state
            queue.update_unresolved = true;

            stats.RemoveUnresolvedBatch();
        }
        if (last_batch != initial_last_batch) {
            queue.queue_state->SetPendingLastBatch(std::move(last_batch));
        }
    }
    return has_new_timeline_signals;
}

bool SyncValidator::ProcessUnresolvedBatch(UnresolvedBatch &unresolved_batch, SignalsUpdate &signals_update,
                                           BatchContextPtr &last_batch, bool &skip, const ErrorObject &error_obj) const {
    // Resolve waits that have matching signal
    auto it = unresolved_batch.unresolved_waits.begin();
    while (it != unresolved_batch.unresolved_waits.end()) {
        const VkSemaphoreSubmitInfo &wait_info = *it;
        auto resolving_signal = signals_update.OnTimelineWait(wait_info.semaphore, wait_info.value);
        if (!resolving_signal.has_value()) {
            ++it;
            continue;  // resolving signal not found, the wait stays unresolved
        }
        if (resolving_signal->batch) {  // null for host signals
            unresolved_batch.batch->ResolveSubmitSemaphoreWait(*resolving_signal, wait_info.stageMask);
            unresolved_batch.batch->ImportTags(*resolving_signal->batch);
            unresolved_batch.resolved_dependencies.emplace_back(resolving_signal->batch);
        }
        it = unresolved_batch.unresolved_waits.erase(it);
    }

    // This batch still has unresolved waits
    if (!unresolved_batch.unresolved_waits.empty()) {
        return false;  // no new timeline signals were registered
    }

    // Process fully resolved batch
    UnresolvedBatch &ready_batch = unresolved_batch;
    if (last_batch && !vvl::Contains(ready_batch.resolved_dependencies, last_batch)) {
        ready_batch.batch->ResolveLastBatch(last_batch);
        ready_batch.resolved_dependencies.emplace_back(std::move(last_batch));
    }
    last_batch = ready_batch.batch;

    const auto async_batches = ready_batch.batch->RegisterAsyncContexts(ready_batch.resolved_dependencies);

    skip |= ready_batch.batch->ValidateSubmit(ready_batch.command_buffers, ready_batch.submit_index, ready_batch.batch_index,
                                              ready_batch.label_stack, error_obj);

    const auto submit_signals = vvl::make_span(ready_batch.signals.data(), ready_batch.signals.size());
    return signals_update.RegisterSignals(ready_batch.batch, submit_signals);
}

void SyncValidator::RecordQueueSubmit(VkQueue queue, VkFence fence, QueueSubmitCmdState *cmd_state) {
    stats.UpdateMemoryStats();

    // If this return is above the TlsGuard, then the Validate phase return must also be.
    if (!syncval_settings.submit_time_validation) {
        return;
    }

    if (!cmd_state->queue) {
        return;
    }

    // Don't need to look up the queue state again, but we need a non-const version
    std::shared_ptr<QueueSyncState> queue_state = std::const_pointer_cast<QueueSyncState>(std::move(cmd_state->queue));
    ApplySignalsUpdate(cmd_state->signals_update, queue_state->PendingLastBatch());

    // Apply the pending state from the validation phase. Check all queues because timeline signals
    // on the current queue can resolve wait-before-signal batches on other queues.
    for (const auto &qs : queue_sync_states_) {
        qs->ApplyPendingLastBatch();
        qs->ApplyPendingUnresolvedBatches();
    }

    const QueueId queue_id = queue_state->GetQueueId();
    FenceHostSyncPoint sync_point;
    sync_point.queue_id = queue_id;
    sync_point.tag = ReserveGlobalTagRange(1).begin;
    if (auto last_batch = queue_sync_states_[queue_id]->LastBatch()) {
        sync_point.queue_sync_tags = last_batch->GetQueueSyncTags();
    }
    UpdateFenceHostSyncPoint(fence, std::move(sync_point));
}

bool SyncValidator::PreCallValidateQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR *pSubmits,
                                                   VkFence fence, const ErrorObject &error_obj) const {
    return PreCallValidateQueueSubmit2(queue, submitCount, pSubmits, fence, error_obj);
}

bool SyncValidator::PreCallValidateQueueSubmit2(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2 *pSubmits, VkFence fence,
                                                const ErrorObject &error_obj) const {
    return ValidateQueueSubmit(queue, submitCount, pSubmits, fence, error_obj);
}

void SyncValidator::PostCallRecordGetFenceStatus(VkDevice device, VkFence fence, const RecordObject &record_obj) {
    if (!syncval_settings.submit_time_validation) return;
    if (record_obj.result == VK_SUCCESS) {
        // fence is signalled, mark it as waited for
        WaitForFence(fence);
    }
}

void SyncValidator::PostCallRecordWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll,
                                                uint64_t timeout, const RecordObject &record_obj) {
    if (!syncval_settings.submit_time_validation) return;
    if ((record_obj.result == VK_SUCCESS) && ((VK_TRUE == waitAll) || (1 == fenceCount))) {
        // We can only know the pFences have signal if we waited for all of them, or there was only one of them
        for (uint32_t i = 0; i < fenceCount; i++) {
            WaitForFence(pFences[i]);
        }
    }
}

bool SyncValidator::PreCallValidateSignalSemaphore(VkDevice device, const VkSemaphoreSignalInfo *pSignalInfo,
                                                   const ErrorObject &error_obj) const {
    bool skip = false;
    if (!syncval_settings.submit_time_validation) {
        return skip;
    }
    ClearPending();
    vvl::TlsGuard<QueueSubmitCmdState> cmd_state(&skip, *this);
    SignalsUpdate &signals_update = cmd_state->signals_update;

    auto semaphore_state = Get<vvl::Semaphore>(pSignalInfo->semaphore);
    if (!semaphore_state) {
        return skip;
    }

    std::vector<SignalInfo> &signals = signals_update.timeline_signals[pSignalInfo->semaphore];

    // Reject invalid signal
    if (!signals.empty() && pSignalInfo->value <= signals.back().timeline_value) {
        return skip;  // [core validation check]: strictly increasing signal values
    }

    signals.emplace_back(SignalInfo(semaphore_state, pSignalInfo->value));
    skip |= PropagateTimelineSignals(signals_update, error_obj);
    return skip;
}

bool SyncValidator::PreCallValidateSignalSemaphoreKHR(VkDevice device, const VkSemaphoreSignalInfo *pSignalInfo,
                                                      const ErrorObject &error_obj) const {
    return PreCallValidateSignalSemaphore(device, pSignalInfo, error_obj);
}

void SyncValidator::PostCallRecordSignalSemaphore(VkDevice device, const VkSemaphoreSignalInfo *pSignalInfo,
                                                  const RecordObject &record_obj) {
    if (!syncval_settings.submit_time_validation) {
        return;
    }

    // The earliest return (when enabled), must be *after* the TlsGuard, as it is the TlsGuard that cleans up the cmd_state
    // static payload
    vvl::TlsGuard<QueueSubmitCmdState> cmd_state;

    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    ApplySignalsUpdate(cmd_state->signals_update, nullptr);
    for (const auto &qs : queue_sync_states_) {
        qs->ApplyPendingLastBatch();
        qs->ApplyPendingUnresolvedBatches();
    }
}

void SyncValidator::PostCallRecordSignalSemaphoreKHR(VkDevice device, const VkSemaphoreSignalInfo *pSignalInfo,
                                                     const RecordObject &record_obj) {
    PostCallRecordSignalSemaphore(device, pSignalInfo, record_obj);
}

void SyncValidator::PostCallRecordWaitSemaphores(VkDevice device, const VkSemaphoreWaitInfo *pWaitInfo, uint64_t timeout,
                                                 const RecordObject &record_obj) {
    if (!syncval_settings.submit_time_validation) {
        return;
    }
    const bool wait_all = pWaitInfo->semaphoreCount == 1 || (pWaitInfo->flags & VK_SEMAPHORE_WAIT_ANY_BIT) == 0;
    if (record_obj.result == VK_SUCCESS && wait_all) {
        for (uint32_t i = 0; i < pWaitInfo->semaphoreCount; i++) {
            WaitForSemaphore(pWaitInfo->pSemaphores[i], pWaitInfo->pValues[i]);
        }
    }
}

void SyncValidator::PostCallRecordWaitSemaphoresKHR(VkDevice device, const VkSemaphoreWaitInfo *pWaitInfo, uint64_t timeout,
                                                    const RecordObject &record_obj) {
    PostCallRecordWaitSemaphores(device, pWaitInfo, timeout, record_obj);
}

void SyncValidator::PostCallRecordGetSemaphoreCounterValue(VkDevice device, VkSemaphore semaphore, uint64_t *pValue,
                                                           const RecordObject &record_obj) {
    if (!syncval_settings.submit_time_validation) {
        return;
    }
    if (record_obj.result == VK_SUCCESS) {
        WaitForSemaphore(semaphore, *pValue);
    }
}

void SyncValidator::PostCallRecordGetSemaphoreCounterValueKHR(VkDevice device, VkSemaphore semaphore, uint64_t *pValue,
                                                              const RecordObject &record_obj) {
    PostCallRecordGetSemaphoreCounterValue(device, semaphore, pValue, record_obj);
}

// Returns null when device address is asssociated with no buffers or more than one buffer.
// Otherwise returns a valid buffer (device address is associated with a single buffer).
// When syncval adds memory aliasing support the need of this function can be revisited.
static const vvl::Buffer *GetSingleBufferFromDeviceAddress(const vvl::DeviceState &device, VkDeviceAddress device_address) {
    vvl::span<vvl::Buffer *const> buffers = device.GetBuffersByAddress(device_address);
    if (buffers.empty()) {
        return nullptr;
    }
    if (buffers.size() > 1) {  // memory aliasing use case
        return nullptr;
    }
    return buffers[0];
}

struct AccelerationStructureGeometryInfo {
    const vvl::Buffer *vertex_data = nullptr;
    AccessRange vertex_range;
    const vvl::Buffer *index_data = nullptr;
    AccessRange index_range;
    const vvl::Buffer *transform_data = nullptr;
    AccessRange transform_range;
    const vvl::Buffer *aabb_data = nullptr;
    AccessRange aabb_range;
    const vvl::Buffer *instance_data = nullptr;
    AccessRange instance_range;
};

static std::optional<AccelerationStructureGeometryInfo> GetValidGeometryInfo(
    const vvl::DeviceState &device, const VkAccelerationStructureGeometryKHR &geometry,
    const VkAccelerationStructureBuildRangeInfoKHR &range_info) {
    if (geometry.geometryType == VK_GEOMETRY_TYPE_TRIANGLES_KHR) {
        const VkAccelerationStructureGeometryTrianglesDataKHR &triangles = geometry.geometry.triangles;
        AccelerationStructureGeometryInfo geometry_info;

        // Assume that synchronization ranges cover the entire vertex struct,
        // even if positional data is strided (i.e., interleaved with other attributes).
        // That is, the application does not attempt to synchronize each position variable
        // with a separate buffer barrier range.
        const vvl::Buffer *p_vertex_data = GetSingleBufferFromDeviceAddress(device, triangles.vertexData.deviceAddress);

        if (triangles.indexType == VK_INDEX_TYPE_NONE_KHR) {
            // Vertex data
            if (p_vertex_data) {
                geometry_info.vertex_data = p_vertex_data;
                const VkDeviceSize base_vertex_offset = triangles.vertexData.deviceAddress - p_vertex_data->deviceAddress;
                const VkDeviceSize local_offset = range_info.primitiveOffset + range_info.firstVertex * triangles.vertexStride;
                const VkDeviceSize offset = base_vertex_offset + local_offset;
                const VkDeviceSize vertex_data_size = 3 * range_info.primitiveCount * triangles.vertexStride;
                geometry_info.vertex_range = MakeRange(*p_vertex_data, offset, vertex_data_size);
            }
        } else {
            // Vertex data
            if (p_vertex_data) {
                geometry_info.vertex_data = p_vertex_data;
                const VkDeviceSize base_vertex_offset = triangles.vertexData.deviceAddress - p_vertex_data->deviceAddress;
                const VkDeviceSize local_offset = range_info.firstVertex * triangles.vertexStride;
                const VkDeviceSize offset = base_vertex_offset + local_offset;
                const VkDeviceSize all_vertex_data_size = (triangles.maxVertex + 1) * triangles.vertexStride;
                const VkDeviceSize potentially_accessed_vertex_data_size = all_vertex_data_size - local_offset;
                geometry_info.vertex_range = MakeRange(*p_vertex_data, offset, potentially_accessed_vertex_data_size);
            }
            // Index data
            const auto p_index_data = GetSingleBufferFromDeviceAddress(device, triangles.indexData.deviceAddress);
            if (p_index_data) {
                geometry_info.index_data = p_index_data;
                const VkDeviceSize base_index_offset = triangles.indexData.deviceAddress - p_index_data->deviceAddress;
                const uint32_t index_byte_size = IndexTypeSize(triangles.indexType);
                const VkDeviceSize offset = base_index_offset + range_info.primitiveOffset;
                const uint32_t index_data_size = 3 * range_info.primitiveCount * index_byte_size;
                geometry_info.index_range = MakeRange(*p_index_data, offset, index_data_size);
            }
        }
        // Transform data
        if (const vvl::Buffer *p_transform_data = GetSingleBufferFromDeviceAddress(device, triangles.transformData.deviceAddress)) {
            const VkDeviceSize base_offset = triangles.transformData.deviceAddress - p_transform_data->deviceAddress;
            const VkDeviceSize offset = base_offset + range_info.transformOffset;
            geometry_info.transform_data = p_transform_data;
            geometry_info.transform_range = MakeRange(*p_transform_data, offset, sizeof(VkTransformMatrixKHR));
        }
        return geometry_info;
    } else if (geometry.geometryType == VK_GEOMETRY_TYPE_AABBS_KHR) {
        // Make a similar assumption for strided aabb data as for vertex data - synchronization ranges themselves are not strided.
        const VkAccelerationStructureGeometryAabbsDataKHR &aabbs = geometry.geometry.aabbs;
        if (const vvl::Buffer *p_aabbs = GetSingleBufferFromDeviceAddress(device, aabbs.data.deviceAddress)) {
            AccelerationStructureGeometryInfo geometry_info;
            geometry_info.aabb_data = p_aabbs;
            const VkDeviceSize base_offset = aabbs.data.deviceAddress - p_aabbs->deviceAddress;
            const VkDeviceSize offset = base_offset + range_info.primitiveOffset;
            const VkDeviceSize aabb_data_size = range_info.primitiveCount * sizeof(VkAabbPositionsKHR);
            geometry_info.aabb_range = MakeRange(*p_aabbs, offset, aabb_data_size);
            return geometry_info;
        }
    } else if (geometry.geometryType == VK_GEOMETRY_TYPE_INSTANCES_KHR) {
        const VkAccelerationStructureGeometryInstancesDataKHR &instances = geometry.geometry.instances;
        if (const vvl::Buffer *p_instances = GetSingleBufferFromDeviceAddress(device, instances.data.deviceAddress)) {
            AccelerationStructureGeometryInfo geometry_info;
            geometry_info.instance_data = p_instances;
            const VkDeviceSize base_offset = instances.data.deviceAddress - p_instances->deviceAddress;
            const VkDeviceSize offset = base_offset + range_info.primitiveOffset;
            const VkDeviceSize instance_data_size =
                range_info.primitiveCount *
                (instances.arrayOfPointers ? sizeof(VkDeviceAddress) : sizeof(VkAccelerationStructureInstanceKHR));
            geometry_info.instance_range = MakeRange(*p_instances, offset, instance_data_size);
            return geometry_info;
        }
    }
    return {};
}

bool SyncValidator::PreCallValidateCmdBuildAccelerationStructuresKHR(
    VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR *pInfos,
    const VkAccelerationStructureBuildRangeInfoKHR *const *ppBuildRangeInfos, const ErrorObject &error_obj) const {
    bool skip = false;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &context = *cb_context.GetCurrentAccessContext();

    for (const auto [i, info] : vvl::enumerate(pInfos, infoCount)) {
        const Location info_loc = error_obj.location.dot(Field::pInfos, i);
        // Validate scratch buffer
        if (const vvl::Buffer *p_scratch_buffer = GetSingleBufferFromDeviceAddress(*device_state, info.scratchData.deviceAddress)) {
            const vvl::Buffer &scratch_buffer = *p_scratch_buffer;
            const VkDeviceSize scratch_size = rt::ComputeScratchSize(rt::BuildType::Device, device, info, ppBuildRangeInfos[i]);
            const VkDeviceSize offset = info.scratchData.deviceAddress - scratch_buffer.deviceAddress;
            const AccessRange range = MakeRange(scratch_buffer, offset, scratch_size);
            auto hazard =
                context.DetectHazard(scratch_buffer, SYNC_ACCELERATION_STRUCTURE_BUILD_ACCELERATION_STRUCTURE_WRITE, range);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, scratch_buffer.Handle());
                const std::string resource_description = "scratch buffer " + FormatHandle(scratch_buffer.VkHandle());
                const auto error =
                    error_messages_.BufferError(hazard, cb_context, error_obj.location.function, resource_description, range);
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
        // Validate access to source acceleration structure
        if (const auto src_accel = Get<vvl::AccelerationStructureKHR>(info.srcAccelerationStructure)) {
            const AccessRange range = MakeRange(src_accel->GetOffset(), src_accel->GetSize());
            auto hazard = context.DetectHazard(*src_accel->buffer_state,
                                               SYNC_ACCELERATION_STRUCTURE_BUILD_ACCELERATION_STRUCTURE_READ, range);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, src_accel->buffer_state->Handle(), src_accel->Handle());
                const std::string resource_description = FormatHandle(src_accel->buffer_state->VkHandle());
                const std::string error = error_messages_.AccelerationStructureError(
                    hazard, cb_context, error_obj.location.function, resource_description, range, info.srcAccelerationStructure,
                    info_loc.dot(Field::srcAccelerationStructure));
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
        // Validate access to the acceleration structure being built
        if (const auto dst_accel = Get<vvl::AccelerationStructureKHR>(info.dstAccelerationStructure)) {
            const AccessRange dst_range = MakeRange(dst_accel->GetOffset(), dst_accel->GetSize());
            auto hazard = context.DetectHazard(*dst_accel->buffer_state,
                                               SYNC_ACCELERATION_STRUCTURE_BUILD_ACCELERATION_STRUCTURE_WRITE, dst_range);
            if (hazard.IsHazard()) {
                const LogObjectList objlist(commandBuffer, dst_accel->buffer_state->Handle(), dst_accel->Handle());
                const std::string resource_description = FormatHandle(dst_accel->buffer_state->VkHandle());
                const std::string error = error_messages_.AccelerationStructureError(
                    hazard, cb_context, error_obj.location.function, resource_description, dst_range, info.dstAccelerationStructure,
                    info_loc.dot(Field::dstAccelerationStructure));
                skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
            }
        }
        // Validate geometry buffers
        const VkAccelerationStructureBuildRangeInfoKHR *p_range_infos = ppBuildRangeInfos[i];
        if (!p_range_infos) {
            continue;  // [core validation check]: range pointers should be valid
        }
        for (uint32_t k = 0; k < info.geometryCount; k++) {
            const auto *p_geometry = info.pGeometries ? &info.pGeometries[k] : info.ppGeometries[k];
            if (!p_geometry) {
                continue;  // [core validation check]: null pointer in ppGeometries
            }
            const auto geometry_info = GetValidGeometryInfo(*device_state, *p_geometry, p_range_infos[k]);
            if (!geometry_info.has_value()) {
                continue;
            }
            auto validate_accel_input_geometry = [this, &context, &cb_context, &commandBuffer, &error_obj](
                                                     const vvl::Buffer &geometry_data, const AccessRange &geometry_range,
                                                     const char *data_description) {
                auto hazard = context.DetectHazard(geometry_data, SYNC_ACCELERATION_STRUCTURE_BUILD_SHADER_READ, geometry_range);
                if (hazard.IsHazard()) {
                    const LogObjectList objlist(commandBuffer, geometry_data.Handle());
                    std::ostringstream ss;
                    ss << data_description << " ";
                    ss << FormatHandle(geometry_data.Handle());
                    const std::string resource_description = ss.str();
                    const std::string error = error_messages_.BufferError(hazard, cb_context, error_obj.location.function,
                                                                          resource_description, geometry_range);
                    return SyncError(hazard.Hazard(), objlist, error_obj.location, error);
                }
                return false;
            };
            if (geometry_info->vertex_data) {
                skip |= validate_accel_input_geometry(*geometry_info->vertex_data, geometry_info->vertex_range, "vertex data");
            }
            if (geometry_info->index_data) {
                skip |= validate_accel_input_geometry(*geometry_info->index_data, geometry_info->index_range, "index data");
            }
            if (geometry_info->transform_data) {
                skip |=
                    validate_accel_input_geometry(*geometry_info->transform_data, geometry_info->transform_range, "transform data");
            }
            if (geometry_info->aabb_data) {
                skip |= validate_accel_input_geometry(*geometry_info->aabb_data, geometry_info->aabb_range, "aabb data");
            }
            if (geometry_info->instance_data) {
                skip |=
                    validate_accel_input_geometry(*geometry_info->instance_data, geometry_info->instance_range, "instance data");
            }
        }
    }
    return skip;
}

void SyncValidator::PostCallRecordCmdBuildAccelerationStructuresKHR(
    VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR *pInfos,
    const VkAccelerationStructureBuildRangeInfoKHR *const *ppBuildRangeInfos, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &context = *cb_context.GetCurrentAccessContext();

    const ResourceUsageTag tag = cb_context.NextCommandTag(record_obj.location.function);

    for (const auto [i, info] : vvl::enumerate(pInfos, infoCount)) {
        // Record scratch buffer access
        if (const vvl::Buffer *p_scratch_buffer = GetSingleBufferFromDeviceAddress(*device_state, info.scratchData.deviceAddress)) {
            const vvl::Buffer &scratch_buffer = *p_scratch_buffer;
            const VkDeviceSize scratch_size = rt::ComputeScratchSize(rt::BuildType::Device, device, info, ppBuildRangeInfos[i]);
            const VkDeviceSize offset = info.scratchData.deviceAddress - scratch_buffer.deviceAddress;
            const AccessRange scratch_range = MakeRange(scratch_buffer, offset, scratch_size);
            const ResourceUsageTagEx scratch_tag_ex = cb_context.AddCommandHandle(tag, scratch_buffer.Handle());
            context.UpdateAccessState(scratch_buffer, SYNC_ACCELERATION_STRUCTURE_BUILD_ACCELERATION_STRUCTURE_WRITE, scratch_range,
                                      scratch_tag_ex);
        }

        const auto src_accel = Get<vvl::AccelerationStructureKHR>(info.srcAccelerationStructure);
        const auto dst_accel = Get<vvl::AccelerationStructureKHR>(info.dstAccelerationStructure);

        // Record source acceleration structure access (READ).
        // If the source is the same as the destination then no need to record READ
        // (destination update will replace access with WRITE anyway).
        if (src_accel && src_accel != dst_accel) {
            const AccessRange range = MakeRange(src_accel->GetOffset(), src_accel->GetSize());
            const ResourceUsageTagEx tag_ex = cb_context.AddCommandHandle(tag, src_accel->buffer_state->Handle());
            context.UpdateAccessState(*src_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_BUILD_ACCELERATION_STRUCTURE_READ,
                                      range, tag_ex);
        }
        // Record destination acceleration structure access (WRITE)
        if (dst_accel) {
            const AccessRange dst_range = MakeRange(dst_accel->GetOffset(), dst_accel->GetSize());
            const ResourceUsageTagEx dst_tag_ex = cb_context.AddCommandHandle(tag, dst_accel->buffer_state->Handle());
            context.UpdateAccessState(*dst_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_BUILD_ACCELERATION_STRUCTURE_WRITE,
                                      dst_range, dst_tag_ex);
        }
        // Record geometry buffer acceses (READ)
        const VkAccelerationStructureBuildRangeInfoKHR *p_range_infos = ppBuildRangeInfos[i];
        if (!p_range_infos) {
            continue;  // [core validation check]: range pointers should be valid
        }
        for (uint32_t k = 0; k < info.geometryCount; k++) {
            const auto *p_geometry = info.pGeometries ? &info.pGeometries[k] : info.ppGeometries[k];
            if (!p_geometry) {
                continue;  // [core validation check]: null pointer in ppGeometries
            }
            const auto geometry_info = GetValidGeometryInfo(*device_state, *p_geometry, p_range_infos[k]);
            if (!geometry_info.has_value()) {
                continue;
            }
            if (geometry_info->vertex_data) {
                const ResourceUsageTagEx vertex_tag_ex = cb_context.AddCommandHandle(tag, geometry_info->vertex_data->Handle());
                context.UpdateAccessState(*geometry_info->vertex_data, SYNC_ACCELERATION_STRUCTURE_BUILD_SHADER_READ,
                                          geometry_info->vertex_range, vertex_tag_ex);
            }
            if (geometry_info->index_data) {
                const ResourceUsageTagEx index_tag_ex = cb_context.AddCommandHandle(tag, geometry_info->index_data->Handle());
                context.UpdateAccessState(*geometry_info->index_data, SYNC_ACCELERATION_STRUCTURE_BUILD_SHADER_READ,
                                          geometry_info->index_range, index_tag_ex);
            }
            if (geometry_info->transform_data) {
                const ResourceUsageTagEx transform_tag_ex =
                    cb_context.AddCommandHandle(tag, geometry_info->transform_data->Handle());
                context.UpdateAccessState(*geometry_info->transform_data, SYNC_ACCELERATION_STRUCTURE_BUILD_SHADER_READ,
                                          geometry_info->transform_range, transform_tag_ex);
            }
            if (geometry_info->aabb_data) {
                const ResourceUsageTagEx aabb_tag_ex = cb_context.AddCommandHandle(tag, geometry_info->aabb_data->Handle());
                context.UpdateAccessState(*geometry_info->aabb_data, SYNC_ACCELERATION_STRUCTURE_BUILD_SHADER_READ,
                                          geometry_info->aabb_range, aabb_tag_ex);
            }
            if (geometry_info->instance_data) {
                const ResourceUsageTagEx instance_tag_ex = cb_context.AddCommandHandle(tag, geometry_info->instance_data->Handle());
                context.UpdateAccessState(*geometry_info->instance_data, SYNC_ACCELERATION_STRUCTURE_BUILD_SHADER_READ,
                                          geometry_info->instance_range, instance_tag_ex);
            }
        }
    }
}

bool SyncValidator::PreCallValidateCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer,
                                                                   const VkCopyAccelerationStructureInfoKHR *pInfo,
                                                                   const ErrorObject &error_obj) const {
    bool skip = false;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &context = *cb_context.GetCurrentAccessContext();

    const Location info_loc = error_obj.location.dot(Field::pInfo);

    if (const auto src_accel = Get<vvl::AccelerationStructureKHR>(pInfo->src)) {
        const AccessRange range = MakeRange(src_accel->GetOffset(), src_accel->GetSize());
        auto hazard =
            context.DetectHazard(*src_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_COPY_ACCELERATION_STRUCTURE_READ, range);
        if (hazard.IsHazard()) {
            const LogObjectList objlist(cb_state->Handle(), src_accel->buffer_state->Handle(), src_accel->Handle());
            const std::string resource_description = FormatHandle(src_accel->buffer_state->VkHandle());
            const std::string error = error_messages_.AccelerationStructureError(
                hazard, cb_context, error_obj.location.function, resource_description, range, pInfo->src, info_loc.dot(Field::src));
            skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
        }
    }
    if (const auto dst_accel = Get<vvl::AccelerationStructureKHR>(pInfo->dst)) {
        const AccessRange range = MakeRange(dst_accel->GetOffset(), dst_accel->GetSize());
        auto hazard =
            context.DetectHazard(*dst_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_COPY_ACCELERATION_STRUCTURE_WRITE, range);
        if (hazard.IsHazard()) {
            const LogObjectList objlist(cb_state->Handle(), dst_accel->buffer_state->Handle(), dst_accel->Handle());
            const std::string resource_description = FormatHandle(dst_accel->buffer_state->VkHandle());
            const std::string error = error_messages_.AccelerationStructureError(
                hazard, cb_context, error_obj.location.function, resource_description, range, pInfo->dst, info_loc.dot(Field::dst));
            skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
        }
    }
    return skip;
}

void SyncValidator::PostCallRecordCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer,
                                                                  const VkCopyAccelerationStructureInfoKHR *pInfo,
                                                                  const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &context = *cb_context.GetCurrentAccessContext();

    const ResourceUsageTag tag = cb_context.NextCommandTag(record_obj.location.function);

    if (const auto src_accel = Get<vvl::AccelerationStructureKHR>(pInfo->src)) {
        const AccessRange range = MakeRange(src_accel->GetOffset(), src_accel->GetSize());
        const ResourceUsageTagEx tag_ex = cb_context.AddCommandHandle(tag, src_accel->buffer_state->Handle());
        context.UpdateAccessState(*src_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_COPY_ACCELERATION_STRUCTURE_READ, range,
                                  tag_ex);
    }
    if (const auto dst_accel = Get<vvl::AccelerationStructureKHR>(pInfo->dst)) {
        const AccessRange range = MakeRange(dst_accel->GetOffset(), dst_accel->GetSize());
        const ResourceUsageTagEx tag_ex = cb_context.AddCommandHandle(tag, dst_accel->buffer_state->Handle());
        context.UpdateAccessState(*dst_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_COPY_ACCELERATION_STRUCTURE_WRITE, range,
                                  tag_ex);
    }
}

bool SyncValidator::PreCallValidateCmdCopyAccelerationStructureToMemoryKHR(VkCommandBuffer commandBuffer,
                                                                           const VkCopyAccelerationStructureToMemoryInfoKHR *pInfo,
                                                                           const ErrorObject &error_obj) const {
    bool skip = false;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &context = *cb_context.GetCurrentAccessContext();

    const Location info_loc = error_obj.location.dot(Field::pInfo);

    if (const auto src_accel = Get<vvl::AccelerationStructureKHR>(pInfo->src)) {
        const AccessRange range = MakeRange(src_accel->GetOffset(), src_accel->GetSize());
        auto hazard =
            context.DetectHazard(*src_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_COPY_ACCELERATION_STRUCTURE_READ, range);
        if (hazard.IsHazard()) {
            const LogObjectList objlist(cb_state->Handle(), src_accel->buffer_state->Handle(), src_accel->Handle());
            const std::string resource_description = FormatHandle(src_accel->buffer_state->VkHandle());
            const std::string error = error_messages_.AccelerationStructureError(
                hazard, cb_context, error_obj.location.function, resource_description, range, pInfo->src, info_loc.dot(Field::src));
            skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
        }
    }

    // NOTE: do not validate src_buffer. This requires recording query and then waiting for it after submit.
    // Currently syncval does not support this but even if support is available this affects application:
    // it flushes entire GPU frame and it also affects app scheduling behavior (CPU and GPU frames do not overlap
    // anymore, and this can hide resource scheduling issues). Such submit-wait-validation can be an optional feature.

    return skip;
}

void SyncValidator::PostCallRecordCmdCopyAccelerationStructureToMemoryKHR(VkCommandBuffer commandBuffer,
                                                                          const VkCopyAccelerationStructureToMemoryInfoKHR *pInfo,
                                                                          const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &context = *cb_context.GetCurrentAccessContext();

    const ResourceUsageTag tag = cb_context.NextCommandTag(record_obj.location.function);

    if (const auto src_accel = Get<vvl::AccelerationStructureKHR>(pInfo->src)) {
        const AccessRange range = MakeRange(src_accel->GetOffset(), src_accel->GetSize());
        const ResourceUsageTagEx tag_ex = cb_context.AddCommandHandle(tag, src_accel->buffer_state->Handle());
        context.UpdateAccessState(*src_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_COPY_ACCELERATION_STRUCTURE_READ, range,
                                  tag_ex);
    }
}

bool SyncValidator::PreCallValidateCmdCopyMemoryToAccelerationStructureKHR(VkCommandBuffer commandBuffer,
                                                                           const VkCopyMemoryToAccelerationStructureInfoKHR *pInfo,
                                                                           const ErrorObject &error_obj) const {
    bool skip = false;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &context = *cb_context.GetCurrentAccessContext();

    const Location info_loc = error_obj.location.dot(Field::pInfo);

    if (const auto dst_accel = Get<vvl::AccelerationStructureKHR>(pInfo->dst)) {
        const AccessRange range = MakeRange(dst_accel->GetOffset(), dst_accel->GetSize());
        auto hazard =
            context.DetectHazard(*dst_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_COPY_ACCELERATION_STRUCTURE_WRITE, range);
        if (hazard.IsHazard()) {
            const LogObjectList objlist(cb_state->Handle(), dst_accel->buffer_state->Handle(), dst_accel->Handle());
            const std::string resource_description = FormatHandle(dst_accel->buffer_state->VkHandle());
            const std::string error = error_messages_.AccelerationStructureError(
                hazard, cb_context, error_obj.location.function, resource_description, range, pInfo->dst, info_loc.dot(Field::dst));
            skip |= SyncError(hazard.Hazard(), objlist, error_obj.location, error);
        }
    }

    // NOTE: do not validate src_buffer. This requires recording query and then waiting for it after submit.
    // Currently syncval does not support this but even if support is available this affects application:
    // it flushes entire GPU frame and it also affects app scheduling behavior (CPU and GPU frames do not overlap
    // anymore, and this can hide resource scheduling issues). Such submit-wait-validation can be an optional feature.

    return skip;
}

void SyncValidator::PostCallRecordCmdCopyMemoryToAccelerationStructureKHR(VkCommandBuffer commandBuffer,
                                                                          const VkCopyMemoryToAccelerationStructureInfoKHR *pInfo,
                                                                          const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &context = *cb_context.GetCurrentAccessContext();

    const ResourceUsageTag tag = cb_context.NextCommandTag(record_obj.location.function);

    if (const auto dst_accel = Get<vvl::AccelerationStructureKHR>(pInfo->dst)) {
        const AccessRange range = MakeRange(dst_accel->GetOffset(), dst_accel->GetSize());
        const ResourceUsageTagEx tag_ex = cb_context.AddCommandHandle(tag, dst_accel->buffer_state->Handle());
        context.UpdateAccessState(*dst_accel->buffer_state, SYNC_ACCELERATION_STRUCTURE_COPY_ACCELERATION_STRUCTURE_WRITE, range,
                                  tag_ex);
    }
}

bool SyncValidator::PreCallValidateCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
                                                   const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
                                                   const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
                                                   const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
                                                   const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
                                                   uint32_t width, uint32_t height, uint32_t depth,
                                                   const ErrorObject &error_obj) const {
    bool skip = false;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);

    skip |= cb_context.ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, error_obj.location);
    return skip;
}

void SyncValidator::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
                                                  const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
                                                  const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
                                                  const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
                                                  const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
                                                  uint32_t width, uint32_t height, uint32_t depth, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);

    const ResourceUsageTag tag = cb_context.NextCommandTag(record_obj.location.function);
    cb_context.RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, tag);
}

bool SyncValidator::PreCallValidateCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
                                                           const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
                                                           const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
                                                           const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
                                                           const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
                                                           VkDeviceAddress indirectDeviceAddress,
                                                           const ErrorObject &error_obj) const {
    bool skip = false;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &access_context = *cb_context.GetCurrentAccessContext();

    skip |= cb_context.ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, error_obj.location);

    if (const vvl::Buffer *indirect_buffer = GetSingleBufferFromDeviceAddress(*device_state, indirectDeviceAddress)) {
        skip |= ValidateIndirectBuffer(cb_context, access_context, sizeof(VkTraceRaysIndirectCommandKHR),
                                       indirect_buffer->VkHandle(), 0, 1, 0, error_obj.location);
    }
    return skip;
}

void SyncValidator::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
                                                          const VkStridedDeviceAddressRegionKHR *pRaygenShaderBindingTable,
                                                          const VkStridedDeviceAddressRegionKHR *pMissShaderBindingTable,
                                                          const VkStridedDeviceAddressRegionKHR *pHitShaderBindingTable,
                                                          const VkStridedDeviceAddressRegionKHR *pCallableShaderBindingTable,
                                                          VkDeviceAddress indirectDeviceAddress, const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);

    const ResourceUsageTag tag = cb_context.NextCommandTag(record_obj.location.function);
    cb_context.RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, tag);

    if (const vvl::Buffer *indirect_buffer = GetSingleBufferFromDeviceAddress(*device_state, indirectDeviceAddress)) {
        RecordIndirectBuffer(cb_context, tag, sizeof(VkTraceRaysIndirectCommandKHR), indirect_buffer->VkHandle(), 0, 1, 0);
    }
}

bool SyncValidator::PreCallValidateCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress,
                                                            const ErrorObject &error_obj) const {
    bool skip = false;
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN_SKIP(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);
    auto &access_context = *cb_context.GetCurrentAccessContext();

    skip |= cb_context.ValidateDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, error_obj.location);

    if (const vvl::Buffer *indirect_buffer = GetSingleBufferFromDeviceAddress(*device_state, indirectDeviceAddress)) {
        skip |= ValidateIndirectBuffer(cb_context, access_context, sizeof(VkTraceRaysIndirectCommand2KHR),
                                       indirect_buffer->VkHandle(), 0, 1, 0, error_obj.location);
    }
    return skip;
}

void SyncValidator::PostCallRecordCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress,
                                                           const RecordObject &record_obj) {
    auto cb_state = Get<vvl::CommandBuffer>(commandBuffer);
    ASSERT_AND_RETURN(cb_state);
    auto &cb_context = *GetAccessContext(*cb_state);

    const ResourceUsageTag tag = cb_context.NextCommandTag(record_obj.location.function);
    cb_context.RecordDispatchDrawDescriptorSet(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, tag);

    if (const vvl::Buffer *indirect_buffer = GetSingleBufferFromDeviceAddress(*device_state, indirectDeviceAddress)) {
        RecordIndirectBuffer(cb_context, tag, sizeof(VkTraceRaysIndirectCommand2KHR), indirect_buffer->VkHandle(), 0, 1, 0);
    }
}

}  // namespace syncval
