/* Copyright (c) 2015-2021 The Khronos Group Inc.
 * Copyright (c) 2015-2021 Valve Corporation
 * Copyright (c) 2015-2021 LunarG, Inc.
 * Copyright (C) 2015-2021 Google Inc.
 * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 *
 * 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.
 *
 * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
 * Author: Tobin Ehlis <tobine@google.com>
 * Author: Chris Forbes <chrisf@ijw.co.nz>
 * Author: Mark Lobodzinski <mark@lunarg.com>
 * Author: Dave Houlton <daveh@lunarg.com>
 * Author: John Zulauf <jzulauf@lunarg.com>
 * Author: Tobias Hector <tobias.hector@amd.com>
 */
#include "cmd_buffer_state.h"
#include "render_pass_state.h"
#include "state_tracker.h"
#include "image_state.h"

COMMAND_POOL_STATE::COMMAND_POOL_STATE(ValidationStateTracker *dev, VkCommandPool cp, const VkCommandPoolCreateInfo *pCreateInfo,
                                       VkQueueFlags flags)
    : BASE_NODE(cp, kVulkanObjectTypeCommandPool),
      dev_data(dev),
      createFlags(pCreateInfo->flags),
      queueFamilyIndex(pCreateInfo->queueFamilyIndex),
      queue_flags(flags),
      unprotected((pCreateInfo->flags & VK_COMMAND_POOL_CREATE_PROTECTED_BIT) == 0) {}

void COMMAND_POOL_STATE::Allocate(const VkCommandBufferAllocateInfo *create_info, const VkCommandBuffer *command_buffers) {
    for (uint32_t i = 0; i < create_info->commandBufferCount; i++) {
        auto new_cb = dev_data->CreateCmdBufferState(command_buffers[i], create_info, this);
        commandBuffers.emplace(command_buffers[i], new_cb.get());
        dev_data->Add(std::move(new_cb));
    }
}

void COMMAND_POOL_STATE::Free(uint32_t count, const VkCommandBuffer *command_buffers) {
    for (uint32_t i = 0; i < count; i++) {
        auto iter = commandBuffers.find(command_buffers[i]);
        if (iter != commandBuffers.end()) {
            dev_data->Destroy<CMD_BUFFER_STATE>(iter->first);
            commandBuffers.erase(iter);
        }
    }
}

void COMMAND_POOL_STATE::Reset() {
    for (auto &entry : commandBuffers) {
        entry.second->Reset();
    }
}

void COMMAND_POOL_STATE::Destroy() {
    for (auto &entry : commandBuffers) {
        dev_data->Destroy<CMD_BUFFER_STATE>(entry.first);
    }
    commandBuffers.clear();
    BASE_NODE::Destroy();
}

const char *CommandTypeString(CMD_TYPE type) {
    // Autogenerated as part of the command_validation.h codegen
    return kGeneratedCommandNameList[type];
}

VkDynamicState ConvertToDynamicState(CBStatusFlagBits flag) {
    switch (flag) {
        case CBSTATUS_LINE_WIDTH_SET:
            return VK_DYNAMIC_STATE_LINE_WIDTH;
        case CBSTATUS_DEPTH_BIAS_SET:
            return VK_DYNAMIC_STATE_DEPTH_BIAS;
        case CBSTATUS_BLEND_CONSTANTS_SET:
            return VK_DYNAMIC_STATE_BLEND_CONSTANTS;
        case CBSTATUS_DEPTH_BOUNDS_SET:
            return VK_DYNAMIC_STATE_DEPTH_BOUNDS;
        case CBSTATUS_STENCIL_READ_MASK_SET:
            return VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK;
        case CBSTATUS_STENCIL_WRITE_MASK_SET:
            return VK_DYNAMIC_STATE_STENCIL_WRITE_MASK;
        case CBSTATUS_STENCIL_REFERENCE_SET:
            return VK_DYNAMIC_STATE_STENCIL_REFERENCE;
        case CBSTATUS_VIEWPORT_SET:
            return VK_DYNAMIC_STATE_VIEWPORT;
        case CBSTATUS_SCISSOR_SET:
            return VK_DYNAMIC_STATE_SCISSOR;
        case CBSTATUS_EXCLUSIVE_SCISSOR_SET:
            return VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV;
        case CBSTATUS_SHADING_RATE_PALETTE_SET:
            return VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV;
        case CBSTATUS_LINE_STIPPLE_SET:
            return VK_DYNAMIC_STATE_LINE_STIPPLE_EXT;
        case CBSTATUS_VIEWPORT_W_SCALING_SET:
            return VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV;
        case CBSTATUS_CULL_MODE_SET:
            return VK_DYNAMIC_STATE_CULL_MODE_EXT;
        case CBSTATUS_FRONT_FACE_SET:
            return VK_DYNAMIC_STATE_FRONT_FACE_EXT;
        case CBSTATUS_PRIMITIVE_TOPOLOGY_SET:
            return VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT;
        case CBSTATUS_VIEWPORT_WITH_COUNT_SET:
            return VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT;
        case CBSTATUS_SCISSOR_WITH_COUNT_SET:
            return VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT;
        case CBSTATUS_VERTEX_INPUT_BINDING_STRIDE_SET:
            return VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT;
        case CBSTATUS_DEPTH_TEST_ENABLE_SET:
            return VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT;
        case CBSTATUS_DEPTH_WRITE_ENABLE_SET:
            return VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT;
        case CBSTATUS_DEPTH_COMPARE_OP_SET:
            return VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT;
        case CBSTATUS_DEPTH_BOUNDS_TEST_ENABLE_SET:
            return VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT;
        case CBSTATUS_STENCIL_TEST_ENABLE_SET:
            return VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT;
        case CBSTATUS_STENCIL_OP_SET:
            return VK_DYNAMIC_STATE_STENCIL_OP_EXT;
        case CBSTATUS_DISCARD_RECTANGLE_SET:
            return VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT;
        case CBSTATUS_SAMPLE_LOCATIONS_SET:
            return VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT;
        case CBSTATUS_COARSE_SAMPLE_ORDER_SET:
            return VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV;
        case CBSTATUS_PATCH_CONTROL_POINTS_SET:
            return VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT;
        case CBSTATUS_RASTERIZER_DISCARD_ENABLE_SET:
            return VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT;
        case CBSTATUS_DEPTH_BIAS_ENABLE_SET:
            return VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT;
        case CBSTATUS_LOGIC_OP_SET:
            return VK_DYNAMIC_STATE_LOGIC_OP_EXT;
        case CBSTATUS_PRIMITIVE_RESTART_ENABLE_SET:
            return VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT;
        case CBSTATUS_VERTEX_INPUT_SET:
            return VK_DYNAMIC_STATE_VERTEX_INPUT_EXT;
        default:
            // CBSTATUS_INDEX_BUFFER_BOUND is not in VkDynamicState
            return VK_DYNAMIC_STATE_MAX_ENUM;
    }
    return VK_DYNAMIC_STATE_MAX_ENUM;
}

