/*
 * 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 <vulkan/utility/vk_format_utils.h>
#include "sync/sync_command_buffer.h"
#include "error_message/error_location.h"
#include "sync/sync_image.h"
#include "sync/sync_op.h"
#include "sync/sync_reporting.h"
#include "sync/sync_validation.h"
#include "state_tracker/descriptor_sets.h"
#include "state_tracker/image_state.h"
#include "state_tracker/buffer_state.h"
#include "state_tracker/event_state.h"
#include "state_tracker/ray_tracing_state.h"
#include "state_tracker/render_pass_state.h"
#include "state_tracker/shader_module.h"
#include "state_tracker/pipeline_state.h"
#include "utils/image_utils.h"
#include "utils/math_utils.h"
#include "utils/text_utils.h"

namespace syncval {

constexpr VkImageAspectFlags kColorAspects =
    VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT;

struct ShaderStageAccesses {
    SyncAccessIndex sampled_read;
    SyncAccessIndex storage_read;
    SyncAccessIndex storage_write;
    SyncAccessIndex uniform_read;
    SyncAccessIndex acceleration_structure_read;
};

// TODO: generate me
static ShaderStageAccesses GetShaderStageAccesses(VkShaderStageFlagBits shader_stage) {
    static const vvl::unordered_map<VkShaderStageFlagBits, ShaderStageAccesses> map = {
        // clang-format off
        {VK_SHADER_STAGE_VERTEX_BIT, {
            SYNC_VERTEX_SHADER_SHADER_SAMPLED_READ,
            SYNC_VERTEX_SHADER_SHADER_STORAGE_READ,
            SYNC_VERTEX_SHADER_SHADER_STORAGE_WRITE,
            SYNC_VERTEX_SHADER_UNIFORM_READ,
            SYNC_VERTEX_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, {
            SYNC_TESSELLATION_CONTROL_SHADER_SHADER_SAMPLED_READ,
            SYNC_TESSELLATION_CONTROL_SHADER_SHADER_STORAGE_READ,
            SYNC_TESSELLATION_CONTROL_SHADER_SHADER_STORAGE_WRITE,
            SYNC_TESSELLATION_CONTROL_SHADER_UNIFORM_READ,
            SYNC_TESSELLATION_CONTROL_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, {
            SYNC_TESSELLATION_EVALUATION_SHADER_SHADER_SAMPLED_READ,
            SYNC_TESSELLATION_EVALUATION_SHADER_SHADER_STORAGE_READ,
            SYNC_TESSELLATION_EVALUATION_SHADER_SHADER_STORAGE_WRITE,
            SYNC_TESSELLATION_EVALUATION_SHADER_UNIFORM_READ,
            SYNC_TESSELLATION_EVALUATION_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_GEOMETRY_BIT, {
            SYNC_GEOMETRY_SHADER_SHADER_SAMPLED_READ,
            SYNC_GEOMETRY_SHADER_SHADER_STORAGE_READ,
            SYNC_GEOMETRY_SHADER_SHADER_STORAGE_WRITE,
            SYNC_GEOMETRY_SHADER_UNIFORM_READ,
            SYNC_GEOMETRY_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_FRAGMENT_BIT, {
            SYNC_FRAGMENT_SHADER_SHADER_SAMPLED_READ,
            SYNC_FRAGMENT_SHADER_SHADER_STORAGE_READ,
            SYNC_FRAGMENT_SHADER_SHADER_STORAGE_WRITE,
            SYNC_FRAGMENT_SHADER_UNIFORM_READ,
            SYNC_FRAGMENT_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_COMPUTE_BIT, {
            SYNC_COMPUTE_SHADER_SHADER_SAMPLED_READ,
            SYNC_COMPUTE_SHADER_SHADER_STORAGE_READ,
            SYNC_COMPUTE_SHADER_SHADER_STORAGE_WRITE,
            SYNC_COMPUTE_SHADER_UNIFORM_READ,
            SYNC_COMPUTE_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_RAYGEN_BIT_KHR, {
            SYNC_RAY_TRACING_SHADER_SHADER_SAMPLED_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_WRITE,
            SYNC_RAY_TRACING_SHADER_UNIFORM_READ,
            SYNC_RAY_TRACING_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_ANY_HIT_BIT_KHR, {
            SYNC_RAY_TRACING_SHADER_SHADER_SAMPLED_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_WRITE,
            SYNC_RAY_TRACING_SHADER_UNIFORM_READ,
            SYNC_RAY_TRACING_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, {
            SYNC_RAY_TRACING_SHADER_SHADER_SAMPLED_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_WRITE,
            SYNC_RAY_TRACING_SHADER_UNIFORM_READ,
            SYNC_RAY_TRACING_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_MISS_BIT_KHR, {
            SYNC_RAY_TRACING_SHADER_SHADER_SAMPLED_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_WRITE,
            SYNC_RAY_TRACING_SHADER_UNIFORM_READ,
            SYNC_RAY_TRACING_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_INTERSECTION_BIT_KHR, {
            SYNC_RAY_TRACING_SHADER_SHADER_SAMPLED_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_WRITE,
            SYNC_RAY_TRACING_SHADER_UNIFORM_READ,
            SYNC_RAY_TRACING_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_CALLABLE_BIT_KHR, {
            SYNC_RAY_TRACING_SHADER_SHADER_SAMPLED_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_READ,
            SYNC_RAY_TRACING_SHADER_SHADER_STORAGE_WRITE,
            SYNC_RAY_TRACING_SHADER_UNIFORM_READ,
            SYNC_RAY_TRACING_SHADER_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_TASK_BIT_EXT, {
            SYNC_TASK_SHADER_EXT_SHADER_SAMPLED_READ,
            SYNC_TASK_SHADER_EXT_SHADER_STORAGE_READ,
            SYNC_TASK_SHADER_EXT_SHADER_STORAGE_WRITE,
            SYNC_TASK_SHADER_EXT_UNIFORM_READ,
            SYNC_TASK_SHADER_EXT_ACCELERATION_STRUCTURE_READ,
        }},
        {VK_SHADER_STAGE_MESH_BIT_EXT, {
            SYNC_MESH_SHADER_EXT_SHADER_SAMPLED_READ,
            SYNC_MESH_SHADER_EXT_SHADER_STORAGE_READ,
            SYNC_MESH_SHADER_EXT_SHADER_STORAGE_WRITE,
            SYNC_MESH_SHADER_EXT_UNIFORM_READ,
            SYNC_MESH_SHADER_EXT_ACCELERATION_STRUCTURE_READ,
        }},
        // clang-format on
    };
    auto it = map.find(shader_stage);
    assert(it != map.end());
    return it->second;
}

static AccessRange MakeRangeForVertexData(VkDeviceSize offset, uint32_t first_vertex, uint32_t vertex_count,
                                          const VertexBindingState& vertex_binding) {
    uint32_t element_size = 0;
    for (const auto& [_, vertex_attrib] : vertex_binding.locations) {
        element_size = std::max(element_size, vertex_attrib.desc.offset + GetVertexInputFormatSize(vertex_attrib.desc.format));
    }
    const VkDeviceSize range_start = offset + (first_vertex * vertex_binding.desc.stride);
    VkDeviceSize range_size = 0;
    if (vertex_count > 0) {
        // Take into account stride between elements but not after the last element.
        range_size = (vertex_count - 1) * vertex_binding.desc.stride + element_size;
    }
    return MakeRange(range_start, range_size);
}

static AccessRange MakeRangeForIndexData(VkDeviceSize offset, uint32_t first_index, uint32_t index_count, uint32_t index_size) {
    const VkDeviceSize range_start = offset + (first_index * index_size);
    const VkDeviceSize range_size = index_count * index_size;
    return MakeRange(range_start, range_size);
}

static AccessRange MakeRange(const vvl::BufferView& buf_view_state) {
    return MakeRange(*buf_view_state.buffer_state.get(), buf_view_state.create_info.offset, buf_view_state.create_info.range);
}

static SyncAccessIndex GetSyncStageAccessIndexsByDescriptorSet(VkDescriptorType descriptor_type,
                                                               const spirv::ResourceInterfaceVariable& variable,
                                                               VkShaderStageFlagBits stage_flag) {
    if (!variable.IsAccessed()) {
        return SYNC_ACCESS_INDEX_NONE;
    }
    if (descriptor_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) {
        assert(stage_flag == VK_SHADER_STAGE_FRAGMENT_BIT);
        return SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ;
    }
    const auto stage_accesses = GetShaderStageAccesses(stage_flag);

    if (descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
        return stage_accesses.uniform_read;
    }
    if (descriptor_type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR ||
        descriptor_type == VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV ||
        descriptor_type == VK_DESCRIPTOR_TYPE_PARTITIONED_ACCELERATION_STRUCTURE_NV) {
        return stage_accesses.acceleration_structure_read;
    }

    // If the desriptorSet is writable, we don't need to care SHADER_READ. SHADER_WRITE is enough.
    // Because if write hazard happens, read hazard might or might not happen.
    // But if write hazard doesn't happen, read hazard is impossible to happen.
    if (variable.IsWrittenTo()) {
        return stage_accesses.storage_write;
    } else if (descriptor_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
               descriptor_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
               descriptor_type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) {
        return stage_accesses.sampled_read;
    } else {
        if (variable.IsImage() && !variable.IsImageReadFrom()) {
            // only image descriptor was accessed, not the image data
            return SYNC_ACCESS_INDEX_NONE;
        }
        return stage_accesses.storage_read;
    }
}

static void UpdateImageAccessState(AccessContext& access_context, const vvl::Image& image, SyncAccessIndex current_usage,
                                   const VkImageSubresourceRange& subresource_range, const ResourceUsageTag& tag) {
    const auto& sub_state = SubState(image);
    ImageRangeGen range_gen = sub_state.MakeImageRangeGen(subresource_range, false);
    access_context.UpdateAccessState(range_gen, current_usage, ResourceUsageTagEx{tag});
}

static void UpdateImageAccessState(AccessContext& access_context, const vvl::Image& image, SyncAccessIndex current_usage,
                                   const VkImageSubresourceRange& subresource_range, const VkOffset3D& offset,
                                   const VkExtent3D& extent, ResourceUsageTagEx tag_ex) {
    const auto& sub_state = SubState(image);
    ImageRangeGen range_gen = sub_state.MakeImageRangeGen(subresource_range, offset, extent, false);
    access_context.UpdateAccessState(range_gen, current_usage, tag_ex);
}

static void UpdateVideoAccessState(AccessContext& access_context, const vvl::VideoSession& vs_state,
                                   const vvl::VideoPictureResource& resource, SyncAccessIndex current_usage, ResourceUsageTag tag) {
    const auto image = static_cast<const vvl::Image*>(resource.image_state.get());
    const auto offset = resource.GetEffectiveImageOffset(vs_state);
    const auto extent = resource.GetEffectiveImageExtent(vs_state);
    const auto& sub_state = SubState(*image);
    ImageRangeGen range_gen(sub_state.MakeImageRangeGen(resource.range, offset, extent, false));
    access_context.UpdateAccessState(range_gen, current_usage, ResourceUsageTagEx{tag});
}

CommandExecutionContext::CommandExecutionContext(const SyncValidator& sync_validator, VkQueueFlags queue_flags)
    : sync_state_(sync_validator), error_messages_(sync_validator.error_messages_), queue_flags_(queue_flags) {}

bool CommandExecutionContext::ValidForSyncOps() const {
    const bool valid = GetCurrentEventsContext() && GetCurrentAccessContext();
    assert(valid);
    return valid;
}

CommandBufferAccessContext::CommandBufferAccessContext(const SyncValidator& sync_validator, VkQueueFlags queue_flags)
    : CommandExecutionContext(sync_validator, queue_flags),
      cb_state_(),
      access_log_(std::make_shared<AccessLog>()),
      cbs_referenced_(std::make_shared<CommandBufferSet>()),
      command_number_(0),
      reset_count_(0),
      cb_access_context_(sync_validator),
      current_context_(&cb_access_context_),
      events_context_(),
      render_pass_contexts_(),
      current_renderpass_context_(),
      sync_ops_() {}

CommandBufferAccessContext::CommandBufferAccessContext(SyncValidator& sync_validator, vvl::CommandBuffer* cb_state)
    : CommandBufferAccessContext(sync_validator, cb_state->GetQueueFlags()) {
    cb_state_ = cb_state;
    sync_state_.stats.AddCommandBufferContext();
}

// NOTE: Make sure the proxy doesn't outlive from, as the proxy is pointing directly to access contexts owned by from.
CommandBufferAccessContext::CommandBufferAccessContext(const CommandBufferAccessContext& from, AsProxyContext dummy)
    : CommandBufferAccessContext(from.sync_state_, from.cb_state_->GetQueueFlags()) {
    // Copy only the needed fields out of from for a temporary, proxy command buffer context
    cb_state_ = from.cb_state_;
    access_log_ = std::make_shared<AccessLog>(*from.access_log_);  // potentially large, but no choice given tagging lookup.
    command_number_ = from.command_number_;
    reset_count_ = from.reset_count_;

    handles_ = from.handles_;
    sync_state_.stats.AddHandleRecord((uint32_t)from.handles_.size());

    const auto* from_context = from.GetCurrentAccessContext();
    assert(from_context);

    // Construct a fully resolved single access context out of from
    cb_access_context_.ResolveFromContext(*from_context);
    // The proxy has flatten the current render pass context (if any), but the async contexts are needed for hazard detection
    cb_access_context_.ImportAsyncContexts(*from_context);

    events_context_ = from.events_context_;

    // We don't want to copy the full render_pass_context_ history just for the proxy.
    sync_state_.stats.AddCommandBufferContext();
}

CommandBufferAccessContext::~CommandBufferAccessContext() {
    sync_state_.stats.RemoveCommandBufferContext();
    sync_state_.stats.RemoveHandleRecord((uint32_t)handles_.size());
}

void CommandBufferAccessContext::Reset() {
    access_log_ = std::make_shared<AccessLog>();
    cbs_referenced_ = std::make_shared<CommandBufferSet>();
    if (cb_state_) {
        cbs_referenced_->push_back(cb_state_->shared_from_this());
    }
    sync_ops_.clear();
    command_number_ = 0;
    reset_count_++;

    sync_state_.stats.RemoveHandleRecord((uint32_t)handles_.size());
    handles_.clear();

    current_command_tag_ = vvl::kNoIndex32;
    cb_access_context_.Reset();
    render_pass_contexts_.clear();
    current_context_ = &cb_access_context_;
    current_renderpass_context_ = nullptr;
    events_context_.Clear();
    dynamic_rendering_info_.reset();
}

bool CommandBufferAccessContext::ValidateBeginRendering(const ErrorObject& error_obj, BeginRenderingCmdState& cmd_state) const {
    bool skip = false;
    const DynamicRenderingInfo& info = cmd_state.GetRenderingInfo();

    // Load operations do not happen when resuming
    if (info.info.flags & VK_RENDERING_RESUMING_BIT) {
        return skip;
    }

    // Need to hazard detect load operations vs. the attachment views
    for (size_t i = 0; i < info.attachments.size(); i++) {
        const auto& attachment = info.attachments[i];
        const SyncAccessIndex load_index = attachment.GetLoadUsage();
        if (load_index == SYNC_ACCESS_INDEX_NONE) {
            continue;
        }

        const AttachmentAccess attachment_access = GetAttachmentAccess(attachment.GetOrdering(), AttachmentAccessType::LoadOp);
        ImageRangeGen range_gen = attachment.GetRangeGen(info.info.viewMask);
        const HazardResult hazard = GetCurrentAccessContext()->DetectAttachmentHazard(range_gen, load_index, attachment_access);
        if (hazard.IsHazard()) {
            LogObjectList objlist(cb_state_->Handle(), attachment.view->Handle());

            std::ostringstream ss;
            ss << vvl::String(vvl::Field::pRenderingInfo) << ".";
            ss << attachment.GetLocation(error_obj.location, uint32_t(i)).Fields();
            ss << " (" << sync_state_.FormatHandle(attachment.view->Handle());
            ss << ", loadOp " << string_VkAttachmentLoadOp(attachment.info.loadOp) << ")";
            std::string resource_description = ss.str();

            const std::string error = sync_state_.error_messages_.BeginRenderingError(hazard, *this, error_obj.location.function,
                                                                                      resource_description, attachment.info.loadOp);
            skip |= sync_state_.SyncError(hazard.Hazard(), objlist, error_obj.location.function, error);
            if (skip) {
                break;
            }
        }
    }
    return skip;
}

void CommandBufferAccessContext::RecordBeginRendering(BeginRenderingCmdState& cmd_state, const Location& loc) {
    const auto tag = NextCommandTag(loc.function);

    const DynamicRenderingInfo& info = cmd_state.GetRenderingInfo();
    if ((info.info.flags & VK_RENDERING_RESUMING_BIT) == 0) {
        for (size_t i = 0; i < info.attachments.size(); i++) {
            const DynamicRenderingInfo::Attachment& attachment = info.attachments[i];
            const SyncAccessIndex load_index = attachment.GetLoadUsage();
            if (load_index == SYNC_ACCESS_INDEX_NONE) {
                continue;
            }
            ImageRangeGen range_gen = attachment.GetRangeGen(info.info.viewMask);
            const AttachmentAccess attachment_access = GetAttachmentAccess(attachment.GetOrdering(), AttachmentAccessType::LoadOp);
            GetCurrentAccessContext()->UpdateAttachmentAccessState(range_gen, load_index, attachment_access,
                                                                   ResourceUsageTagEx{tag});
        }
    }
    dynamic_rendering_info_ = std::move(cmd_state.info);
}

bool CommandBufferAccessContext::ValidateEndRendering(const ErrorObject& error_obj) const {
    bool skip = false;

    // Only validate resolve and store if not suspending (as specified by BeginRendering)
    if (!dynamic_rendering_info_ || (dynamic_rendering_info_->info.flags & VK_RENDERING_SUSPENDING_BIT) != 0) {
        return skip;
    }

    for (uint32_t i = 0; i < (uint32_t)dynamic_rendering_info_->attachments.size(); i++) {
        const auto& attachment = dynamic_rendering_info_->attachments[i];

        auto attachment_description = [this, &error_obj, &attachment, i](const auto& view, std::ostringstream& ss) {
            ss << vvl::String(vvl::Field::pRenderingInfo) << ".";
            ss << attachment.GetLocation(error_obj.location, uint32_t(i)).Fields();
            ss << " (" << sync_state_.FormatHandle(view->Handle());
        };

        // The logic about whether to resolve is embedded in the Attachment constructor
        if (attachment.resolve_gen) {
            const bool is_color = attachment.type == AttachmentType::kColor;
            const SyncOrdering kResolveOrder = is_color ? kColorResolveOrder : kDepthStencilResolveOrder;

            const AttachmentAccess resolve_read_access = GetAttachmentAccess(kResolveOrder, AttachmentAccessType::ResolveRead);
            ImageRangeGen view_gen = attachment.GetRangeGen(dynamic_rendering_info_->info.viewMask);
            HazardResult hazard = current_context_->DetectAttachmentHazard(view_gen, kResolveRead, resolve_read_access);
            if (hazard.IsHazard()) {
                LogObjectList objlist(cb_state_->Handle(), attachment.view->Handle());

                std::ostringstream ss;
                attachment_description(attachment.view, ss);
                ss << ", resolveMode " << string_VkResolveModeFlagBits(attachment.info.resolveMode) << ")";
                const std::string resource_description = ss.str();

                const std::string error = sync_state_.error_messages_.EndRenderingResolveError(
                    hazard, *this, error_obj.location.function, resource_description, attachment.info.resolveMode, false);
                skip |= sync_state_.SyncError(hazard.Hazard(), objlist, error_obj.location.function, error);
                if (skip) {
                    break;
                }
            }

            const AttachmentAccess resolve_write_access = GetAttachmentAccess(kResolveOrder, AttachmentAccessType::ResolveWrite);
            ImageRangeGen resolve_gen = *attachment.resolve_gen;
            hazard = current_context_->DetectAttachmentHazard(resolve_gen, kResolveWrite, resolve_write_access);
            if (hazard.IsHazard()) {
                LogObjectList objlist(cb_state_->Handle(), attachment.resolve_view->Handle());

                std::ostringstream ss;
                attachment_description(attachment.resolve_view, ss);
                ss << ", resolveMode " << string_VkResolveModeFlagBits(attachment.info.resolveMode) << ")";
                const std::string resource_description = ss.str();

                const std::string error = sync_state_.error_messages_.EndRenderingResolveError(
                    hazard, *this, error_obj.location.function, resource_description, attachment.info.resolveMode, true);
                skip |= sync_state_.SyncError(hazard.Hazard(), objlist, error_obj.location.function, error);
                if (skip) {
                    break;
                }
            }
        }

        const SyncAccessIndex store_access = attachment.GetStoreUsage();
        if (store_access != SYNC_ACCESS_INDEX_NONE) {
            const AttachmentAccess attachment_access = GetAttachmentAccess(kStoreOrder, AttachmentAccessType::StoreOp);
            ImageRangeGen view_gen = attachment.GetRangeGen(dynamic_rendering_info_->info.viewMask);

            HazardResult hazard = current_context_->DetectAttachmentHazard(view_gen, store_access, attachment_access);
            if (hazard.IsHazard()) {
                LogObjectList objlist(cb_state_->Handle(), attachment.view->Handle());

                std::ostringstream ss;
                attachment_description(attachment.view, ss);
                ss << ", storeOp " << string_VkAttachmentStoreOp(attachment.info.storeOp) << ")";
                const std::string resource_description = ss.str();

                const std::string error = sync_state_.error_messages_.EndRenderingStoreError(
                    hazard, *this, error_obj.location.function, resource_description, attachment.info.storeOp);
                skip |= sync_state_.SyncError(hazard.Hazard(), objlist, error_obj.location.function, error);
                if (skip) {
                    break;
                }
            }
        }
    }
    return skip;
}

void CommandBufferAccessContext::RecordEndRendering(const RecordObject& record_obj) {
    if (!dynamic_rendering_info_) {
        return;
    }
    if ((dynamic_rendering_info_->info.flags & VK_RENDERING_SUSPENDING_BIT) != 0) {
        dynamic_rendering_info_.reset();
        return;
    }

    auto store_tag = NextCommandTag(record_obj.location.function, SubCommandType::kStoreOp);
    AccessContext& access_context = *GetCurrentAccessContext();

    for (const auto& attachment : dynamic_rendering_info_->attachments) {
        if (attachment.resolve_gen) {
            const bool is_color = attachment.type == AttachmentType::kColor;
            const SyncOrdering kResolveOrder = is_color ? kColorResolveOrder : kDepthStencilResolveOrder;

            const AttachmentAccess resolve_read_access = GetAttachmentAccess(kResolveOrder, AttachmentAccessType::ResolveRead);
            ImageRangeGen view_gen = attachment.GetRangeGen(dynamic_rendering_info_->info.viewMask);
            access_context.UpdateAttachmentAccessState(view_gen, kResolveRead, resolve_read_access, ResourceUsageTagEx{store_tag});

            const AttachmentAccess resolve_write_access = GetAttachmentAccess(kResolveOrder, AttachmentAccessType::ResolveWrite);
            ImageRangeGen resolve_gen = *attachment.resolve_gen;
            access_context.UpdateAttachmentAccessState(resolve_gen, kResolveWrite, resolve_write_access,
                                                       ResourceUsageTagEx{store_tag});
        }

        const SyncAccessIndex store_index = attachment.GetStoreUsage();
        if (store_index != SYNC_ACCESS_INDEX_NONE) {
            const AttachmentAccess attachment_access = GetAttachmentAccess(kStoreOrder, AttachmentAccessType::StoreOp);
            ImageRangeGen view_gen = attachment.GetRangeGen(dynamic_rendering_info_->info.viewMask);
            access_context.UpdateAttachmentAccessState(view_gen, store_index, attachment_access, ResourceUsageTagEx{store_tag});
        }
    }
    current_render_pass_instance_id_++;
    dynamic_rendering_info_.reset();
}

bool CommandBufferAccessContext::ValidateDispatchDrawDescriptorSet(VkPipelineBindPoint pipelineBindPoint,
                                                                   const Location& loc) const {
    bool skip = false;
    if (!sync_state_.syncval_settings.shader_accesses_heuristic) {
        return skip;
    }
    const auto& last_bound_state = cb_state_->lastBound[ConvertToVvlBindPoint(pipelineBindPoint)];
    const vvl::Pipeline* pipe = last_bound_state.pipeline_state;
    const std::vector<LastBound::DescriptorSetSlot>& ds_slots = last_bound_state.ds_slots;
    if (!pipe) {
        return skip;
    }

    using DescriptorClass = vvl::DescriptorClass;
    using BufferDescriptor = vvl::BufferDescriptor;
    using ImageDescriptor = vvl::ImageDescriptor;
    using TexelDescriptor = vvl::TexelDescriptor;

    for (const auto& stage_state : pipe->stage_states) {
        if (stage_state.GetStage() == VK_SHADER_STAGE_FRAGMENT_BIT && pipe->RasterizationDisabled()) {
            continue;
        } else if (!stage_state.HasSpirv()) {
            continue;
        }
        for (const auto& variable : stage_state.entrypoint->resource_interface_variables) {
            if (variable.decorations.set >= ds_slots.size()) {
                // This should be caught by Core validation, but if core checks are disabled SyncVal should not crash.
                continue;
            }
            const auto& ds_slot = ds_slots[variable.decorations.set];
            const auto* descriptor_set = ds_slot.ds_state.get();
            if (!descriptor_set) continue;
            auto binding = descriptor_set->GetBinding(variable.decorations.binding);
            if (!binding) continue;
            const auto descriptor_type = binding->type;
            SyncAccessIndex sync_index = GetSyncStageAccessIndexsByDescriptorSet(descriptor_type, variable, stage_state.GetStage());

            // Currently, validation of memory accesses based on declared descriptors can produce false-positives.
            // The shader can decide not to do such accesses, it can perform accesses with more narrow scope
            // (e.g. read access, when both reads and writes are allowed) or for an array of descriptors, not all
            // elements are accessed in the general case.
            //
            // This workaround disables validation for the descriptor array case.
            if (binding->count > 1) {
                continue;
            }

            for (uint32_t index = 0; index < binding->count; index++) {
                const auto* descriptor = binding->GetDescriptor(index);
                switch (descriptor->GetClass()) {
                    case DescriptorClass::ImageSampler:
                    case DescriptorClass::Image: {
                        if (descriptor->Invalid()) {
                            continue;
                        }

                        // NOTE: ImageSamplerDescriptor inherits from ImageDescriptor, so this cast works for both types.
                        const auto* image_descriptor = static_cast<const ImageDescriptor*>(descriptor);
                        const auto* img_view_state = image_descriptor->GetImageViewState();
                        VkImageLayout image_layout = image_descriptor->GetImageLayout();

                        if (img_view_state->is_depth_sliced) {
                            // NOTE: 2D ImageViews of VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT Images are not allowed in
                            // Descriptors, unless VK_EXT_image_2d_view_of_3d is supported, which it isn't at the moment.
                            // See: VUID 00343
                            continue;
                        }

                        HazardResult hazard;

                        if (sync_index == SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ) {
                            const VkExtent3D extent = CastTo3D(cb_state_->render_area.extent);
                            const VkOffset3D offset = CastTo3D(cb_state_->render_area.offset);
                            const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kRaster);
                            hazard = current_context_->DetectAttachmentHazard(*img_view_state, offset, extent, sync_index,
                                                                              attachment_access);
                        } else {
                            hazard = current_context_->DetectHazard(*img_view_state, sync_index);
                        }

                        if (hazard.IsHazard()) {
                            LogObjectList objlist(cb_state_->Handle(), img_view_state->Handle(), pipe->Handle());
                            const auto error = error_messages_.ImageDescriptorError(
                                hazard, *this, loc.function, sync_state_.FormatHandle(*img_view_state), *pipe,
                                variable.decorations.set, *descriptor_set, descriptor_type, variable.decorations.binding, index,
                                stage_state.GetStage(), image_layout);
                            skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc, error);
                        }
                        break;
                    }
                    case DescriptorClass::TexelBuffer: {
                        const auto* texel_descriptor = static_cast<const TexelDescriptor*>(descriptor);
                        if (texel_descriptor->Invalid()) {
                            continue;
                        }
                        const auto* buf_view_state = texel_descriptor->GetBufferViewState();
                        const auto* buf_state = buf_view_state->buffer_state.get();
                        const AccessRange range = MakeRange(*buf_view_state);
                        auto hazard = current_context_->DetectHazard(*buf_state, sync_index, range);
                        if (hazard.IsHazard()) {
                            LogObjectList objlist(cb_state_->Handle(), buf_view_state->Handle(), pipe->Handle());
                            const auto error = error_messages_.BufferDescriptorError(
                                hazard, *this, loc.function, sync_state_.FormatHandle(*buf_view_state), *pipe,
                                variable.decorations.set, *descriptor_set, descriptor_type, variable.decorations.binding, index,
                                stage_state.GetStage());
                            skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc, error);
                        }
                        break;
                    }
                    case DescriptorClass::GeneralBuffer: {
                        const auto* buffer_descriptor = static_cast<const BufferDescriptor*>(descriptor);
                        if (buffer_descriptor->Invalid()) {
                            continue;
                        }
                        VkDeviceSize offset = buffer_descriptor->GetOffset();
                        if (vvl::IsDynamicDescriptor(descriptor_type)) {
                            const uint32_t dynamic_offset_index =
                                descriptor_set->GetDynamicOffsetIndexFromBinding(binding->binding);
                            if (dynamic_offset_index >= ds_slot.dynamic_offsets.size()) {
                                continue;  // core validation error
                            }
                            offset += ds_slot.dynamic_offsets[dynamic_offset_index];
                        }
                        const auto* buf_state = buffer_descriptor->GetBufferState();
                        const AccessRange range = MakeRange(*buf_state, offset, buffer_descriptor->GetRange());
                        auto hazard = current_context_->DetectHazard(*buf_state, sync_index, range);
                        if (hazard.IsHazard()) {
                            LogObjectList objlist(cb_state_->Handle(), buf_state->Handle(), pipe->Handle());
                            const auto error = error_messages_.BufferDescriptorError(
                                hazard, *this, loc.function, sync_state_.FormatHandle(*buf_state), *pipe, variable.decorations.set,
                                *descriptor_set, descriptor_type, variable.decorations.binding, index, stage_state.GetStage());
                            skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc, error);
                        }
                        break;
                    }
                    case DescriptorClass::AccelerationStructure: {
                        const auto* accel_descriptor = static_cast<const vvl::AccelerationStructureDescriptor*>(descriptor);
                        if (accel_descriptor->Invalid()) {
                            continue;
                        }
                        const vvl::AccelerationStructureKHR* accel = accel_descriptor->GetAccelerationStructureStateKHR();
                        if (!accel) {
                            continue;
                        }
                        if (const vvl::BufferAndOffset as_buffer = accel->GetFirstValidBuffer(cb_state_->dev_data)) {
                            const AccessRange range = MakeRange(*as_buffer.state, as_buffer.offset, accel->GetSize());
                            auto hazard = current_context_->DetectHazard(*as_buffer.state, sync_index, range);
                            if (hazard.IsHazard()) {
                                LogObjectList objlist(cb_state_->Handle(), as_buffer.state->Handle(), pipe->Handle());
                                const std::string resource_description = sync_state_.FormatHandle(accel->Handle());
                                const std::string error = error_messages_.AccelerationStructureDescriptorError(
                                    hazard, *this, loc.function, resource_description, *pipe, variable.decorations.set,
                                    *descriptor_set, descriptor_type, variable.decorations.binding, index, stage_state.GetStage());
                                skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc, error);
                            }
                        }
                        break;
                    }
                    // TODO: INLINE_UNIFORM_BLOCK_EXT
                    default:
                        break;
                }
            }
        }
    }
    return skip;
}

// TODO: Record structure repeats Validate. Unify this code, it was the source of bugs few times already.
void CommandBufferAccessContext::RecordDispatchDrawDescriptorSet(VkPipelineBindPoint pipelineBindPoint,
                                                                 const ResourceUsageTag tag) {
    if (!sync_state_.syncval_settings.shader_accesses_heuristic) {
        return;
    }

    const auto& last_bound_state = cb_state_->lastBound[ConvertToVvlBindPoint(pipelineBindPoint)];
    const vvl::Pipeline* pipe = last_bound_state.pipeline_state;
    const std::vector<LastBound::DescriptorSetSlot>& ds_slots = last_bound_state.ds_slots;
    if (!pipe) {
        return;
    }

    using DescriptorClass = vvl::DescriptorClass;
    using BufferDescriptor = vvl::BufferDescriptor;
    using ImageDescriptor = vvl::ImageDescriptor;
    using TexelDescriptor = vvl::TexelDescriptor;

    for (const auto& stage_state : pipe->stage_states) {
        if (stage_state.GetStage() == VK_SHADER_STAGE_FRAGMENT_BIT && pipe->RasterizationDisabled()) {
            continue;
        } else if (!stage_state.HasSpirv()) {
            continue;
        }
        for (const auto& variable : stage_state.entrypoint->resource_interface_variables) {
            if (variable.decorations.set >= ds_slots.size()) {
                // This should be caught by Core validation, but if core checks are disabled SyncVal should not crash.
                continue;
            }
            const auto& ds_slot = ds_slots[variable.decorations.set];
            const auto* descriptor_set = ds_slot.ds_state.get();
            if (!descriptor_set) continue;
            auto binding = descriptor_set->GetBinding(variable.decorations.binding);
            if (!binding) continue;
            const auto descriptor_type = binding->type;
            SyncAccessIndex sync_index = GetSyncStageAccessIndexsByDescriptorSet(descriptor_type, variable, stage_state.GetStage());

            // Do not update state for descriptor array (the same as in Validate function).
            if (binding->count > 1) {
                continue;
            }

            for (uint32_t i = 0; i < binding->count; i++) {
                const auto* descriptor = binding->GetDescriptor(i);
                switch (descriptor->GetClass()) {
                    case DescriptorClass::ImageSampler:
                    case DescriptorClass::Image: {
                        // NOTE: ImageSamplerDescriptor inherits from ImageDescriptor, so this cast works for both types.
                        const auto* image_descriptor = static_cast<const ImageDescriptor*>(descriptor);
                        if (image_descriptor->Invalid()) {
                            continue;
                        }
                        const auto* img_view_state = image_descriptor->GetImageViewState();
                        if (img_view_state->is_depth_sliced) {
                            // NOTE: 2D ImageViews of VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT Images are not allowed in
                            // Descriptors, unless VK_EXT_image_2d_view_of_3d is supported, which it isn't at the moment.
                            // See: VUID 00343
                            continue;
                        }
                        const ResourceUsageTagEx tag_ex = AddCommandHandle(tag, img_view_state->image_state->Handle());
                        if (sync_index == SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ) {
                            const VkExtent3D extent = CastTo3D(cb_state_->render_area.extent);
                            const VkOffset3D offset = CastTo3D(cb_state_->render_area.offset);
                            const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kRaster);

                            ImageRangeGen range_gen(MakeImageRangeGen(*img_view_state, offset, extent));
                            current_context_->UpdateAttachmentAccessState(range_gen, SYNC_FRAGMENT_SHADER_INPUT_ATTACHMENT_READ,
                                                                          attachment_access, tag_ex);
                        } else {
                            ImageRangeGen range_gen = MakeImageRangeGen(*img_view_state);
                            current_context_->UpdateAccessState(range_gen, sync_index, tag_ex);
                        }
                        break;
                    }
                    case DescriptorClass::TexelBuffer: {
                        const auto* texel_descriptor = static_cast<const TexelDescriptor*>(descriptor);
                        if (texel_descriptor->Invalid()) {
                            continue;
                        }
                        const auto* buf_view_state = texel_descriptor->GetBufferViewState();
                        const auto* buf_state = buf_view_state->buffer_state.get();
                        const AccessRange range = MakeRange(*buf_view_state);
                        const ResourceUsageTagEx tag_ex = AddCommandHandle(tag, buf_view_state->Handle());
                        current_context_->UpdateAccessState(*buf_state, sync_index, range, tag_ex);
                        break;
                    }
                    case DescriptorClass::GeneralBuffer: {
                        const auto* buffer_descriptor = static_cast<const BufferDescriptor*>(descriptor);
                        if (buffer_descriptor->Invalid()) {
                            continue;
                        }
                        VkDeviceSize offset = buffer_descriptor->GetOffset();
                        if (vvl::IsDynamicDescriptor(descriptor_type)) {
                            const uint32_t dynamic_offset_index =
                                descriptor_set->GetDynamicOffsetIndexFromBinding(binding->binding);
                            if (dynamic_offset_index >= ds_slot.dynamic_offsets.size()) {
                                continue;  // core validation error
                            }
                            offset += ds_slot.dynamic_offsets[dynamic_offset_index];
                        }
                        const auto* buf_state = buffer_descriptor->GetBufferState();
                        const AccessRange range = MakeRange(*buf_state, offset, buffer_descriptor->GetRange());
                        const ResourceUsageTagEx tag_ex = AddCommandHandle(tag, buf_state->Handle());
                        current_context_->UpdateAccessState(*buf_state, sync_index, range, tag_ex);
                        break;
                    }
                    case DescriptorClass::AccelerationStructure: {
                        const auto* accel_descriptor = static_cast<const vvl::AccelerationStructureDescriptor*>(descriptor);
                        if (accel_descriptor->Invalid()) {
                            continue;
                        }
                        const vvl::AccelerationStructureKHR* accel = accel_descriptor->GetAccelerationStructureStateKHR();
                        if (!accel) {
                            continue;
                        }
                        if (const vvl::BufferAndOffset as_buffer = accel->GetFirstValidBuffer(cb_state_->dev_data)) {
                            const AccessRange range = MakeRange(*as_buffer.state, as_buffer.offset, accel->GetSize());
                            const ResourceUsageTagEx tag_ex = AddCommandHandle(tag, accel->Handle());
                            current_context_->UpdateAccessState(*as_buffer.state, sync_index, range, tag_ex);
                        }
                        break;
                    }
                    // TODO: INLINE_UNIFORM_BLOCK_EXT
                    default:
                        break;
                }
            }
        }
    }
}

bool CommandBufferAccessContext::ValidateDrawVertex(uint32_t vertexCount, uint32_t firstVertex, const Location& loc) const {
    bool skip = false;
    const auto* pipe = cb_state_->GetLastBoundGraphics().pipeline_state;
    if (!pipe) {
        return skip;
    }

    const auto& binding_buffers = cb_state_->current_vertex_buffer_binding_info;
    const auto& vertex_bindings = pipe->IsDynamic(CB_DYNAMIC_STATE_VERTEX_INPUT_EXT)
                                      ? cb_state_->dynamic_state_value.vertex_bindings
                                      : pipe->vertex_input_state->bindings;

    for (const auto& [_, binding_state] : vertex_bindings) {
        const auto& binding_desc = binding_state.desc;
        if (binding_desc.inputRate != VK_VERTEX_INPUT_RATE_VERTEX) {
            // TODO: add support to determine range of instance level attributes
            continue;
        }
        if (const vvl::VertexBufferBinding* vertex_buffer = vvl::Find(binding_buffers, binding_desc.binding)) {
            // TODO - Handle https://gitlab.khronos.org/vulkan/Vulkan-ValidationLayers/-/issues/45
            const auto buf_state = sync_state_.Get<vvl::Buffer>(vertex_buffer->Buffer());
            if (!buf_state) continue;  // also skips if using nullDescriptor

            const AccessRange range =
                MakeRangeForVertexData(vertex_buffer->BufferOffset(), firstVertex, vertexCount, binding_state);
            auto hazard = current_context_->DetectHazard(*buf_state, SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ, range);
            if (hazard.IsHazard()) {
                LogObjectList objlist(cb_state_->Handle(), buf_state->Handle(), pipe->Handle());
                const std::string resource_description = "vertex " + sync_state_.FormatHandle(*buf_state);
                const auto error = error_messages_.BufferError(hazard, *this, loc.function, resource_description, range);
                skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc, error);
            }
        }
    }
    return skip;
}

void CommandBufferAccessContext::RecordDrawVertex(uint32_t vertexCount, uint32_t firstVertex, const ResourceUsageTag tag) {
    const auto* pipe = cb_state_->GetLastBoundGraphics().pipeline_state;
    if (!pipe) {
        return;
    }
    const auto& binding_buffers = cb_state_->current_vertex_buffer_binding_info;
    const auto& vertex_bindings = pipe->IsDynamic(CB_DYNAMIC_STATE_VERTEX_INPUT_EXT)
                                      ? cb_state_->dynamic_state_value.vertex_bindings
                                      : pipe->vertex_input_state->bindings;

    for (const auto& [_, binding_state] : vertex_bindings) {
        const auto& binding_desc = binding_state.desc;
        if (binding_desc.inputRate != VK_VERTEX_INPUT_RATE_VERTEX) {
            // TODO: add support to determine range of instance level attributes
            continue;
        }
        if (const auto* vertex_buffer = vvl::Find(binding_buffers, binding_desc.binding)) {
            // TODO - Handle https://gitlab.khronos.org/vulkan/Vulkan-ValidationLayers/-/issues/45
            const auto buf_state = sync_state_.Get<vvl::Buffer>(vertex_buffer->Buffer());
            if (!buf_state) continue;  // also skips if using nullDescriptor

            const AccessRange range =
                MakeRangeForVertexData(vertex_buffer->BufferOffset(), firstVertex, vertexCount, binding_state);
            const ResourceUsageTagEx tag_ex = AddCommandHandle(tag, buf_state->Handle());
            current_context_->UpdateAccessState(*buf_state, SYNC_VERTEX_ATTRIBUTE_INPUT_VERTEX_ATTRIBUTE_READ, range, tag_ex);
        }
    }
}

bool CommandBufferAccessContext::ValidateDrawVertexIndex(uint32_t index_count, uint32_t firstIndex, const Location& loc) const {
    bool skip = false;
    const auto& index_binding = cb_state_->index_buffer_binding;
    // TODO - Handle https://gitlab.khronos.org/vulkan/Vulkan-ValidationLayers/-/issues/45
    const auto index_buf_state = sync_state_.Get<vvl::Buffer>(index_binding.Buffer());
    if (!index_buf_state) return skip;

    const uint32_t index_size = IndexTypeByteSize(index_binding.index_type);
    const AccessRange range = MakeRangeForIndexData(index_binding.BufferOffset(), firstIndex, index_count, index_size);

    auto hazard = current_context_->DetectHazard(*index_buf_state, SYNC_INDEX_INPUT_INDEX_READ, range);
    if (hazard.IsHazard()) {
        LogObjectList objlist(cb_state_->Handle(), index_buf_state->Handle());
        if (const auto* pipe = cb_state_->GetLastBoundGraphics().pipeline_state) {
            objlist.add(pipe->Handle());
        }
        const std::string resource_description = "index " + sync_state_.FormatHandle(*index_buf_state);
        const auto error = error_messages_.BufferError(hazard, *this, loc.function, resource_description, range);
        skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc, error);
    }

    // TODO: Shader instrumentation support is needed to read index buffer content and determine the range of accessed
    // versices (new syncval mode). Scanning index buffer for each draw call might be the simplest option to implement
    // and the most reliable one, but potentially it can be heavy (still might be okay, testing is needed).
    // Some other options: a) rescan index buffer when its modification is detected, b) scan index buffer only once and
    // then assume it is immutable (common scenario).
    // skip |= ValidateDrawVertex(?, ?, loc);

    return skip;
}

void CommandBufferAccessContext::RecordDrawVertexIndex(uint32_t indexCount, uint32_t firstIndex, const ResourceUsageTag tag) {
    const auto& index_binding = cb_state_->index_buffer_binding;
    // TODO - Handle https://gitlab.khronos.org/vulkan/Vulkan-ValidationLayers/-/issues/45
    const auto index_buf_state = sync_state_.Get<vvl::Buffer>(index_binding.Buffer());
    if (!index_buf_state) {
        return;
    }

    const uint32_t index_size = IndexTypeByteSize(index_binding.index_type);
    const AccessRange range = MakeRangeForIndexData(index_binding.BufferOffset(), firstIndex, indexCount, index_size);
    const ResourceUsageTagEx tag_ex = AddCommandHandle(tag, index_buf_state->Handle());
    current_context_->UpdateAccessState(*index_buf_state, SYNC_INDEX_INPUT_INDEX_READ, range, tag_ex);

    // TODO: Shader instrumentation support is needed to read index buffer content and determine the range of accessed
    // versices (new syncval mode). Scanning index buffer for each draw call might be the simplest option to implement
    // and the most reliable one, but potentially it can be heavy (still might be okay, testing is needed).
    // Some other options: a) rescan index buffer when its modification is detected, b) scan index buffer only once and
    // then assume it is immutable (common scenario).
    // RecordDrawVertex(?, ?, tag);
}

bool CommandBufferAccessContext::ValidateDrawAttachment(const Location& loc) const {
    bool skip = false;
    if (current_renderpass_context_) {
        skip |= current_renderpass_context_->ValidateDrawSubpassAttachment(*this, loc.function);
    } else if (dynamic_rendering_info_) {
        skip |= ValidateDrawDynamicRenderingAttachment(loc);
    }
    return skip;
}

bool CommandBufferAccessContext::ValidateDrawDynamicRenderingAttachment(const Location& location) const {
    bool skip = false;
    const auto& last_bound_state = cb_state_->GetLastBoundGraphics();
    const auto* pipe = last_bound_state.pipeline_state;
    if (!pipe || pipe->RasterizationDisabled()) return skip;

    const auto& list = pipe->fs_writable_output_location_list;
    const auto& access_context = *GetCurrentAccessContext();

    const DynamicRenderingInfo& info = *dynamic_rendering_info_;
    for (const auto output_location : list) {
        if (output_location >= info.info.colorAttachmentCount) {
            continue;
        }
        const auto& attachment = info.attachments[output_location];
        if (!attachment.IsWriteable(last_bound_state)) {
            continue;
        }
        const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kColorAttachment);
        ImageRangeGen view_gen = attachment.GetRangeGen(info.info.viewMask);
        HazardResult hazard =
            access_context.DetectAttachmentHazard(view_gen, SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, attachment_access);

        if (hazard.IsHazard()) {
            LogObjectList obj_list(cb_state_->Handle(), attachment.view->Handle());
            Location loc = attachment.GetLocation(location, output_location);
            const std::string error = error_messages_.Error(
                hazard, *this, location.function, sync_state_.FormatHandle(*attachment.view), "DynamicRenderingAttachmentError");
            skip |= sync_state_.SyncError(hazard.Hazard(), obj_list, loc.dot(vvl::Field::imageView), error);
        }
    }

    // TODO -- fixup this and Subpass attachment to correct map the various depth stencil enables/reads vs. writes
    // PHASE1 TODO: Add layout based read/vs. write selection.
    // PHASE1 TODO: Read operations for both depth and stencil are possible in the future.
    // PHASE1 TODO: Add EARLY stage detection based on ExecutionMode.
    for (size_t i = info.info.colorAttachmentCount; i < info.attachments.size(); i++) {
        const auto& attachment = info.attachments[i];
        bool writeable = attachment.IsWriteable(last_bound_state);

        if (writeable) {
            const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kDepthStencilAttachment);
            ImageRangeGen view_gen = attachment.GetRangeGen(info.info.viewMask);
            HazardResult hazard = access_context.DetectAttachmentHazard(
                view_gen, SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, attachment_access);

            if (hazard.IsHazard()) {
                LogObjectList objlist(cb_state_->Handle(), attachment.view->Handle());
                Location loc = attachment.GetLocation(location);
                const std::string error =
                    error_messages_.Error(hazard, *this, location.function, sync_state_.FormatHandle(*attachment.view),
                                          "DynamicRenderingAttachmentError");
                skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc.dot(vvl::Field::imageView), error);
            }
        }
    }

    return skip;
}

void CommandBufferAccessContext::RecordDrawAttachment(const ResourceUsageTag tag) {
    if (current_renderpass_context_) {
        current_renderpass_context_->RecordDrawSubpassAttachment(*cb_state_, tag);
    } else if (dynamic_rendering_info_) {
        RecordDrawDynamicRenderingAttachment(tag);
    }
}

void CommandBufferAccessContext::RecordDrawDynamicRenderingAttachment(ResourceUsageTag tag) {
    const auto& last_bound_state = cb_state_->GetLastBoundGraphics();
    const auto* pipe = last_bound_state.pipeline_state;
    if (!pipe || pipe->RasterizationDisabled()) {
        return;
    }

    const auto& list = pipe->fs_writable_output_location_list;
    auto& access_context = *GetCurrentAccessContext();

    const DynamicRenderingInfo& info = *dynamic_rendering_info_;
    for (const auto output_location : list) {
        if (output_location >= info.info.colorAttachmentCount) {
            continue;
        }
        const auto& attachment = info.attachments[output_location];
        if (!attachment.IsWriteable(last_bound_state)) {
            continue;
        }
        const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kColorAttachment);
        ImageRangeGen view_gen = attachment.GetRangeGen(info.info.viewMask);
        access_context.UpdateAttachmentAccessState(view_gen, SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, attachment_access,
                                                   ResourceUsageTagEx{tag});
    }

    // TODO -- fixup this and Subpass attachment to correct map the various depth stencil enables/reads vs. writes
    // PHASE1 TODO: Add layout based read/vs. write selection.
    // PHASE1 TODO: Read operations for both depth and stencil are possible in the future.
    // PHASE1 TODO: Add EARLY stage detection based on ExecutionMode.

    const uint32_t attachment_count = static_cast<uint32_t>(info.attachments.size());
    for (uint32_t i = info.info.colorAttachmentCount; i < attachment_count; i++) {
        const auto& attachment = info.attachments[i];
        bool writeable = attachment.IsWriteable(last_bound_state);

        if (writeable) {
            const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kDepthStencilAttachment);
            ImageRangeGen view_gen = attachment.GetRangeGen(info.info.viewMask);
            access_context.UpdateAttachmentAccessState(view_gen, SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE,
                                                       attachment_access, ResourceUsageTagEx{tag});
        }
    }
}

static VkImageAspectFlags GetAttachmentAspectsToClear(VkImageAspectFlags clear_aspect_mask, const vvl::ImageView& attachment_view,
                                                      bool separate_depth_stencil_attachment_access) {
    // Check if clear request is valid.
    const bool clear_color = (clear_aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0;
    const bool clear_depth = (clear_aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) != 0;
    const bool clear_stencil = (clear_aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) != 0;
    if (!clear_color && !clear_depth && !clear_stencil) {
        return 0;  // nothing to clear
    }
    if (clear_color && (clear_depth || clear_stencil)) {
        return 0;  // according to spec it's not allowed
    }

    // View's aspect mask is used only for color attachment.
    // For depth/stencil attachment view aspect mask is ignored according to spec.
    const VkImageAspectFlags view_aspect_mask = attachment_view.normalized_subresource_range.aspectMask;

    // Collect aspects that should be cleared.
    VkImageAspectFlags aspects_to_clear = VK_IMAGE_ASPECT_NONE;
    if (clear_color && (view_aspect_mask & kColorAspects) != 0) {
        assert(CountSetBits(view_aspect_mask) == 1);
        aspects_to_clear |= view_aspect_mask;
    }
    if (clear_depth && vkuFormatHasDepth(attachment_view.create_info.format)) {
        aspects_to_clear |= VK_IMAGE_ASPECT_DEPTH_BIT;
    }
    if (clear_stencil && vkuFormatHasStencil(attachment_view.create_info.format)) {
        aspects_to_clear |= VK_IMAGE_ASPECT_STENCIL_BIT;
    }

    // Even if only depth or stencil aspect is specified we validate access to
    // both depth and stencil aspects because they can be interleaved.
    if (!separate_depth_stencil_attachment_access && (aspects_to_clear & kDepthStencilAspects) != 0) {
        aspects_to_clear = kDepthStencilAspects;
    }
    return aspects_to_clear;
}

static std::optional<VkImageSubresourceRange> RestrictSubresourceRangeToClearLayers(
    const VkImageSubresourceRange& normalized_subresource_range, uint32_t clear_first_layer, uint32_t clear_layer_count) {
    // Contract of this function
    assert(normalized_subresource_range.layerCount != VK_REMAINING_ARRAY_LAYERS);
    // According to spec
    assert(clear_layer_count != VK_REMAINING_ARRAY_LAYERS);

    const uint32_t first = std::max(normalized_subresource_range.baseArrayLayer, clear_first_layer);
    const uint32_t last_range = normalized_subresource_range.baseArrayLayer + normalized_subresource_range.layerCount;
    const uint32_t last_clear = clear_first_layer + clear_layer_count;
    const uint32_t last = std::min(last_range, last_clear);

    if (first >= last) {
        return {};
    }

    std::optional<VkImageSubresourceRange> result = normalized_subresource_range;
    result->baseArrayLayer = first;
    result->layerCount = last - first;
    return result;
}

std::optional<CommandBufferAccessContext::ClearAttachmentInfo> CommandBufferAccessContext::GetClearAttachmentInfo(
    const VkClearAttachment& clear_attachment, uint32_t clear_first_layer, uint32_t clear_layer_count) const {
    const vvl::ImageView* attachment_view = nullptr;
    if (current_renderpass_context_) {
        attachment_view = current_renderpass_context_->GetClearAttachmentView(clear_attachment);
    } else if (dynamic_rendering_info_) {
        attachment_view = dynamic_rendering_info_->GetClearAttachmentView(clear_attachment);
    }
    if (!attachment_view) {
        return {};
    }

    const bool separate_depth_stencil_attachment_access =
        GetSyncState().device_state->enabled_features.maintenance7 &&
        GetSyncState().device_state->phys_dev_ext_props.maintenance7_props.separateDepthStencilAttachmentAccess;
    const VkImageAspectFlags aspects =
        GetAttachmentAspectsToClear(clear_attachment.aspectMask, *attachment_view, separate_depth_stencil_attachment_access);
    if (!aspects) {
        return {};
    }

    const auto subresource_range =
        RestrictSubresourceRangeToClearLayers(attachment_view->normalized_subresource_range, clear_first_layer, clear_layer_count);
    if (!subresource_range.has_value()) {
        return {};
    }

    return ClearAttachmentInfo{*attachment_view, *subresource_range};
}

bool CommandBufferAccessContext::ValidateClearAttachment(const Location& loc, const VkClearAttachment& clear_attachment,
                                                         uint32_t clear_rect_index, const VkClearRect& clear_rect) const {
    bool skip = false;

    const auto optional_info = GetClearAttachmentInfo(clear_attachment, clear_rect.baseArrayLayer, clear_rect.layerCount);
    if (!optional_info) {
        return skip;
    }
    const ClearAttachmentInfo& info = *optional_info;
    const VkImageSubresourceRange subresource_range = info.subresource_range;
    const VkImageAspectFlags aspects_to_clear = subresource_range.aspectMask;
    const uint32_t view_mask = GetViewMask();
    const ImageSubState& sub_state = SubState(*info.attachment_view.image_state);

    // NOTE: when we teach ImageRangeGen to work with view masks all logic will be much simplified

    // Validate Color clear
    auto report_color_hazard = [this, &skip, &loc, &info](const HazardResult& hazard, const VkClearAttachment& clear_attachment,
                                                          uint32_t clear_rect_index, const VkClearRect& clear_rect) {
        std::ostringstream ss;
        ss << string_VkImageAspectFlags(clear_attachment.aspectMask);
        ss << " aspect of color attachment " << clear_attachment.colorAttachment;
        ss << " (" << sync_state_.FormatHandle(info.attachment_view) << ")";
        if (current_renderpass_context_) {
            ss << " in subpass " << current_renderpass_context_->GetCurrentSubpass();
        }
        const std::string resource_description = ss.str();
        const LogObjectList objlist(cb_state_->Handle(), info.attachment_view.Handle());
        const auto error = error_messages_.ClearAttachmentError(hazard, *this, loc.function, resource_description,
                                                                clear_attachment.aspectMask, clear_rect_index, clear_rect);
        skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc, error);
    };
    if (aspects_to_clear & kColorAspects) {
        // [core validation check]: if COLOR_ASPECT is included then PLANE aspects are not allowed,
        // and if PLANE aspect is included then only one is allowed.
        assert(CountSetBits(aspects_to_clear) == 1);

        const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kColorAttachment);
        if (view_mask == 0) {
            HazardResult hazard = current_context_->DetectAttachmentHazard(
                *info.attachment_view.image_state, subresource_range, info.attachment_view.is_depth_sliced,
                SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, attachment_access);
            if (hazard.IsHazard()) {
                report_color_hazard(hazard, clear_attachment, clear_rect_index, clear_rect);
            }
        } else {
            const auto view_indices = GetSetBitIndices(view_mask);
            const VkImageSubresourceRange& attachment_subresource = info.attachment_view.normalized_subresource_range;
            for (uint32_t view_index : view_indices) {
                if (view_index < attachment_subresource.layerCount) {
                    VkImageSubresourceRange view_subresource = attachment_subresource;
                    view_subresource.baseArrayLayer += view_index;
                    view_subresource.layerCount = 1;

                    ImageRangeGen range_gen = sub_state.MakeImageRangeGen(view_subresource, info.attachment_view.is_depth_sliced);
                    HazardResult hazard = current_context_->DetectAttachmentHazard(
                        range_gen, SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE, attachment_access);
                    if (hazard.IsHazard()) {
                        report_color_hazard(hazard, clear_attachment, clear_rect_index, clear_rect);
                    }
                }
            }
        }
    }

    // Validate Depth-Stencil clear
    auto report_depth_stencil_hazard = [this, &skip, &loc, &info](const HazardResult& hazard,
                                                                  const VkClearAttachment& clear_attachment,
                                                                  uint32_t clear_rect_index, const VkClearRect& clear_rect) {
        std::ostringstream ss;
        ss << string_VkImageAspectFlags(clear_attachment.aspectMask);
        ss << " aspect(s) of depth-stencil attachment (";
        ss << sync_state_.FormatHandle(info.attachment_view) << ")";
        if (current_renderpass_context_) {
            ss << " in subpass " << current_renderpass_context_->GetCurrentSubpass();
        }
        const std::string resource_description = ss.str();
        const LogObjectList objlist(cb_state_->Handle(), info.attachment_view.Handle());
        const auto error = error_messages_.ClearAttachmentError(hazard, *this, loc.function, resource_description,
                                                                clear_attachment.aspectMask, clear_rect_index, clear_rect);
        skip |= sync_state_.SyncError(hazard.Hazard(), objlist, loc, error);
    };
    if (aspects_to_clear & kDepthStencilAspects) {
        const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kDepthStencilAttachment);

        if (view_mask == 0) {
            // vkCmdClearAttachments depth/stencil writes are executed by the EARLY_FRAGMENT_TESTS_BIT and LATE_FRAGMENT_TESTS_BIT
            // stages. The implementation tracks the most recent access, which happens in the LATE_FRAGMENT_TESTS_BIT stage.
            HazardResult hazard = current_context_->DetectAttachmentHazard(
                *info.attachment_view.image_state, subresource_range, info.attachment_view.is_depth_sliced,
                SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, attachment_access);
            if (hazard.IsHazard()) {
                report_depth_stencil_hazard(hazard, clear_attachment, clear_rect_index, clear_rect);
            }
        } else {
            const auto view_indices = GetSetBitIndices(view_mask);
            const VkImageSubresourceRange& attachment_subresource = info.attachment_view.normalized_subresource_range;
            for (uint32_t view_index : view_indices) {
                if (view_index < attachment_subresource.layerCount) {
                    VkImageSubresourceRange view_subresource = attachment_subresource;
                    view_subresource.baseArrayLayer += view_index;
                    view_subresource.layerCount = 1;

                    ImageRangeGen range_gen = sub_state.MakeImageRangeGen(view_subresource, info.attachment_view.is_depth_sliced);
                    HazardResult hazard = current_context_->DetectAttachmentHazard(
                        range_gen, SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE, attachment_access);
                    if (hazard.IsHazard()) {
                        report_depth_stencil_hazard(hazard, clear_attachment, clear_rect_index, clear_rect);
                    }
                }
            }
        }
    }
    return skip;
}

void CommandBufferAccessContext::RecordClearAttachment(ResourceUsageTag tag, const VkClearAttachment& clear_attachment,
                                                       const VkClearRect& rect) {
    const auto optional_info = GetClearAttachmentInfo(clear_attachment, rect.baseArrayLayer, rect.layerCount);
    if (!optional_info) {
        return;
    }
    const ClearAttachmentInfo& info = *optional_info;
    const VkImageSubresourceRange subresource_range = info.subresource_range;
    const VkImageAspectFlags aspects_to_clear = subresource_range.aspectMask;
    const uint32_t view_mask = GetViewMask();
    const ImageSubState& sub_state = SubState(*info.attachment_view.image_state);

    auto update_access_state = [this, aspects_to_clear, tag](ImageRangeGen& range_gen) {
        if (aspects_to_clear & kColorAspects) {
            const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kColorAttachment);
            current_context_->UpdateAttachmentAccessState(range_gen, SYNC_COLOR_ATTACHMENT_OUTPUT_COLOR_ATTACHMENT_WRITE,
                                                          attachment_access, ResourceUsageTagEx{tag});
        } else {
            const AttachmentAccess attachment_access = GetAttachmentAccess(SyncOrdering::kDepthStencilAttachment);
            current_context_->UpdateAttachmentAccessState(range_gen, SYNC_LATE_FRAGMENT_TESTS_DEPTH_STENCIL_ATTACHMENT_WRITE,
                                                          attachment_access, ResourceUsageTagEx{tag});
        }
    };
    // NOTE: when we teach ImageRangeGen to work with view masks all logic will be much simplified
    if (view_mask == 0) {
        ImageRangeGen range_gen = sub_state.MakeImageRangeGen(subresource_range, false);
        update_access_state(range_gen);
    } else {
        const auto view_indices = GetSetBitIndices(view_mask);
        const VkImageSubresourceRange& attachment_subresource = info.attachment_view.normalized_subresource_range;
        for (uint32_t view_index : view_indices) {
            if (view_index < attachment_subresource.layerCount) {
                VkImageSubresourceRange view_subresource = attachment_subresource;
                view_subresource.baseArrayLayer += view_index;
                view_subresource.layerCount = 1;
                ImageRangeGen range_gen = sub_state.MakeImageRangeGen(view_subresource, false);
                update_access_state(range_gen);
            }
        }
    }
}

QueueId CommandBufferAccessContext::GetQueueId() const { return kQueueIdInvalid; }

ResourceUsageTag CommandBufferAccessContext::RecordBeginRenderPass(vvl::Func command, const vvl::RenderPass& rp_state,
                                                                   const VkRect2D& render_area,
                                                                   const std::vector<const vvl::ImageView*>& attachment_views) {
    // Create an access context the current renderpass.
    const auto barrier_tag = NextCommandTag(command, SubCommandType::kSubpassTransition, 0);
    AddCommandHandle(barrier_tag, rp_state.Handle());
    const auto load_tag = NextSubCommandTag(command, SubCommandType::kLoadOp, 0);
    render_pass_contexts_.emplace_back(std::make_unique<RenderPassAccessContext>(
        rp_state, render_area, GetQueueFlags(), attachment_views, cb_access_context_, current_render_pass_instance_id_));
    current_renderpass_context_ = render_pass_contexts_.back().get();
    current_renderpass_context_->RecordBeginRenderPass(barrier_tag, load_tag);
    current_context_ = &current_renderpass_context_->CurrentContext();
    return barrier_tag;
}

ResourceUsageTag CommandBufferAccessContext::RecordNextSubpass(vvl::Func command) {
    assert(current_renderpass_context_);
    if (!current_renderpass_context_) return NextCommandTag(command);

    // At this point current subpass value has not updated yet to the index of "next subpass"
    const uint32_t previous_subpass = current_renderpass_context_->GetCurrentSubpass();
    const uint32_t this_subpass = previous_subpass + 1;

    auto resolve_tag = NextCommandTag(command, SubCommandType::kResolveOp, previous_subpass);
    AddCommandHandle(resolve_tag, current_renderpass_context_->GetRenderPassState()->Handle());
    auto store_tag = NextSubCommandTag(command, SubCommandType::kStoreOp, previous_subpass);
    auto transition_tag = NextSubCommandTag(command, SubCommandType::kSubpassTransition, this_subpass);
    auto load_tag = NextSubCommandTag(command, SubCommandType::kLoadOp, this_subpass);

    current_renderpass_context_->RecordNextSubpass(resolve_tag, store_tag, transition_tag, load_tag);
    current_context_ = &current_renderpass_context_->CurrentContext();
    return transition_tag;
}

ResourceUsageTag CommandBufferAccessContext::RecordEndRenderPass(vvl::Func command) {
    assert(current_renderpass_context_);
    if (!current_renderpass_context_) return NextCommandTag(command);

    const uint32_t current_subpass = current_renderpass_context_->GetCurrentSubpass();

    auto store_tag = NextCommandTag(command, SubCommandType::kStoreOp, current_subpass);
    AddCommandHandle(store_tag, current_renderpass_context_->GetRenderPassState()->Handle());

    auto barrier_tag = NextSubCommandTag(command, SubCommandType::kSubpassTransition);

    current_renderpass_context_->RecordEndRenderPass(&cb_access_context_, store_tag, barrier_tag);
    current_context_ = &cb_access_context_;
    current_renderpass_context_ = nullptr;
    current_render_pass_instance_id_++;
    return barrier_tag;
}

void CommandBufferAccessContext::RecordDestroyEvent(vvl::Event* event_state) { GetCurrentEventsContext()->Destroy(event_state); }

void CommandBufferAccessContext::RecordExecutedCommandBuffer(const CommandBufferAccessContext& recorded_cb_context) {
    const AccessContext* recorded_context = recorded_cb_context.GetCurrentAccessContext();
    assert(recorded_context);

    // Just run through the barriers ignoring the usage from the recorded context, as Resolve will overwrite outdated state
    const ResourceUsageTag base_tag = GetTagCount();
    for (const auto& sync_op : recorded_cb_context.GetSyncOps()) {
        // we update the range to any include layout transition first use writes,
        // as they are stored along with the source scope (as effective barrier) when recorded
        sync_op.sync_op->ReplayRecord(*this, base_tag + sync_op.tag);
    }

    ImportRecordedAccessLog(recorded_cb_context);
    ResolveExecutedCommandBuffer(*recorded_context, base_tag);
}

void CommandBufferAccessContext::ResolveExecutedCommandBuffer(const AccessContext& recorded_context, ResourceUsageTag offset) {
    auto tag_offset = [offset](AccessState* access) { access->OffsetTag(offset); };
    GetCurrentAccessContext()->ResolveFromContext(tag_offset, recorded_context);
}

void CommandBufferAccessContext::ImportRecordedAccessLog(const CommandBufferAccessContext& recorded_context) {
    cbs_referenced_->emplace_back(recorded_context.GetCBStateShared());
    access_log_->insert(access_log_->end(), recorded_context.access_log_->cbegin(), recorded_context.access_log_->cend());

    // Adjust command indices for the log records added from recorded_context.
    const auto& recorded_label_commands = recorded_context.cb_state_->GetLabelCommands();
    const bool use_proxy = !proxy_label_commands_.empty();
    const auto& label_commands = use_proxy ? proxy_label_commands_ : cb_state_->GetLabelCommands();
    if (!label_commands.empty()) {
        assert(label_commands.size() >= recorded_label_commands.size());
        const uint32_t command_offset = static_cast<uint32_t>(label_commands.size() - recorded_label_commands.size());
        for (size_t i = 0; i < recorded_context.access_log_->size(); i++) {
            size_t index = (access_log_->size() - 1) - i;
            assert((*access_log_)[index].label_command_index != vvl::kNoIndex32);
            (*access_log_)[index].label_command_index += command_offset;
        }
    }
}

ResourceUsageTag CommandBufferAccessContext::NextCommandTag(vvl::Func command, SubCommandType subcommand, uint32_t subpass) {
    command_number_++;
    current_command_tag_ = access_log_->size();

    ResourceUsageRecord& record = access_log_->emplace_back(command, command_number_, subcommand, cb_state_, reset_count_, subpass);

    if (!cb_state_->GetLabelCommands().empty()) {
        record.label_command_index = static_cast<uint32_t>(cb_state_->GetLabelCommands().size() - 1);
    }
    CheckCommandTagDebugCheckpoint();
    return current_command_tag_;
}

ResourceUsageTag CommandBufferAccessContext::NextSubCommandTag(vvl::Func command, SubCommandType subcommand, uint32_t subpass) {
    const ResourceUsageTag tag = access_log_->size();
    ResourceUsageRecord& record = access_log_->emplace_back(command, command_number_, subcommand, cb_state_, reset_count_, subpass);

    // By default copy handle range from the main command, but can be overwritten with AddSubcommandHandle.
    const auto& main_command_record = (*access_log_)[current_command_tag_];
    record.first_handle_index = main_command_record.first_handle_index;
    record.handle_count = main_command_record.handle_count;

    if (!cb_state_->GetLabelCommands().empty()) {
        record.label_command_index = static_cast<uint32_t>(cb_state_->GetLabelCommands().size() - 1);
    }
    return tag;
}

uint32_t CommandBufferAccessContext::AddHandle(const VulkanTypedHandle& typed_handle, uint32_t index) {
    const uint32_t handle_index = static_cast<uint32_t>(handles_.size());
    handles_.emplace_back(HandleRecord(typed_handle, index));
    sync_state_.stats.AddHandleRecord();
    return handle_index;
}

ResourceUsageTagEx CommandBufferAccessContext::AddCommandHandle(ResourceUsageTag tag, const VulkanTypedHandle& typed_handle) {
    return AddCommandHandleIndexed(tag, typed_handle, vvl::kNoIndex32);
}

ResourceUsageTagEx CommandBufferAccessContext::AddCommandHandleIndexed(ResourceUsageTag tag, const VulkanTypedHandle& typed_handle,
                                                                       uint32_t index) {
    assert(tag < access_log_->size());
    const uint32_t handle_index = AddHandle(typed_handle, index);
    // TODO: the following range check is not needed. Test and remove.
    if (tag < access_log_->size()) {
        auto& record = (*access_log_)[tag];
        if (record.first_handle_index == vvl::kNoIndex32) {
            record.first_handle_index = handle_index;
            record.handle_count = 1;
        } else {
            // assert that command handles occupy continuous range
            assert(handle_index - record.first_handle_index == record.handle_count);
            record.handle_count++;
        }
    }
    return {tag, handle_index};
}

void CommandBufferAccessContext::AddSubcommandHandleIndexed(ResourceUsageTag tag, const VulkanTypedHandle& typed_handle,
                                                            uint32_t index) {
    assert(tag < access_log_->size());
    const uint32_t handle_index = AddHandle(typed_handle, index);
    // TODO: the following range check is not needed. Test and remove.
    if (tag < access_log_->size()) {
        auto& record = (*access_log_)[tag];
        const auto& main_command_record = (*access_log_)[current_command_tag_];
        if (record.first_handle_index == main_command_record.first_handle_index) {
            // override default behavior that subcommand references the same handles as the main command
            record.first_handle_index = handle_index;
            record.handle_count = 1;
        } else {
            // assert that command handles occupy continuous range
            assert(handle_index - record.first_handle_index == record.handle_count);
            record.handle_count++;
        }
    }
}

std::string CommandBufferAccessContext::GetDebugRegionName(const ResourceUsageRecord& record) const {
    const bool use_proxy = !proxy_label_commands_.empty();
    const auto& label_commands = use_proxy ? proxy_label_commands_ : cb_state_->GetLabelCommands();
    return vvl::CommandBuffer::GetDebugRegionName(label_commands, record.label_command_index);
}

void CommandBufferAccessContext::RecordSyncOp(SyncOpPointer&& sync_op) {
    auto tag = sync_op->Record(this);
    // As renderpass operations can have side effects on the command buffer access context,
    // update the sync operation to record these if any.
    sync_ops_.emplace_back(tag, std::move(sync_op));
}

AttachmentAccess CommandBufferAccessContext::GetAttachmentAccess(SyncOrdering ordering, AttachmentAccessType type) const {
    AttachmentAccess attachment_access;
    attachment_access.type = type;
    attachment_access.ordering = ordering;
    attachment_access.render_pass_instance_id = current_render_pass_instance_id_;
    attachment_access.subpass = current_renderpass_context_ ? current_renderpass_context_->GetCurrentSubpass() : vvl::kNoIndex32;
    return attachment_access;
}

uint32_t CommandBufferAccessContext::GetViewMask() const {
    if (dynamic_rendering_info_) {
        return dynamic_rendering_info_->info.viewMask;
    } else if (current_renderpass_context_) {
        const auto& render_pass_ci = current_renderpass_context_->GetRenderPassState()->create_info;
        const uint32_t subpass = current_renderpass_context_->GetCurrentSubpass();
        return render_pass_ci.pSubpasses[subpass].viewMask;
    } else {
        assert(false && "GetViewMask musk be called only during render pass instance");
        return 0;
    }
}

// NOTE: debug location reporting feature works only for reproducible application sessions
// (it uses command number/reset count from the error message from the previous session).
// It's considered experimental and can be replaced with a better way to report syncval debug locations.
//
// Logs informational message when vulkan command stream reaches a specific location.
// The message can be intercepted by the reporting routines. For example, the message handler can trigger a breakpoint.
// The location can be specified through environment variables.
// VK_SYNCVAL_DEBUG_COMMAND_NUMBER: the command number
// VK_SYNCVAL_DEBUG_RESET_COUNT: (optional, default value is 1) command buffer reset count
// VK_SYNCVAL_DEBUG_CMDBUF_PATTERN: (optional, empty string by default) pattern to match command buffer debug name
void CommandBufferAccessContext::CheckCommandTagDebugCheckpoint() {
    auto get_cmdbuf_name = [](const DebugReport& debug_report, uint64_t cmdbuf_handle) {
        std::unique_lock<std::mutex> lock(debug_report.debug_output_mutex);
        std::string object_name = debug_report.GetUtilsObjectNameNoLock(cmdbuf_handle);
        if (object_name.empty()) {
            object_name = debug_report.GetMarkerObjectNameNoLock(cmdbuf_handle);
        }
        text::ToLower(object_name);
        return object_name;
    };
    if (sync_state_.debug_command_number == command_number_ && sync_state_.debug_reset_count == reset_count_) {
        const auto cmdbuf_name = get_cmdbuf_name(*sync_state_.debug_report, cb_state_->Handle().handle);
        const auto& pattern = sync_state_.debug_cmdbuf_pattern;
        const bool cmdbuf_match = pattern.empty() || (cmdbuf_name.find(pattern) != std::string::npos);
        if (cmdbuf_match) {
            sync_state_.LogInfo("SYNCVAL_DEBUG_COMMAND", LogObjectList(), Location(access_log_->back().command),
                                "Command stream has reached command #%" PRIu32 " in command buffer %s with reset count #%" PRIu32,
                                sync_state_.debug_command_number, sync_state_.FormatHandle(cb_state_->Handle()).c_str(),
                                sync_state_.debug_reset_count);
        }
    }
}

void UpdateAccessMapStats(const AccessMap& access_map, AccessContextStats& stats);

void CommandBufferAccessContext::UpdateStats(AccessStats& access_stats) const {
#if VVL_ENABLE_SYNCVAL_STATS != 0
    UpdateAccessMapStats(cb_access_context_.GetAccessMap(), access_stats.cb_access_stats);

    for (const auto& render_pass_context : render_pass_contexts_) {
        for (const AccessContext& subpass_access_context : render_pass_context->GetSubpassContexts()) {
            UpdateAccessMapStats(subpass_access_context.GetAccessMap(), access_stats.subpass_access_stats);
        }
    }
#endif
}

CommandBufferSubState::CommandBufferSubState(SyncValidator& dev, vvl::CommandBuffer& cb)
    : vvl::CommandBufferSubState(cb), access_context(dev, &cb) {
    access_context.SetSelfReference();
}

void CommandBufferSubState::End() {
    access_context.GetCurrentAccessContext()->Finalize();

    // For threads that are dedicated to recording command buffers but do not submit themselves,
    // the end of recording is a logical point to update memory stats
    access_context.GetSyncState().stats.UpdateMemoryStats();
}

void CommandBufferSubState::Destroy() {
    access_context.Destroy();  // must be first to clean up self references correctly.
}

void CommandBufferSubState::Reset(const Location& loc) { access_context.Reset(); }

void CommandBufferSubState::NotifyInvalidate(const vvl::StateObject::NodeList& invalid_nodes, bool unlink) {
    for (auto& obj : invalid_nodes) {
        switch (obj->Type()) {
            case kVulkanObjectTypeEvent:
                access_context.RecordDestroyEvent(static_cast<vvl::Event*>(obj.get()));
                break;
            default:
                break;
        }
    }
}

void CommandBufferSubState::RecordCopyBuffer(vvl::Buffer& src_buffer_state, vvl::Buffer& dst_buffer_state, uint32_t region_count,
                                             const VkBufferCopy* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_buffer_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_buffer_state.Handle());

    for (const auto& copy_region : vvl::make_span(regions, region_count)) {
        const AccessRange src_range = MakeRange(src_buffer_state, copy_region.srcOffset, copy_region.size);
        context->UpdateAccessState(src_buffer_state, SYNC_COPY_TRANSFER_READ, src_range, src_tag_ex);

        const AccessRange dst_range = MakeRange(dst_buffer_state, copy_region.dstOffset, copy_region.size);
        context->UpdateAccessState(dst_buffer_state, SYNC_COPY_TRANSFER_WRITE, dst_range, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordCopyBuffer2(vvl::Buffer& src_buffer_state, vvl::Buffer& dst_buffer_state, uint32_t region_count,
                                              const VkBufferCopy2* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_buffer_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_buffer_state.Handle());

    for (const auto& copy_region : vvl::make_span(regions, region_count)) {
        const AccessRange src_range = MakeRange(src_buffer_state, copy_region.srcOffset, copy_region.size);
        context->UpdateAccessState(src_buffer_state, SYNC_COPY_TRANSFER_READ, src_range, src_tag_ex);

        const AccessRange dst_range = MakeRange(dst_buffer_state, copy_region.dstOffset, copy_region.size);
        context->UpdateAccessState(dst_buffer_state, SYNC_COPY_TRANSFER_WRITE, dst_range, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordCopyImage(vvl::Image& src_image_state, vvl::Image& dst_image_state,
                                            VkImageLayout src_image_layout, VkImageLayout dst_image_layout, uint32_t region_count,
                                            const VkImageCopy* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_image_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_image_state.Handle());

    for (const auto& copy_region : vvl::make_span(regions, region_count)) {
        UpdateImageAccessState(*context, src_image_state, SYNC_COPY_TRANSFER_READ, RangeFromLayers(copy_region.srcSubresource),
                               copy_region.srcOffset, copy_region.extent, src_tag_ex);
        UpdateImageAccessState(*context, dst_image_state, SYNC_COPY_TRANSFER_WRITE, RangeFromLayers(copy_region.dstSubresource),
                               copy_region.dstOffset, copy_region.extent, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordCopyImage2(vvl::Image& src_image_state, vvl::Image& dst_image_state,
                                             VkImageLayout src_image_layout, VkImageLayout dst_image_layout, uint32_t region_count,
                                             const VkImageCopy2* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_image_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_image_state.Handle());

    for (const auto& copy_region : vvl::make_span(regions, region_count)) {
        UpdateImageAccessState(*context, src_image_state, SYNC_COPY_TRANSFER_READ, RangeFromLayers(copy_region.srcSubresource),
                               copy_region.srcOffset, copy_region.extent, src_tag_ex);
        UpdateImageAccessState(*context, dst_image_state, SYNC_COPY_TRANSFER_WRITE, RangeFromLayers(copy_region.dstSubresource),
                               copy_region.dstOffset, copy_region.extent, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordCopyBufferToImage(vvl::Buffer& src_buffer_state, vvl::Image& dst_image_state, VkImageLayout,
                                                    uint32_t region_count, const VkBufferImageCopy* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_buffer_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_image_state.Handle());

    for (const auto& copy_region : vvl::make_span(regions, region_count)) {
        AccessRange src_range = MakeRange(copy_region.bufferOffset, dst_image_state.GetBufferSizeFromCopyImage(copy_region));
        context->UpdateAccessState(src_buffer_state, SYNC_COPY_TRANSFER_READ, src_range, src_tag_ex);

        UpdateImageAccessState(*context, dst_image_state, SYNC_COPY_TRANSFER_WRITE, RangeFromLayers(copy_region.imageSubresource),
                               copy_region.imageOffset, copy_region.imageExtent, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordCopyBufferToImage2(vvl::Buffer& src_buffer_state, vvl::Image& dst_image_state, VkImageLayout,
                                                     uint32_t region_count, const VkBufferImageCopy2* regions,
                                                     const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_buffer_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_image_state.Handle());

    for (const auto& copy_region : vvl::make_span(regions, region_count)) {
        AccessRange src_range = MakeRange(copy_region.bufferOffset, dst_image_state.GetBufferSizeFromCopyImage(copy_region));
        context->UpdateAccessState(src_buffer_state, SYNC_COPY_TRANSFER_READ, src_range, src_tag_ex);

        UpdateImageAccessState(*context, dst_image_state, SYNC_COPY_TRANSFER_WRITE, RangeFromLayers(copy_region.imageSubresource),
                               copy_region.imageOffset, copy_region.imageExtent, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordCopyImageToBuffer(vvl::Image& src_image_state, vvl::Buffer& dst_buffer_state,
                                                    VkImageLayout src_image_layout, uint32_t region_count,
                                                    const VkBufferImageCopy* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_image_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_buffer_state.Handle());

    for (const auto& copy_region : vvl::make_span(regions, region_count)) {
        UpdateImageAccessState(*context, src_image_state, SYNC_COPY_TRANSFER_READ, RangeFromLayers(copy_region.imageSubresource),
                               copy_region.imageOffset, copy_region.imageExtent, src_tag_ex);

        AccessRange dst_range = MakeRange(copy_region.bufferOffset, src_image_state.GetBufferSizeFromCopyImage(copy_region));
        context->UpdateAccessState(dst_buffer_state, SYNC_COPY_TRANSFER_WRITE, dst_range, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordCopyImageToBuffer2(vvl::Image& src_image_state, vvl::Buffer& dst_buffer_state,
                                                     VkImageLayout src_image_layout, uint32_t region_count,
                                                     const VkBufferImageCopy2* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_image_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_buffer_state.Handle());

    for (const auto& copy_region : vvl::make_span(regions, region_count)) {
        UpdateImageAccessState(*context, src_image_state, SYNC_COPY_TRANSFER_READ, RangeFromLayers(copy_region.imageSubresource),
                               copy_region.imageOffset, copy_region.imageExtent, src_tag_ex);

        AccessRange dst_range = MakeRange(copy_region.bufferOffset, src_image_state.GetBufferSizeFromCopyImage(copy_region));
        context->UpdateAccessState(dst_buffer_state, SYNC_COPY_TRANSFER_WRITE, dst_range, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordBlitImage(vvl::Image& src_image_state, vvl::Image& dst_image_state,
                                            VkImageLayout src_image_layout, VkImageLayout dst_image_layout, uint32_t region_count,
                                            const VkImageBlit* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_image_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_image_state.Handle());

    for (const auto& blit_region : vvl::make_span(regions, region_count)) {
        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))};
        UpdateImageAccessState(*context, src_image_state, SYNC_BLIT_TRANSFER_READ, RangeFromLayers(blit_region.srcSubresource),
                               offset, extent, src_tag_ex);

        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)};
        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))};
        UpdateImageAccessState(*context, dst_image_state, SYNC_BLIT_TRANSFER_WRITE, RangeFromLayers(blit_region.dstSubresource),
                               offset, extent, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordBlitImage2(vvl::Image& src_image_state, vvl::Image& dst_image_state,
                                             VkImageLayout src_image_layout, VkImageLayout dst_image_layout, uint32_t region_count,
                                             const VkImageBlit2* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_image_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_image_state.Handle());

    for (const auto& blit_region : vvl::make_span(regions, region_count)) {
        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))};
        UpdateImageAccessState(*context, src_image_state, SYNC_BLIT_TRANSFER_READ, RangeFromLayers(blit_region.srcSubresource),
                               offset, extent, src_tag_ex);

        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)};
        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))};
        UpdateImageAccessState(*context, dst_image_state, SYNC_BLIT_TRANSFER_WRITE, RangeFromLayers(blit_region.dstSubresource),
                               offset, extent, dst_tag_ex);
    }
}

void CommandBufferSubState::RecordResolveImage(vvl::Image& src_image_state, vvl::Image& dst_image_state, uint32_t region_count,
                                               const VkImageResolve* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_image_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_image_state.Handle());

    for (const auto& resolve_region : vvl::make_span(regions, region_count)) {
        UpdateImageAccessState(*context, src_image_state, SYNC_RESOLVE_TRANSFER_READ,
                               RangeFromLayers(resolve_region.srcSubresource), resolve_region.srcOffset, resolve_region.extent,
                               src_tag_ex);
        UpdateImageAccessState(*context, dst_image_state, SYNC_RESOLVE_TRANSFER_WRITE,
                               RangeFromLayers(resolve_region.dstSubresource), resolve_region.dstOffset, resolve_region.extent,
                               dst_tag_ex);
    }
}

void CommandBufferSubState::RecordResolveImage2(vvl::Image& src_image_state, vvl::Image& dst_image_state, uint32_t region_count,
                                                const VkImageResolve2* regions, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    auto src_tag_ex = access_context.AddCommandHandle(tag, src_image_state.Handle());
    auto dst_tag_ex = access_context.AddCommandHandle(tag, dst_image_state.Handle());

    for (const auto& resolve_region : vvl::make_span(regions, region_count)) {
        UpdateImageAccessState(*context, src_image_state, SYNC_RESOLVE_TRANSFER_READ,
                               RangeFromLayers(resolve_region.srcSubresource), resolve_region.srcOffset, resolve_region.extent,
                               src_tag_ex);
        UpdateImageAccessState(*context, dst_image_state, SYNC_RESOLVE_TRANSFER_WRITE,
                               RangeFromLayers(resolve_region.dstSubresource), resolve_region.dstOffset, resolve_region.extent,
                               dst_tag_ex);
    }
}

void CommandBufferSubState::RecordClearColorImage(vvl::Image& image_state, VkImageLayout, const VkClearColorValue*,
                                                  uint32_t range_count, const VkImageSubresourceRange* ranges,
                                                  const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();
    assert(context);

    access_context.AddCommandHandle(tag, image_state.Handle());

    for (uint32_t index = 0; index < range_count; index++) {
        const auto& range = ranges[index];
        UpdateImageAccessState(*context, image_state, SYNC_CLEAR_TRANSFER_WRITE, range, tag);
    }
}

void CommandBufferSubState::RecordClearDepthStencilImage(vvl::Image& image_state, VkImageLayout, const VkClearDepthStencilValue*,
                                                         uint32_t range_count, const VkImageSubresourceRange* ranges,
                                                         const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();
    assert(context);

    access_context.AddCommandHandle(tag, image_state.Handle());

    for (uint32_t index = 0; index < range_count; index++) {
        const auto& range = ranges[index];
        UpdateImageAccessState(*context, image_state, SYNC_CLEAR_TRANSFER_WRITE, range, tag);
    }
}

void CommandBufferSubState::RecordClearAttachments(uint32_t attachment_count, const VkClearAttachment* pAttachments,
                                                   uint32_t rect_count, const VkClearRect* pRects, const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);

    for (const auto& attachment : vvl::make_span(pAttachments, attachment_count)) {
        for (const auto& rect : vvl::make_span(pRects, rect_count)) {
            access_context.RecordClearAttachment(tag, attachment, rect);
        }
    }
}

void CommandBufferSubState::RecordFillBuffer(vvl::Buffer& buffer_state, VkDeviceSize offset, VkDeviceSize size,
                                             const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();
    assert(context);

    const AccessRange range = MakeRange(buffer_state, offset, size);
    const ResourceUsageTagEx tag_ex = access_context.AddCommandHandle(tag, buffer_state.Handle());
    context->UpdateAccessState(buffer_state, SYNC_CLEAR_TRANSFER_WRITE, range, tag_ex);
}

void CommandBufferSubState::RecordUpdateBuffer(vvl::Buffer& buffer_state, VkDeviceSize offset, VkDeviceSize size,
                                               const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();
    assert(context);

    // VK_WHOLE_SIZE not allowed
    const AccessRange range = MakeRange(offset, size);
    const ResourceUsageTagEx tag_ex = access_context.AddCommandHandle(tag, buffer_state.Handle());
    context->UpdateAccessState(buffer_state, SYNC_CLEAR_TRANSFER_WRITE, range, tag_ex);
}

void CommandBufferSubState::RecordDecodeVideo(vvl::VideoSession& vs_state, const VkVideoDecodeInfoKHR& decode_info,
                                              const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    if (auto src_buffer = base.dev_data.Get<vvl::Buffer>(decode_info.srcBuffer)) {
        const AccessRange src_range = MakeRange(*src_buffer, decode_info.srcBufferOffset, decode_info.srcBufferRange);
        const ResourceUsageTagEx src_tag_ex = access_context.AddCommandHandle(tag, src_buffer->Handle());
        context->UpdateAccessState(*src_buffer, SYNC_VIDEO_DECODE_VIDEO_DECODE_READ, src_range, src_tag_ex);
    }

    const auto* device_state = access_context.GetSyncState().device_state;
    auto dst_resource = vvl::VideoPictureResource(*device_state, decode_info.dstPictureResource);
    if (dst_resource) {
        UpdateVideoAccessState(*context, vs_state, dst_resource, SYNC_VIDEO_DECODE_VIDEO_DECODE_WRITE, tag);
    }

    if (decode_info.pSetupReferenceSlot != nullptr && decode_info.pSetupReferenceSlot->pPictureResource != nullptr) {
        auto setup_resource = vvl::VideoPictureResource(*device_state, *decode_info.pSetupReferenceSlot->pPictureResource);
        if (setup_resource && (setup_resource != dst_resource)) {
            UpdateVideoAccessState(*context, vs_state, setup_resource, SYNC_VIDEO_DECODE_VIDEO_DECODE_WRITE, tag);
        }
    }

    for (uint32_t i = 0; i < decode_info.referenceSlotCount; ++i) {
        if (decode_info.pReferenceSlots[i].pPictureResource != nullptr) {
            auto reference_resource = vvl::VideoPictureResource(*device_state, *decode_info.pReferenceSlots[i].pPictureResource);
            if (reference_resource) {
                UpdateVideoAccessState(*context, vs_state, reference_resource, SYNC_VIDEO_DECODE_VIDEO_DECODE_READ, tag);
            }
        }
    }
}

void CommandBufferSubState::RecordEncodeVideo(vvl::VideoSession& vs_state, const VkVideoEncodeInfoKHR& encode_info,
                                              const Location& loc) {
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    if (auto src_buffer = base.dev_data.Get<vvl::Buffer>(encode_info.dstBuffer)) {
        const AccessRange src_range = MakeRange(*src_buffer, encode_info.dstBufferOffset, encode_info.dstBufferRange);
        const ResourceUsageTagEx src_tag_ex = access_context.AddCommandHandle(tag, src_buffer->Handle());
        context->UpdateAccessState(*src_buffer, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_WRITE, src_range, src_tag_ex);
    }

    const auto* device_state = access_context.GetSyncState().device_state;
    auto src_resource = vvl::VideoPictureResource(*device_state, encode_info.srcPictureResource);
    if (src_resource) {
        UpdateVideoAccessState(*context, vs_state, src_resource, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_READ, tag);
    }

    if (encode_info.pSetupReferenceSlot != nullptr && encode_info.pSetupReferenceSlot->pPictureResource != nullptr) {
        auto setup_resource = vvl::VideoPictureResource(*device_state, *encode_info.pSetupReferenceSlot->pPictureResource);
        if (setup_resource) {
            UpdateVideoAccessState(*context, vs_state, setup_resource, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_WRITE, tag);
        }
    }

    for (uint32_t i = 0; i < encode_info.referenceSlotCount; ++i) {
        if (encode_info.pReferenceSlots[i].pPictureResource != nullptr) {
            auto reference_resource = vvl::VideoPictureResource(*device_state, *encode_info.pReferenceSlots[i].pPictureResource);
            if (reference_resource) {
                UpdateVideoAccessState(*context, vs_state, reference_resource, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_READ, tag);
            }
        }
    }

    if (encode_info.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>(encode_info.pNext);
        if (quantization_map_info) {
            auto image_view_state = base.dev_data.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};
                ImageRangeGen range_gen(MakeImageRangeGen(*image_view_state, offset, extent));
                context->UpdateAccessState(range_gen, SYNC_VIDEO_ENCODE_VIDEO_ENCODE_READ, ResourceUsageTagEx{tag});
            }
        }
    }
}

void CommandBufferSubState::RecordCopyQueryPoolResults(vvl::QueryPool& pool_state, vvl::Buffer& dst_buffer_state,
                                                       uint32_t first_query, uint32_t query_count, VkDeviceSize dst_offset,
                                                       VkDeviceSize stride, VkQueryResultFlags flags, const Location& loc) {
    if (query_count == 0) {
        return;
    }
    const auto tag = access_context.NextCommandTag(loc.function);
    auto* context = access_context.GetCurrentAccessContext();

    const uint32_t query_size = (flags & VK_QUERY_RESULT_64_BIT) ? 8 : 4;
    const VkDeviceSize range_size = (query_count - 1) * stride + query_size;
    const AccessRange range = MakeRange(dst_offset, range_size);
    const ResourceUsageTagEx tag_ex = access_context.AddCommandHandle(tag, dst_buffer_state.Handle());
    context->UpdateAccessState(dst_buffer_state, SYNC_COPY_TRANSFER_WRITE, range, tag_ex);

    // TODO:Track VkQueryPool
}

void CommandBufferSubState::RecordBeginRenderPass(const VkRenderPassBeginInfo& render_pass_begin,
                                                  const VkSubpassBeginInfo& subpass_begin_info, const Location& loc) {
    if (!base.IsPrimary()) {
        return;  // [core validation check]: only primary command buffer can begin render pass
    }
    access_context.RecordSyncOp<SyncOpBeginRenderPass>(loc.function, access_context.GetSyncState(), &render_pass_begin,
                                                       &subpass_begin_info);
}

void CommandBufferSubState::RecordNextSubpass(const VkSubpassBeginInfo& subpass_begin_info,
                                              const VkSubpassEndInfo* subpass_end_info, const Location& loc) {
    if (!base.IsPrimary()) {
        return;  // [core validation check]: only primary command buffer can start next subpass
    }
    access_context.RecordSyncOp<SyncOpNextSubpass>(loc.function, access_context.GetSyncState(), &subpass_begin_info,
                                                   subpass_end_info);
}

void CommandBufferSubState::RecordEndRenderPass(const VkSubpassEndInfo* subpass_end_info, const Location& loc) {
    if (!base.IsPrimary()) {
        return;  // [core validation check]: only primary command buffer can end render pass
    }
    // Resolve the all subpass contexts to the command buffer contexts
    access_context.RecordSyncOp<SyncOpEndRenderPass>(loc.function, access_context.GetSyncState(), subpass_end_info);
}

void CommandBufferSubState::RecordExecuteCommand(vvl::CommandBuffer& secondary_command_buffer, uint32_t cmd_index,
                                                 const Location& loc) {
    if (cmd_index == 0) {
        ResourceUsageTag cb_tag = access_context.NextCommandTag(loc.function, SubCommandType::kIndex);
        access_context.AddCommandHandleIndexed(cb_tag, secondary_command_buffer.Handle(), cmd_index);
    } else {
        ResourceUsageTag cb_tag = access_context.NextSubCommandTag(loc.function, SubCommandType::kIndex);
        access_context.AddSubcommandHandleIndexed(cb_tag, secondary_command_buffer.Handle(), cmd_index);
    }
    access_context.RecordExecutedCommandBuffer(*GetAccessContext(secondary_command_buffer));
}

}  // namespace syncval