CBStatusFlagBits ConvertToCBStatusFlagBits(VkDynamicState state) {
    switch (state) {
        case VK_DYNAMIC_STATE_VIEWPORT:
            return CBSTATUS_VIEWPORT_SET;
        case VK_DYNAMIC_STATE_SCISSOR:
            return CBSTATUS_SCISSOR_SET;
        case VK_DYNAMIC_STATE_LINE_WIDTH:
            return CBSTATUS_LINE_WIDTH_SET;
        case VK_DYNAMIC_STATE_DEPTH_BIAS:
            return CBSTATUS_DEPTH_BIAS_SET;
        case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
            return CBSTATUS_BLEND_CONSTANTS_SET;
        case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
            return CBSTATUS_DEPTH_BOUNDS_SET;
        case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
            return CBSTATUS_STENCIL_READ_MASK_SET;
        case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
            return CBSTATUS_STENCIL_WRITE_MASK_SET;
        case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
            return CBSTATUS_STENCIL_REFERENCE_SET;
        case VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV:
            return CBSTATUS_VIEWPORT_W_SCALING_SET;
        case VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT:
            return CBSTATUS_DISCARD_RECTANGLE_SET;
        case VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT:
            return CBSTATUS_SAMPLE_LOCATIONS_SET;
        case VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV:
            return CBSTATUS_SHADING_RATE_PALETTE_SET;
        case VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV:
            return CBSTATUS_COARSE_SAMPLE_ORDER_SET;
        case VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV:
            return CBSTATUS_EXCLUSIVE_SCISSOR_SET;
        case VK_DYNAMIC_STATE_LINE_STIPPLE_EXT:
            return CBSTATUS_LINE_STIPPLE_SET;
        case VK_DYNAMIC_STATE_CULL_MODE_EXT:
            return CBSTATUS_CULL_MODE_SET;
        case VK_DYNAMIC_STATE_FRONT_FACE_EXT:
            return CBSTATUS_FRONT_FACE_SET;
        case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT:
            return CBSTATUS_PRIMITIVE_TOPOLOGY_SET;
        case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT:
            return CBSTATUS_VIEWPORT_WITH_COUNT_SET;
        case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT:
            return CBSTATUS_SCISSOR_WITH_COUNT_SET;
        case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT:
            return CBSTATUS_VERTEX_INPUT_BINDING_STRIDE_SET;
        case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT:
            return CBSTATUS_DEPTH_TEST_ENABLE_SET;
        case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT:
            return CBSTATUS_DEPTH_WRITE_ENABLE_SET;
        case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT:
            return CBSTATUS_DEPTH_COMPARE_OP_SET;
        case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT:
            return CBSTATUS_DEPTH_BOUNDS_TEST_ENABLE_SET;
        case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT:
            return CBSTATUS_STENCIL_TEST_ENABLE_SET;
        case VK_DYNAMIC_STATE_STENCIL_OP_EXT:
            return CBSTATUS_STENCIL_OP_SET;
        case VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT:
            return CBSTATUS_PATCH_CONTROL_POINTS_SET;
        case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT:
            return CBSTATUS_RASTERIZER_DISCARD_ENABLE_SET;
        case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE_EXT:
            return CBSTATUS_DEPTH_BIAS_ENABLE_SET;
        case VK_DYNAMIC_STATE_LOGIC_OP_EXT:
            return CBSTATUS_LOGIC_OP_SET;
        case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE_EXT:
            return CBSTATUS_PRIMITIVE_RESTART_ENABLE_SET;
        case VK_DYNAMIC_STATE_VERTEX_INPUT_EXT:
            return CBSTATUS_VERTEX_INPUT_SET;
        default:
            return CBSTATUS_NONE;
    }
    return CBSTATUS_NONE;
}

CMD_BUFFER_STATE::CMD_BUFFER_STATE(ValidationStateTracker *dev, VkCommandBuffer cb, const VkCommandBufferAllocateInfo *pCreateInfo,
                                   const COMMAND_POOL_STATE *pool)
    : REFCOUNTED_NODE(cb, kVulkanObjectTypeCommandBuffer),
      createInfo(*pCreateInfo),
      command_pool(pool),
      dev_data(dev),
      unprotected(pool->unprotected) {
    Reset();
}

// Get the image viewstate for a given framebuffer attachment
IMAGE_VIEW_STATE *CMD_BUFFER_STATE::GetActiveAttachmentImageViewState(uint32_t index) {
    assert(active_attachments && index != VK_ATTACHMENT_UNUSED && (index < active_attachments->size()));
    return active_attachments->at(index);
}

// Get the image viewstate for a given framebuffer attachment
const IMAGE_VIEW_STATE *CMD_BUFFER_STATE::GetActiveAttachmentImageViewState(uint32_t index) const {
    if (!active_attachments || index == VK_ATTACHMENT_UNUSED || (index >= active_attachments->size())) {
        return nullptr;
    }
    return active_attachments->at(index);
}

void CMD_BUFFER_STATE::AddChild(BASE_NODE *child_node) {
    assert(child_node);
    if (child_node->AddParent(this)) {
        object_bindings.insert(child_node);
    }
}

void CMD_BUFFER_STATE::RemoveChild(BASE_NODE *child_node) {
    assert(child_node);
    child_node->RemoveParent(this);
    object_bindings.erase(child_node);
}

// Reset the command buffer state
//  Maintain the createInfo and set state to CB_NEW, but clear all other state
void CMD_BUFFER_STATE::Reset() {
    ResetUse();
    // Reset CB state (note that createInfo is not cleared)
    memset(&beginInfo, 0, sizeof(VkCommandBufferBeginInfo));
    memset(&inheritanceInfo, 0, sizeof(VkCommandBufferInheritanceInfo));
    hasDrawCmd = false;
    hasTraceRaysCmd = false;
    hasBuildAccelerationStructureCmd = false;
    hasDispatchCmd = false;
    state = CB_NEW;
    commandCount = 0;
    submitCount = 0;
    image_layout_change_count = 1;  // Start at 1. 0 is insert value for validation cache versions, s.t. new == dirty
    status = 0;
    static_status = 0;
    inheritedViewportDepths.clear();
    usedViewportScissorCount = 0;
    pipelineStaticViewportCount = 0;
    pipelineStaticScissorCount = 0;
    viewportMask = 0;
    viewportWithCountMask = 0;
    viewportWithCountCount = 0;
    scissorMask = 0;
    scissorWithCountMask = 0;
    scissorWithCountCount = 0;
    trashedViewportMask = 0;
    trashedScissorMask = 0;
    trashedViewportCount = false;
    trashedScissorCount = false;
    usedDynamicViewportCount = false;
    usedDynamicScissorCount = false;
    primitiveTopology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;

    activeRenderPassBeginInfo = safe_VkRenderPassBeginInfo();
    activeRenderPass = nullptr;
    active_attachments = nullptr;
    active_subpasses = nullptr;
    attachments_view_states.clear();
    activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE;
    activeSubpass = 0;
    broken_bindings.clear();
    waitedEvents.clear();
    events.clear();
    writeEventsBeforeWait.clear();
    activeQueries.clear();
    startedQueries.clear();
    image_layout_map.clear();
    current_vertex_buffer_binding_info.vertex_buffer_bindings.clear();
    vertex_buffer_used = false;
    primaryCommandBuffer = VK_NULL_HANDLE;

    linkedCommandBuffers.clear();
    // Remove reverse command buffer links.
    Invalidate(true);

    queue_submit_functions.clear();
    queue_submit_functions_after_render_pass.clear();
    cmd_execute_commands_functions.clear();
    eventUpdates.clear();
    queryUpdates.clear();

    // Remove object bindings
    for (const auto &obj : object_bindings) {
        obj->RemoveParent(this);
    }
    object_bindings.clear();

    for (auto &item : lastBound) {
        item.Reset();
    }
    // Remove this cmdBuffer's reference from each FrameBuffer's CB ref list
    for (auto &framebuffer : framebuffers) {
        framebuffer->RemoveParent(this);
    }
    framebuffers.clear();
    activeFramebuffer = VK_NULL_HANDLE;
    index_buffer_binding.reset();

    qfo_transfer_image_barriers.Reset();
    qfo_transfer_buffer_barriers.Reset();

    // Clean up the label data
    debug_label.Reset();
    validate_descriptorsets_in_queuesubmit.clear();

    // Best practices info
    small_indexed_draw_call_count = 0;

    transform_feedback_active = false;

    // Remove object bindings
    for (auto *base_obj : object_bindings) {
        RemoveChild(base_obj);
    }
    object_bindings.clear();

    // Clean up the label data
    ResetCmdDebugUtilsLabel(dev_data->report_data, commandBuffer());

    if (dev_data->command_buffer_reset_callback) {
        (*dev_data->command_buffer_reset_callback)(commandBuffer());
    }
}

// Track which resources are in-flight by atomically incrementing their "in_use" count
void CMD_BUFFER_STATE::IncrementResources() {
    submitCount++;

    // TODO : We should be able to remove the NULL look-up checks from the code below as long as
    //  all the corresponding cases are verified to cause CB_INVALID state and the CB_INVALID state
    //  should then be flagged prior to calling this function
    for (auto event : writeEventsBeforeWait) {
        auto event_state = dev_data->GetEventState(event);
        if (event_state) event_state->write_in_use++;
    }
}

// Discussed in details in https://github.com/KhronosGroup/Vulkan-Docs/issues/1081
// Internal discussion and CTS were written to prove that this is not called after an incompatible vkCmdBindPipeline
// "Binding a pipeline with a layout that is not compatible with the push constant layout does not disturb the push constant values"
//
// vkCmdBindDescriptorSet has nothing to do with push constants and don't need to call this after neither
//
// Part of this assumes apps at draw/dispath/traceRays/etc time will have it properly compatabile or else other VU will be triggered
void CMD_BUFFER_STATE::ResetPushConstantDataIfIncompatible(const PIPELINE_LAYOUT_STATE *pipeline_layout_state) {
    if (pipeline_layout_state == nullptr) {
        return;
    }
    if (push_constant_data_ranges == pipeline_layout_state->push_constant_ranges) {
        return;
    }

    push_constant_data_ranges = pipeline_layout_state->push_constant_ranges;
    push_constant_data.clear();
    push_constant_data_update.clear();
    uint32_t size_needed = 0;
    for (const auto &push_constant_range : *push_constant_data_ranges) {
        auto size = push_constant_range.offset + push_constant_range.size;
        size_needed = std::max(size_needed, size);

        auto stage_flags = push_constant_range.stageFlags;
        uint32_t bit_shift = 0;
        while (stage_flags) {
            if (stage_flags & 1) {
                VkShaderStageFlagBits flag = static_cast<VkShaderStageFlagBits>(1 << bit_shift);
                const auto it = push_constant_data_update.find(flag);

                if (it != push_constant_data_update.end()) {
                    if (it->second.size() < push_constant_range.offset) {
                        it->second.resize(push_constant_range.offset, PC_Byte_Not_Set);
                    }
                    if (it->second.size() < size) {
                        it->second.resize(size, PC_Byte_Not_Updated);
                    }
                } else {
                    std::vector<uint8_t> bytes;
                    bytes.resize(push_constant_range.offset, PC_Byte_Not_Set);
                    bytes.resize(size, PC_Byte_Not_Updated);
                    push_constant_data_update[flag] = bytes;
                }
            }
            stage_flags = stage_flags >> 1;
            ++bit_shift;
        }
    }
    push_constant_data.resize(size_needed, 0);
}

void CMD_BUFFER_STATE::Destroy() {
    // Allow any derived class to clean up command buffer state
    if (dev_data->command_buffer_reset_callback) {
        (*dev_data->command_buffer_reset_callback)(commandBuffer());
    }
    if (dev_data->command_buffer_free_callback) {
        (*dev_data->command_buffer_free_callback)(commandBuffer());
    }

    // Remove the cb debug labels
    EraseCmdDebugUtilsLabel(dev_data->report_data, commandBuffer());
    Reset();
    BASE_NODE::Destroy();
}

void CMD_BUFFER_STATE::NotifyInvalidate(const BASE_NODE::NodeList &invalid_nodes, bool unlink) {
    if (state == CB_RECORDING) {
        state = CB_INVALID_INCOMPLETE;
    } else if (state == CB_RECORDED) {
        state = CB_INVALID_COMPLETE;
    }
    assert(!invalid_nodes.empty());
    LogObjectList log_list;
    for (auto *obj : invalid_nodes) {
        log_list.object_list.emplace_back(obj->Handle());
    }
    broken_bindings.emplace(invalid_nodes[0]->Handle(), log_list);

    if (unlink) {
        for (auto *obj : invalid_nodes) {
            object_bindings.erase(obj);
            switch (obj->Type()) {
                case kVulkanObjectTypeCommandBuffer:
                    linkedCommandBuffers.erase(static_cast<CMD_BUFFER_STATE *>(obj));
                    break;
                case kVulkanObjectTypeImage:
                    image_layout_map.erase(static_cast<IMAGE_STATE *>(obj));
                    break;
                default:
                    break;
            }
        }
    }
    BASE_NODE::NotifyInvalidate(invalid_nodes, unlink);
}

const CommandBufferImageLayoutMap& CMD_BUFFER_STATE::GetImageSubresourceLayoutMap() const { return image_layout_map; }

// The const variant only need the image as it is the key for the map
const ImageSubresourceLayoutMap *CMD_BUFFER_STATE::GetImageSubresourceLayoutMap(const IMAGE_STATE &image_state) const {
    auto it = image_layout_map.find(&image_state);
    if (it == image_layout_map.cend()) {
        return nullptr;
    }
    return &it->second;
}

// The non-const variant only needs the image state, as the factory requires it to construct a new entry
ImageSubresourceLayoutMap *CMD_BUFFER_STATE::GetImageSubresourceLayoutMap(const IMAGE_STATE &image_state) {
    auto &layout_map = image_layout_map[&image_state];
    if (!layout_map) {
        // Was an empty slot... fill it in.
        layout_map.emplace(image_state);
    }
    return &layout_map;
}

static bool SetQueryState(QueryObject object, QueryState value, QueryMap *localQueryToStateMap) {
    (*localQueryToStateMap)[object] = value;
    return false;
}

void CMD_BUFFER_STATE::BeginQuery(const QueryObject &query_obj) {
    activeQueries.insert(query_obj);
    startedQueries.insert(query_obj);
    queryUpdates.emplace_back([query_obj](const ValidationStateTracker *device_data, bool do_validate,
                                          VkQueryPool &firstPerfQueryPool, uint32_t perfQueryPass, QueryMap *localQueryToStateMap) {
        SetQueryState(QueryObject(query_obj, perfQueryPass), QUERYSTATE_RUNNING, localQueryToStateMap);
        return false;
    });
}

void CMD_BUFFER_STATE::EndQuery(const QueryObject &query_obj) {
    activeQueries.erase(query_obj);
    queryUpdates.emplace_back([query_obj](const ValidationStateTracker *device_data, bool do_validate,
                                          VkQueryPool &firstPerfQueryPool, uint32_t perfQueryPass, QueryMap *localQueryToStateMap) {
        return SetQueryState(QueryObject(query_obj, perfQueryPass), QUERYSTATE_ENDED, localQueryToStateMap);
    });
}

static bool SetQueryStateMulti(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, uint32_t perfPass, QueryState value,
                               QueryMap *localQueryToStateMap) {
    for (uint32_t i = 0; i < queryCount; i++) {
        QueryObject object = QueryObject(QueryObject(queryPool, firstQuery + i), perfPass);
        (*localQueryToStateMap)[object] = value;
    }
    return false;
}

void CMD_BUFFER_STATE::EndQueries(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
    for (uint32_t slot = firstQuery; slot < (firstQuery + queryCount); slot++) {
        QueryObject query = {queryPool, slot};
        activeQueries.erase(query);
    }
    queryUpdates.emplace_back([queryPool, firstQuery, queryCount](const ValidationStateTracker *device_data, bool do_validate,
                                                                  VkQueryPool &firstPerfQueryPool, uint32_t perfQueryPass,
                                                                  QueryMap *localQueryToStateMap) {
        return SetQueryStateMulti(queryPool, firstQuery, queryCount, perfQueryPass, QUERYSTATE_RESET, localQueryToStateMap);
    });
}

void CMD_BUFFER_STATE::ResetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
    for (uint32_t slot = firstQuery; slot < (firstQuery + queryCount); slot++) {
        QueryObject query = {queryPool, slot};
        resetQueries.insert(query);
    }

    queryUpdates.emplace_back([queryPool, firstQuery, queryCount](const ValidationStateTracker *device_data, bool do_validate,
                                                                  VkQueryPool &firstPerfQueryPool, uint32_t perfQueryPass,
                                                                  QueryMap *localQueryToStateMap) {
        return SetQueryStateMulti(queryPool, firstQuery, queryCount, perfQueryPass, QUERYSTATE_RESET, localQueryToStateMap);
    });
}

void UpdateSubpassAttachments(const safe_VkSubpassDescription2 &subpass, std::vector<SUBPASS_INFO> &subpasses) {
    for (uint32_t index = 0; index < subpass.inputAttachmentCount; ++index) {
        const uint32_t attachment_index = subpass.pInputAttachments[index].attachment;
        if (attachment_index != VK_ATTACHMENT_UNUSED) {
            subpasses[attachment_index].used = true;
            subpasses[attachment_index].usage = VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
            subpasses[attachment_index].layout = subpass.pInputAttachments[index].layout;
        }
    }

    for (uint32_t index = 0; index < subpass.colorAttachmentCount; ++index) {
        const uint32_t attachment_index = subpass.pColorAttachments[index].attachment;
        if (attachment_index != VK_ATTACHMENT_UNUSED) {
            subpasses[attachment_index].used = true;
            subpasses[attachment_index].usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
            subpasses[attachment_index].layout = subpass.pColorAttachments[index].layout;
        }
        if (subpass.pResolveAttachments) {
            const uint32_t attachment_index2 = subpass.pResolveAttachments[index].attachment;
            if (attachment_index2 != VK_ATTACHMENT_UNUSED) {
                subpasses[attachment_index2].used = true;
                subpasses[attachment_index2].usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
                subpasses[attachment_index2].layout = subpass.pResolveAttachments[index].layout;
            }
        }
    }

    if (subpass.pDepthStencilAttachment) {
        const uint32_t attachment_index = subpass.pDepthStencilAttachment->attachment;
        if (attachment_index != VK_ATTACHMENT_UNUSED) {
            subpasses[attachment_index].used = true;
            subpasses[attachment_index].usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
            subpasses[attachment_index].layout = subpass.pDepthStencilAttachment->layout;
        }
    }
}

void CMD_BUFFER_STATE::UpdateAttachmentsView(const VkRenderPassBeginInfo *pRenderPassBegin) {
    auto &attachments = *(active_attachments.get());
    const bool imageless = (activeFramebuffer->createInfo.flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT) ? true : false;
    const VkRenderPassAttachmentBeginInfo *attachment_info_struct = nullptr;
    if (pRenderPassBegin) attachment_info_struct = LvlFindInChain<VkRenderPassAttachmentBeginInfo>(pRenderPassBegin->pNext);

    for (uint32_t i = 0; i < attachments.size(); ++i) {
        if (imageless) {
            if (attachment_info_struct && i < attachment_info_struct->attachmentCount) {
                auto res =
                    attachments_view_states.insert(dev_data->GetShared<IMAGE_VIEW_STATE>(attachment_info_struct->pAttachments[i]));
                attachments[i] = res.first->get();
            }
        } else {
            auto res = attachments_view_states.insert(activeFramebuffer->attachments_view_state[i]);
            attachments[i] = res.first->get();
        }
    }
}

void CMD_BUFFER_STATE::BeginRenderPass(CMD_TYPE cmd_type, const VkRenderPassBeginInfo *pRenderPassBegin,
                                       const VkSubpassContents contents) {
    RecordCmd(cmd_type);
    activeFramebuffer = dev_data->GetShared<FRAMEBUFFER_STATE>(pRenderPassBegin->framebuffer);
    activeRenderPass = dev_data->GetShared<RENDER_PASS_STATE>(pRenderPassBegin->renderPass);
    activeRenderPassBeginInfo = safe_VkRenderPassBeginInfo(pRenderPassBegin);
    activeSubpass = 0;
    activeSubpassContents = contents;

    // Connect this RP to cmdBuffer
    if (!dev_data->disabled[command_buffer_state] && activeRenderPass) {
        AddChild(activeRenderPass.get());
    }

    auto chained_device_group_struct = LvlFindInChain<VkDeviceGroupRenderPassBeginInfo>(pRenderPassBegin->pNext);
    if (chained_device_group_struct) {
        active_render_pass_device_mask = chained_device_group_struct->deviceMask;
    } else {
        active_render_pass_device_mask = initial_device_mask;
    }

    active_subpasses = nullptr;
    active_attachments = nullptr;

    if (activeFramebuffer) {
        framebuffers.insert(activeFramebuffer);

        // Set cb_state->active_subpasses
        active_subpasses = std::make_shared<std::vector<SUBPASS_INFO>>(activeFramebuffer->createInfo.attachmentCount);
        const auto &subpass = activeRenderPass->createInfo.pSubpasses[activeSubpass];
        UpdateSubpassAttachments(subpass, *active_subpasses);

        // Set cb_state->active_attachments & cb_state->attachments_view_states
        active_attachments = std::make_shared<std::vector<IMAGE_VIEW_STATE *>>(activeFramebuffer->createInfo.attachmentCount);
        UpdateAttachmentsView(pRenderPassBegin);

        // Connect this framebuffer and its children to this cmdBuffer
        AddChild(activeFramebuffer.get());
    }
}

void CMD_BUFFER_STATE::NextSubpass(CMD_TYPE cmd_type, VkSubpassContents contents) {
    RecordCmd(cmd_type);
    activeSubpass++;
    activeSubpassContents = contents;

    // Update cb_state->active_subpasses
    if (activeRenderPass && activeFramebuffer) {
        active_subpasses = nullptr;
        active_subpasses = std::make_shared<std::vector<SUBPASS_INFO>>(activeFramebuffer->createInfo.attachmentCount);

        const auto &subpass = activeRenderPass->createInfo.pSubpasses[activeSubpass];
        UpdateSubpassAttachments(subpass, *active_subpasses);
    }
}

void CMD_BUFFER_STATE::EndRenderPass(CMD_TYPE cmd_type) {
    RecordCmd(cmd_type);
    activeRenderPass = nullptr;
    active_attachments = nullptr;
    active_subpasses = nullptr;
    activeSubpass = 0;
    activeFramebuffer = VK_NULL_HANDLE;
}

void CMD_BUFFER_STATE::BeginRendering(CMD_TYPE cmd_type, const VkRenderingInfoKHR *pRenderingInfo) {
    RecordCmd(cmd_type);
    activeRenderPass = std::make_shared<RENDER_PASS_STATE>(pRenderingInfo);

    auto chained_device_group_struct = LvlFindInChain<VkDeviceGroupRenderPassBeginInfo>(pRenderingInfo->pNext);
    if (chained_device_group_struct) {
        active_render_pass_device_mask = chained_device_group_struct->deviceMask;
    } else {
        active_render_pass_device_mask = initial_device_mask;
    }

    activeSubpassContents = ((pRenderingInfo->flags & VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR) ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE);

    active_attachments = nullptr;
    uint32_t attachment_count = (pRenderingInfo->colorAttachmentCount + 2) * 2;

    // Set cb_state->active_attachments & cb_state->attachments_view_states
    active_attachments = std::make_shared<std::vector<IMAGE_VIEW_STATE *>>(attachment_count);
    auto &attachments = *(active_attachments.get());

    for (uint32_t i = 0; i < pRenderingInfo->colorAttachmentCount; ++i) {
        auto& colorAttachment = attachments[GetDynamicColorAttachmentImageIndex(i)];
        auto& colorResolveAttachment = attachments[GetDynamicColorResolveAttachmentImageIndex(i)];
        colorAttachment = nullptr;
        colorResolveAttachment = nullptr;

        if (pRenderingInfo->pColorAttachments[i].imageView != VK_NULL_HANDLE) {
            auto res = attachments_view_states.insert(
                dev_data->GetShared<IMAGE_VIEW_STATE>(pRenderingInfo->pColorAttachments[i].imageView));
            colorAttachment = res.first->get();
            if (pRenderingInfo->pColorAttachments[i].resolveMode != VK_RESOLVE_MODE_NONE &&
                pRenderingInfo->pColorAttachments[i].resolveImageView != VK_NULL_HANDLE) {
                colorResolveAttachment = res.first->get();
            }
        }
    }

    if (pRenderingInfo->pDepthAttachment && pRenderingInfo->pDepthAttachment->imageView != VK_NULL_HANDLE) {
        auto& depthAttachment = attachments[GetDynamicDepthAttachmentImageIndex()];
        auto& depthResolveAttachment = attachments[GetDynamicDepthResolveAttachmentImageIndex()];
        depthAttachment = nullptr;
        depthResolveAttachment = nullptr;

        auto res =
            attachments_view_states.insert(dev_data->GetShared<IMAGE_VIEW_STATE>(pRenderingInfo->pDepthAttachment->imageView));
        depthAttachment = res.first->get();
        if (pRenderingInfo->pDepthAttachment->resolveMode != VK_RESOLVE_MODE_NONE &&
            pRenderingInfo->pDepthAttachment->resolveImageView != VK_NULL_HANDLE) {
            depthResolveAttachment = res.first->get();
        }
    } 

    if (pRenderingInfo->pStencilAttachment && pRenderingInfo->pStencilAttachment->imageView != VK_NULL_HANDLE) {
        auto& stencilAttachment = attachments[GetDynamicStencilAttachmentImageIndex()];
        auto& stencilResolveAttachment = attachments[GetDynamicStencilResolveAttachmentImageIndex()];
        stencilAttachment = nullptr;
        stencilResolveAttachment = nullptr;

        auto res =
            attachments_view_states.insert(dev_data->GetShared<IMAGE_VIEW_STATE>(pRenderingInfo->pStencilAttachment->imageView));
        stencilAttachment = res.first->get();
        if (pRenderingInfo->pStencilAttachment->resolveMode != VK_RESOLVE_MODE_NONE &&
            pRenderingInfo->pStencilAttachment->resolveImageView != VK_NULL_HANDLE) {
            stencilResolveAttachment = res.first->get();
        }
    }
}

void CMD_BUFFER_STATE::Begin(const VkCommandBufferBeginInfo *pBeginInfo) {
    if (CB_RECORDED == state || CB_INVALID_COMPLETE == state) {
        Reset();
    }
    // Set updated state here in case implicit reset occurs above
    state = CB_RECORDING;
    beginInfo = *pBeginInfo;
    if (beginInfo.pInheritanceInfo && (createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY)) {
        inheritanceInfo = *(beginInfo.pInheritanceInfo);
        beginInfo.pInheritanceInfo = &inheritanceInfo;
        // If we are a secondary command-buffer and inheriting.  Update the items we should inherit.
        if ((createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
            (beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
            if (beginInfo.pInheritanceInfo->renderPass) {
                activeRenderPass = dev_data->GetShared<RENDER_PASS_STATE>(beginInfo.pInheritanceInfo->renderPass);
                activeSubpass = beginInfo.pInheritanceInfo->subpass;

                if (beginInfo.pInheritanceInfo->framebuffer) {
                    activeFramebuffer = dev_data->GetShared<FRAMEBUFFER_STATE>(beginInfo.pInheritanceInfo->framebuffer);
                    active_subpasses = nullptr;
                    active_attachments = nullptr;

                    if (activeFramebuffer) {
                        framebuffers.insert(activeFramebuffer);

                        // Set active_subpasses
                        active_subpasses = std::make_shared<std::vector<SUBPASS_INFO>>(activeFramebuffer->createInfo.attachmentCount);
                        const auto& subpass = activeRenderPass->createInfo.pSubpasses[activeSubpass];
                        UpdateSubpassAttachments(subpass, *active_subpasses);

                        // Set active_attachments & attachments_view_states
                        active_attachments =
                            std::make_shared<std::vector<IMAGE_VIEW_STATE*>>(activeFramebuffer->createInfo.attachmentCount);
                        UpdateAttachmentsView(nullptr);

                        // Connect this framebuffer and its children to this cmdBuffer
                        if (!dev_data->disabled[command_buffer_state]) {
                            AddChild(activeFramebuffer.get());
                        }
                    }
                }
            }
            else
            {
                auto inheritance_rendering_info = lvl_find_in_chain<VkCommandBufferInheritanceRenderingInfoKHR>(beginInfo.pInheritanceInfo->pNext);
                if (inheritance_rendering_info) {
                    activeRenderPass = std::make_shared<RENDER_PASS_STATE>(inheritance_rendering_info);
                }
            }

            // Check for VkCommandBufferInheritanceViewportScissorInfoNV (VK_NV_inherited_viewport_scissor)
            auto p_inherited_viewport_scissor_info =
                LvlFindInChain<VkCommandBufferInheritanceViewportScissorInfoNV>(beginInfo.pInheritanceInfo->pNext);
            if (p_inherited_viewport_scissor_info != nullptr && p_inherited_viewport_scissor_info->viewportScissor2D) {
                auto pViewportDepths = p_inherited_viewport_scissor_info->pViewportDepths;
                inheritedViewportDepths.assign(pViewportDepths,
                                               pViewportDepths + p_inherited_viewport_scissor_info->viewportDepthCount);
            }
        }
    }

    auto chained_device_group_struct = LvlFindInChain<VkDeviceGroupCommandBufferBeginInfo>(pBeginInfo->pNext);
    if (chained_device_group_struct) {
        initial_device_mask = chained_device_group_struct->deviceMask;
    } else {
        initial_device_mask = (1 << dev_data->physical_device_count) - 1;
    }
    performance_lock_acquired = dev_data->performance_lock_acquired;
}

void CMD_BUFFER_STATE::End(VkResult result) {
    // Cached validation is specific to a specific recording of a specific command buffer.
    descriptorset_cache.clear();
    validated_descriptor_sets.clear();
    if (VK_SUCCESS == result) {
        state = CB_RECORDED;
    }
}

void CMD_BUFFER_STATE::ExecuteCommands(uint32_t commandBuffersCount, const VkCommandBuffer *pCommandBuffers) {
    RecordCmd(CMD_EXECUTECOMMANDS);
    CMD_BUFFER_STATE *sub_cb_state = NULL;
    for (uint32_t i = 0; i < commandBuffersCount; i++) {
        sub_cb_state = dev_data->Get<CMD_BUFFER_STATE>(pCommandBuffers[i]);
        assert(sub_cb_state);
        if (!(sub_cb_state->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
            if (beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
                // TODO: Because this is a state change, clearing the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT needs to be moved
                // from the validation step to the recording step
                beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
            }
        }

        // Propagate inital layout and current layout state to the primary cmd buffer
        // NOTE: The update/population of the image_layout_map is done in CoreChecks, but for other classes derived from
        // ValidationStateTracker these maps will be empty, so leaving the propagation in the the state tracker should be a no-op
        // for those other classes.
        for (const auto &sub_layout_map_entry : sub_cb_state->image_layout_map) {
            const auto *image_state = sub_layout_map_entry.first;

            auto *cb_subres_map = GetImageSubresourceLayoutMap(*image_state);
            const auto *sub_cb_subres_map = &sub_layout_map_entry.second;
            assert(cb_subres_map && sub_cb_subres_map);  // Non const get and map traversal should never be null
            cb_subres_map->UpdateFrom(*sub_cb_subres_map);
        }

        sub_cb_state->primaryCommandBuffer = commandBuffer();
        linkedCommandBuffers.insert(sub_cb_state);
        AddChild(sub_cb_state);
        for (auto &function : sub_cb_state->queryUpdates) {
            queryUpdates.push_back(function);
        }
        for (auto &function : sub_cb_state->queue_submit_functions) {
            queue_submit_functions.push_back(function);
        }

        // State is trashed after executing secondary command buffers.
        // Importantly, this function runs after CoreChecks::PreCallValidateCmdExecuteCommands.
        trashedViewportMask = ~uint32_t(0);
        trashedScissorMask = ~uint32_t(0);
        trashedViewportCount = true;
        trashedScissorCount = true;
    }
}

void CMD_BUFFER_STATE::PushDescriptorSetState(VkPipelineBindPoint pipelineBindPoint, PIPELINE_LAYOUT_STATE *pipeline_layout,
                                              uint32_t set, uint32_t descriptorWriteCount,
                                              const VkWriteDescriptorSet *pDescriptorWrites) {
    // Short circuit invalid updates
    if (!pipeline_layout || (set >= pipeline_layout->set_layouts.size()) || !pipeline_layout->set_layouts[set] ||
        !pipeline_layout->set_layouts[set]->IsPushDescriptor()) {
        return;
    }

    // We need a descriptor set to update the bindings with, compatible with the passed layout
    const auto &dsl = pipeline_layout->set_layouts[set];
    const auto lv_bind_point = ConvertToLvlBindPoint(pipelineBindPoint);
    auto &last_bound = lastBound[lv_bind_point];
    auto &push_descriptor_set = last_bound.push_descriptor_set;
    // If we are disturbing the current push_desriptor_set clear it
    if (!push_descriptor_set || !CompatForSet(set, last_bound, pipeline_layout->compat_for_set)) {
        last_bound.UnbindAndResetPushDescriptorSet(this, new cvdescriptorset::DescriptorSet(0, nullptr, dsl, 0, dev_data));
    }

    UpdateLastBoundDescriptorSets(pipelineBindPoint, pipeline_layout, set, 1, nullptr, push_descriptor_set.get(), 0, nullptr);
    last_bound.pipeline_layout = pipeline_layout->layout();

    // Now that we have either the new or extant push_descriptor set ... do the write updates against it
    push_descriptor_set->PerformPushDescriptorsUpdate(dev_data, descriptorWriteCount, pDescriptorWrites);
}

// Generic function to handle state update for all CmdDraw* and CmdDispatch* type functions
void CMD_BUFFER_STATE::UpdateStateCmdDrawDispatchType(CMD_TYPE cmd_type, VkPipelineBindPoint bind_point) {
    UpdateDrawState(cmd_type, bind_point);
    hasDispatchCmd = true;
}

// Generic function to handle state update for all CmdDraw* type functions
void CMD_BUFFER_STATE::UpdateStateCmdDrawType(CMD_TYPE cmd_type, VkPipelineBindPoint bind_point) {
    UpdateStateCmdDrawDispatchType(cmd_type, bind_point);
    hasDrawCmd = true;

    // Update the consumed viewport/scissor count.
    uint32_t &used = usedViewportScissorCount;
    used = std::max(used, pipelineStaticViewportCount);
    used = std::max(used, pipelineStaticScissorCount);
    usedDynamicViewportCount |= !!(dynamic_status & CBSTATUS_VIEWPORT_WITH_COUNT_SET);  // !! silences MSVC warn
    usedDynamicScissorCount |= !!(dynamic_status & CBSTATUS_SCISSOR_WITH_COUNT_SET);
}

void CMD_BUFFER_STATE::UpdateDrawState(CMD_TYPE cmd_type, const VkPipelineBindPoint bind_point) {
    RecordCmd(cmd_type);

    const auto lv_bind_point = ConvertToLvlBindPoint(bind_point);
    auto &state = lastBound[lv_bind_point];
    PIPELINE_STATE *pipe = state.pipeline_state;
    if (VK_NULL_HANDLE != state.pipeline_layout) {
        for (const auto &set_binding_pair : pipe->active_slots) {
            uint32_t set_index = set_binding_pair.first;
            // Pull the set node
            cvdescriptorset::DescriptorSet *descriptor_set = state.per_set[set_index].bound_descriptor_set;

            // For the "bindless" style resource usage with many descriptors, need to optimize command <-> descriptor binding

            // TODO: If recreating the reduced_map here shows up in profilinging, need to find a way of sharing with the
            // Validate pass.  Though in the case of "many" descriptors, typically the descriptor count >> binding count
            cvdescriptorset::PrefilterBindRequestMap reduced_map(*descriptor_set, set_binding_pair.second);
            const auto &binding_req_map = reduced_map.FilteredMap(*this, *pipe);

            if (reduced_map.IsManyDescriptors()) {
                // Only update validate binding tags if we meet the "many" criteria in the Prefilter class
                descriptor_set->UpdateValidationCache(*this, *pipe, binding_req_map);
            }

            // We can skip updating the state if "nothing" has changed since the last validation.
            // See CoreChecks::ValidateCmdBufDrawState for more details.
            bool descriptor_set_changed =
                !reduced_map.IsManyDescriptors() ||
                // Update if descriptor set (or contents) has changed
                state.per_set[set_index].validated_set != descriptor_set ||
                state.per_set[set_index].validated_set_change_count != descriptor_set->GetChangeCount() ||
                (!dev_data->disabled[image_layout_validation] &&
                 state.per_set[set_index].validated_set_image_layout_change_count != image_layout_change_count);
            bool need_update = descriptor_set_changed ||
                               // Update if previous bindingReqMap doesn't include new bindingReqMap
                               !std::includes(state.per_set[set_index].validated_set_binding_req_map.begin(),
                                              state.per_set[set_index].validated_set_binding_req_map.end(), binding_req_map.begin(),
                                              binding_req_map.end());

            if (need_update) {
                // Bind this set and its active descriptor resources to the command buffer
                if (!descriptor_set_changed && reduced_map.IsManyDescriptors()) {
                    // Only record the bindings that haven't already been recorded
                    BindingReqMap delta_reqs;
                    std::set_difference(binding_req_map.begin(), binding_req_map.end(),
                                        state.per_set[set_index].validated_set_binding_req_map.begin(),
                                        state.per_set[set_index].validated_set_binding_req_map.end(),
                                        layer_data::insert_iterator<BindingReqMap>(delta_reqs, delta_reqs.begin()));
                    descriptor_set->UpdateDrawState(dev_data, this, cmd_type, pipe, delta_reqs);
                } else {
                    descriptor_set->UpdateDrawState(dev_data, this, cmd_type, pipe, binding_req_map);
                }

                state.per_set[set_index].validated_set = descriptor_set;
                state.per_set[set_index].validated_set_change_count = descriptor_set->GetChangeCount();
                state.per_set[set_index].validated_set_image_layout_change_count = image_layout_change_count;
                if (reduced_map.IsManyDescriptors()) {
                    // Check whether old == new before assigning, the equality check is much cheaper than
                    // freeing and reallocating the map.
                    if (state.per_set[set_index].validated_set_binding_req_map != set_binding_pair.second) {
                        state.per_set[set_index].validated_set_binding_req_map = set_binding_pair.second;
                    }
                } else {
                    state.per_set[set_index].validated_set_binding_req_map = BindingReqMap();
                }
            }
        }
    }
    if (pipe && !pipe->vertex_binding_descriptions_.empty()) {
        vertex_buffer_used = true;
    }
}

// Update pipeline_layout bind points applying the "Pipeline Layout Compatibility" rules.
// One of pDescriptorSets or push_descriptor_set should be nullptr, indicating whether this
// is called for CmdBindDescriptorSets or CmdPushDescriptorSet.
void CMD_BUFFER_STATE::UpdateLastBoundDescriptorSets(VkPipelineBindPoint pipeline_bind_point,
                                                     const PIPELINE_LAYOUT_STATE *pipeline_layout, uint32_t first_set,
                                                     uint32_t set_count, const VkDescriptorSet *pDescriptorSets,
                                                     cvdescriptorset::DescriptorSet *push_descriptor_set,
                                                     uint32_t dynamic_offset_count, const uint32_t *p_dynamic_offsets) {
    assert((pDescriptorSets == nullptr) ^ (push_descriptor_set == nullptr));
    // Defensive
    assert(pipeline_layout);
    if (!pipeline_layout) return;

    uint32_t required_size = first_set + set_count;
    const uint32_t last_binding_index = required_size - 1;
    assert(last_binding_index < pipeline_layout->compat_for_set.size());

    // Some useful shorthand
    const auto lv_bind_point = ConvertToLvlBindPoint(pipeline_bind_point);
    auto &last_bound = lastBound[lv_bind_point];
    auto &pipe_compat_ids = pipeline_layout->compat_for_set;
    const uint32_t current_size = static_cast<uint32_t>(last_bound.per_set.size());

    // We need this three times in this function, but nowhere else
    auto push_descriptor_cleanup = [&last_bound](const cvdescriptorset::DescriptorSet *ds) -> bool {
        if (ds && ds->IsPushDescriptor()) {
            assert(ds == last_bound.push_descriptor_set.get());
            last_bound.push_descriptor_set = nullptr;
            return true;
        }
        return false;
    };

    // Clean up the "disturbed" before and after the range to be set
    if (required_size < current_size) {
        if (last_bound.per_set[last_binding_index].compat_id_for_set != pipe_compat_ids[last_binding_index]) {
            // We're disturbing those after last, we'll shrink below, but first need to check for and cleanup the push_descriptor
            for (auto set_idx = required_size; set_idx < current_size; ++set_idx) {
                if (push_descriptor_cleanup(last_bound.per_set[set_idx].bound_descriptor_set)) break;
            }
        } else {
            // We're not disturbing past last, so leave the upper binding data alone.
            required_size = current_size;
        }
    }

    // We resize if we need more set entries or if those past "last" are disturbed
    if (required_size != current_size) {
        last_bound.per_set.resize(required_size);
    }

    // For any previously bound sets, need to set them to "invalid" if they were disturbed by this update
    for (uint32_t set_idx = 0; set_idx < first_set; ++set_idx) {
        if (last_bound.per_set[set_idx].compat_id_for_set != pipe_compat_ids[set_idx]) {
            push_descriptor_cleanup(last_bound.per_set[set_idx].bound_descriptor_set);
            last_bound.per_set[set_idx].bound_descriptor_set = nullptr;
            last_bound.per_set[set_idx].dynamicOffsets.clear();
            last_bound.per_set[set_idx].compat_id_for_set = pipe_compat_ids[set_idx];
        }
    }

    // Now update the bound sets with the input sets
    const uint32_t *input_dynamic_offsets = p_dynamic_offsets;  // "read" pointer for dynamic offset data
    for (uint32_t input_idx = 0; input_idx < set_count; input_idx++) {
        auto set_idx = input_idx + first_set;  // set_idx is index within layout, input_idx is index within input descriptor sets
        cvdescriptorset::DescriptorSet *descriptor_set =
            push_descriptor_set ? push_descriptor_set : dev_data->GetSetNode(pDescriptorSets[input_idx]);

        // Record binding (or push)
        if (descriptor_set != last_bound.push_descriptor_set.get()) {
            // Only cleanup the push descriptors if they aren't the currently used set.
            push_descriptor_cleanup(last_bound.per_set[set_idx].bound_descriptor_set);
        }
        last_bound.per_set[set_idx].bound_descriptor_set = descriptor_set;
        last_bound.per_set[set_idx].compat_id_for_set = pipe_compat_ids[set_idx];  // compat ids are canonical *per* set index

        if (descriptor_set) {
            auto set_dynamic_descriptor_count = descriptor_set->GetDynamicDescriptorCount();
            // TODO: Add logic for tracking push_descriptor offsets (here or in caller)
            if (set_dynamic_descriptor_count && input_dynamic_offsets) {
                const uint32_t *end_offset = input_dynamic_offsets + set_dynamic_descriptor_count;
                last_bound.per_set[set_idx].dynamicOffsets = std::vector<uint32_t>(input_dynamic_offsets, end_offset);
                input_dynamic_offsets = end_offset;
                assert(input_dynamic_offsets <= (p_dynamic_offsets + dynamic_offset_count));
            } else {
                last_bound.per_set[set_idx].dynamicOffsets.clear();
            }
            if (!descriptor_set->IsPushDescriptor()) {
                // Can't cache validation of push_descriptors
                validated_descriptor_sets.insert(descriptor_set);
            }
        }
    }
}

// Set image layout for given VkImageSubresourceRange struct
void CMD_BUFFER_STATE::SetImageLayout(const IMAGE_STATE &image_state, const VkImageSubresourceRange &image_subresource_range,
                                      VkImageLayout layout, VkImageLayout expected_layout) {
    auto *subresource_map = GetImageSubresourceLayoutMap(image_state);
    assert(subresource_map);  // the non-const getter must return a valid pointer
    if (subresource_map->SetSubresourceRangeLayout(*this, image_subresource_range, layout, expected_layout)) {
        image_layout_change_count++;  // Change the version of this data to force revalidation
    }
    for (const auto *alias_state : image_state.aliasing_images) {
        assert(alias_state);
        // The map state of the aliases should all be in sync, so no need to check the return value
        subresource_map = GetImageSubresourceLayoutMap(*alias_state);
        assert(subresource_map);
        subresource_map->SetSubresourceRangeLayout(*this, image_subresource_range, layout, expected_layout);
    }
}

// Set the initial image layout for all slices of an image view
void CMD_BUFFER_STATE::SetImageViewInitialLayout(const IMAGE_VIEW_STATE &view_state, VkImageLayout layout) {
    if (dev_data->disabled[image_layout_validation]) {
        return;
    }
    IMAGE_STATE *image_state = view_state.image_state.get();
    auto *subresource_map = GetImageSubresourceLayoutMap(*image_state);
    subresource_map->SetSubresourceRangeInitialLayout(*this, layout, view_state);
    for (const auto *alias_state : image_state->aliasing_images) {
        assert(alias_state);
        subresource_map = GetImageSubresourceLayoutMap(*alias_state);
        subresource_map->SetSubresourceRangeInitialLayout(*this, layout, view_state);
    }
}

// Set the initial image layout for a passed non-normalized subresource range
void CMD_BUFFER_STATE::SetImageInitialLayout(const IMAGE_STATE &image_state, const VkImageSubresourceRange &range,
                                             VkImageLayout layout) {
    auto *subresource_map = GetImageSubresourceLayoutMap(image_state);
    assert(subresource_map);
    subresource_map->SetSubresourceRangeInitialLayout(*this, image_state.NormalizeSubresourceRange(range), layout);
    for (const auto *alias_state : image_state.aliasing_images) {
        assert(alias_state);
        subresource_map = GetImageSubresourceLayoutMap(*alias_state);
        assert(subresource_map);
        subresource_map->SetSubresourceRangeInitialLayout(*this, alias_state->NormalizeSubresourceRange(range), layout);
    }
}

void CMD_BUFFER_STATE::SetImageInitialLayout(VkImage image, const VkImageSubresourceRange &range, VkImageLayout layout) {
    const IMAGE_STATE *image_state = dev_data->GetImageState(image);
    if (!image_state) return;
    SetImageInitialLayout(*image_state, range, layout);
}

void CMD_BUFFER_STATE::SetImageInitialLayout(const IMAGE_STATE &image_state, const VkImageSubresourceLayers &layers,
                                             VkImageLayout layout) {
    SetImageInitialLayout(image_state, RangeFromLayers(layers), layout);
}

// Set image layout for all slices of an image view
void CMD_BUFFER_STATE::SetImageViewLayout(const IMAGE_VIEW_STATE &view_state, VkImageLayout layout, VkImageLayout layoutStencil) {
    const IMAGE_STATE *image_state = view_state.image_state.get();

    VkImageSubresourceRange sub_range = view_state.normalized_subresource_range;

    if (sub_range.aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) && layoutStencil != kInvalidLayout) {
        sub_range.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
        SetImageLayout(*image_state, sub_range, layout);
        sub_range.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
        SetImageLayout(*image_state, sub_range, layoutStencil);
    } else {
        SetImageLayout(*image_state, sub_range, layout);
    }
}

void CMD_BUFFER_STATE::RecordCmd(CMD_TYPE cmd_type) { commandCount++; }

void CMD_BUFFER_STATE::RecordStateCmd(CMD_TYPE cmd_type, CBStatusFlags state_bits) {
    RecordCmd(cmd_type);
    status |= state_bits;
    static_status &= ~state_bits;
}

void CMD_BUFFER_STATE::RecordTransferCmd(CMD_TYPE cmd_type, BINDABLE *buf1, BINDABLE *buf2) {
    RecordCmd(cmd_type);
    if (buf1) {
        AddChild(buf1);
    }
    if (buf2) {
        AddChild(buf2);
    }
}

static bool SetEventStageMask(VkEvent event, VkPipelineStageFlags2KHR stageMask, EventToStageMap *localEventToStageMap) {
    (*localEventToStageMap)[event] = stageMask;
    return false;
}

void CMD_BUFFER_STATE::RecordSetEvent(CMD_TYPE cmd_type, VkEvent event, VkPipelineStageFlags2KHR stageMask) {
    RecordCmd(cmd_type);
    if (!dev_data->disabled[command_buffer_state]) {
        auto event_state = dev_data->GetEventState(event);
        if (event_state) {
            AddChild(event_state);
        }
    }
    events.push_back(event);
    if (!waitedEvents.count(event)) {
        writeEventsBeforeWait.push_back(event);
    }
    eventUpdates.emplace_back(
        [event, stageMask](const ValidationStateTracker *device_data, bool do_validate, EventToStageMap *localEventToStageMap) {
            return SetEventStageMask(event, stageMask, localEventToStageMap);
        });
}

void CMD_BUFFER_STATE::RecordResetEvent(CMD_TYPE cmd_type, VkEvent event, VkPipelineStageFlags2KHR stageMask) {
    RecordCmd(cmd_type);
    if (!dev_data->disabled[command_buffer_state]) {
        auto event_state = dev_data->GetEventState(event);
        if (event_state) {
            AddChild(event_state);
        }
    }
    events.push_back(event);
    if (!waitedEvents.count(event)) {
        writeEventsBeforeWait.push_back(event);
    }

    eventUpdates.emplace_back([event](const ValidationStateTracker *, bool do_validate, EventToStageMap *localEventToStageMap) {
        return SetEventStageMask(event, VkPipelineStageFlags2KHR(0), localEventToStageMap);
    });
}

void CMD_BUFFER_STATE::RecordWaitEvents(CMD_TYPE cmd_type, uint32_t eventCount, const VkEvent *pEvents) {
    RecordCmd(cmd_type);
    for (uint32_t i = 0; i < eventCount; ++i) {
        if (!dev_data->disabled[command_buffer_state]) {
            auto event_state = dev_data->GetEventState(pEvents[i]);
            if (event_state) {
                AddChild(event_state);
            }
        }
        waitedEvents.insert(pEvents[i]);
        events.push_back(pEvents[i]);
    }
}

void CMD_BUFFER_STATE::RecordBarriers(uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
                                      uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
                                      uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
    if (dev_data->disabled[command_buffer_state]) return;

    for (uint32_t i = 0; i < bufferMemoryBarrierCount; i++) {
        auto buffer_state = dev_data->GetBufferState(pBufferMemoryBarriers[i].buffer);
        if (buffer_state) {
            AddChild(buffer_state);
        }
    }
    for (uint32_t i = 0; i < imageMemoryBarrierCount; i++) {
        auto image_state = dev_data->GetImageState(pImageMemoryBarriers[i].image);
        if (image_state) {
            AddChild(image_state);
        }
    }
}

void CMD_BUFFER_STATE::RecordBarriers(const VkDependencyInfoKHR &dep_info) {
    if (dev_data->disabled[command_buffer_state]) return;

    for (uint32_t i = 0; i < dep_info.bufferMemoryBarrierCount; i++) {
        auto buffer_state = dev_data->GetBufferState(dep_info.pBufferMemoryBarriers[i].buffer);
        if (buffer_state) {
            AddChild(buffer_state);
        }
    }
    for (uint32_t i = 0; i < dep_info.imageMemoryBarrierCount; i++) {
        auto image_state = dev_data->GetImageState(dep_info.pImageMemoryBarriers[i].image);
        if (image_state) {
            AddChild(image_state);
        }
    }
}

void CMD_BUFFER_STATE::RecordWriteTimestamp(CMD_TYPE cmd_type, VkPipelineStageFlags2KHR pipelineStage, VkQueryPool queryPool,
                                            uint32_t slot) {
    RecordCmd(cmd_type);
    if (dev_data->disabled[query_validation]) return;

    if (!dev_data->disabled[command_buffer_state]) {
        auto pool_state = dev_data->GetQueryPoolState(queryPool);
        AddChild(pool_state);
    }
    QueryObject query = {queryPool, slot};
    EndQuery(query);
}

void CMD_BUFFER_STATE::Submit(uint32_t perf_submit_pass) {
    VkQueryPool first_pool = VK_NULL_HANDLE;
    EventToStageMap local_event_to_stage_map;
    QueryMap local_query_to_state_map;
    for (auto &function : queryUpdates) {
        function(nullptr, /*do_validate*/ false, first_pool, perf_submit_pass, &local_query_to_state_map);
    }

    for (const auto &query_state_pair : local_query_to_state_map) {
        dev_data->queryToStateMap[query_state_pair.first] = query_state_pair.second;
    }

    for (const auto &function : eventUpdates) {
        function(nullptr, /*do_validate*/ false, &local_event_to_stage_map);
    }

    for (const auto &eventStagePair : local_event_to_stage_map) {
        dev_data->Get<EVENT_STATE>(eventStagePair.first)->stageMask = eventStagePair.second;
    }
}

void CMD_BUFFER_STATE::Retire(uint32_t perf_submit_pass) {
    // First perform decrement on general case bound objects
    for (auto event : writeEventsBeforeWait) {
        auto event_state = dev_data->Get<EVENT_STATE>(event);
        if (event_state) {
            event_state->write_in_use--;
        }
    }
    QueryMap local_query_to_state_map;
    VkQueryPool first_pool = VK_NULL_HANDLE;
    for (auto &function : queryUpdates) {
        function(nullptr, /*do_validate*/ false, first_pool, perf_submit_pass, &local_query_to_state_map);
    }

    for (const auto &query_state_pair : local_query_to_state_map) {
        if (query_state_pair.second == QUERYSTATE_ENDED) {
            dev_data->queryToStateMap[query_state_pair.first] = QUERYSTATE_AVAILABLE;
        }
    }
}
