/* Copyright (c) 2015-2026 The Khronos Group Inc.
 * Copyright (c) 2015-2026 Valve Corporation
 * Copyright (c) 2015-2026 LunarG, Inc.
 * Copyright (C) 2015-2026 Google Inc.
 * Copyright (c) 2025 Arm Limited.
 * Modifications Copyright (C) 2020,2025-2026 Advanced Micro Devices, Inc. All rights reserved.
 * Modifications Copyright (C) 2022 RasterGrid Kft.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <algorithm>
#include <vulkan/utility/vk_format_utils.h>
#include <vulkan/vk_enum_string_helper.h>
#include <vulkan/vulkan_core.h>
#include <sstream>
#include <string>
#include <vulkan/utility/vk_struct_helper.hpp>
#include "containers/custom_containers.h"
#include "containers/container_utils.h"
#include "error_message/error_strings.h"
#include "generated/vk_extension_helper.h"
#include "state_tracker/data_graph_pipeline_session_state.h"
#include "state_tracker/shader_stage_state.h"
#include "state_tracker/image_state.h"
#include "state_tracker/buffer_state.h"
#include "state_tracker/tensor_state.h"
#include "state_tracker/device_state.h"
#include "state_tracker/queue_state.h"
#include "state_tracker/cmd_buffer_state.h"
#include "state_tracker/pipeline_state.h"
#include "state_tracker/render_pass_state.h"
#include "state_tracker/ray_tracing_state.h"
#include "state_tracker/shader_object_state.h"
#include "state_tracker/device_generated_commands_state.h"
#include "state_tracker/wsi_state.h"
#include "state_tracker/descriptor_mode.h"
#include "chassis/chassis_modification_state.h"
#include "spirv-tools/optimizer.hpp"
#include "utils/assert_utils.h"
#include "utils/spirv_tools_utils.h"
#include "utils/math_utils.h"

// Used for debugging
#include "utils/keyboard.h"

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

namespace vvl {

DeviceState::DeviceState(DispatchDevice* dev, InstanceState* instance)
    : BaseDevice(dev, instance, LayerObjectTypeStateTracker),
      instance_state(instance),
      special_supported(dev->stateless_device_data.special_supported) {
    physical_device_state = instance_state->Get<vvl::PhysicalDevice>(physical_device).get();
    physical_device_state->has_maintenance9 = dev->stateless_device_data.special_supported.has_maintenance9;
}

DeviceState::~DeviceState() { DestroyObjectMaps(); }

void DeviceState::AddProxy(DeviceProxy& proxy) { proxies.emplace(proxy.container_type, proxy); }

void DeviceState::RemoveProxy(LayerObjectTypeId id) {
    proxies.erase(id);
    // this is used by gpuav abort so it needs to clean up any substates as well
    RemoveSubState(id);
}

// Seperate function so GPU-AV (or other objects) can destroy its substate before it destroys itself (and then the leaked object
// cleanup tries to destroy the substate)
void DeviceState::RemoveSubState(LayerObjectTypeId id) {
    // Currently we have not good way to track all objects that have a substate, so this is a list from manual inspection
    ForEachShared<vvl::CommandBuffer>([id](std::shared_ptr<vvl::CommandBuffer> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::Queue>([id](std::shared_ptr<vvl::Queue> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::Swapchain>([id](std::shared_ptr<vvl::Swapchain> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::ImageView>([id](std::shared_ptr<vvl::ImageView> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::Image>([id](std::shared_ptr<vvl::Image> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::Sampler>([id](std::shared_ptr<vvl::Sampler> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::DescriptorSet>([id](std::shared_ptr<vvl::DescriptorSet> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::BufferView>([id](std::shared_ptr<vvl::BufferView> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::Buffer>([id](std::shared_ptr<vvl::Buffer> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::AccelerationStructureNV>(
        [id](std::shared_ptr<vvl::AccelerationStructureNV> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::AccelerationStructureKHR>(
        [id](std::shared_ptr<vvl::AccelerationStructureKHR> state) { state->RemoveSubState(id); });
    ForEachShared<vvl::ShaderObject>([id](std::shared_ptr<vvl::ShaderObject> state) { state->RemoveSubState(id); });
}

VkDeviceAddress DeviceState::GetBufferDeviceAddressHelper(VkBuffer buffer, const DeviceExtensions* exts) const {
    // GPU-AV needs to pass in the modified extensions, since it may turn on BDA on its own
    if (!exts) {
        exts = &extensions;
    }
    VkBufferDeviceAddressInfo address_info = vku::InitStructHelper();
    address_info.buffer = buffer;

    if (api_version >= VK_API_VERSION_1_2) {
        return DispatchGetBufferDeviceAddress(device, &address_info);
    } else {
        if (IsExtEnabled(exts->vk_khr_buffer_device_address)) {
            return DispatchGetBufferDeviceAddressKHR(device, &address_info);
        } else {
            return 0;
        }
    }
}

small_vector<vvl::Buffer*, 2> DeviceState::GetBuffersByAddressRange(const VkDeviceAddressRangeKHR& address_range,
                                                                    VkBufferUsageFlags2 buffer_usage_flags) const {
    small_vector<vvl::Buffer*, 2> filtered_buffers;

    vvl::span<vvl::Buffer* const> buffers = GetBuffersByAddress(address_range.address);
    for (vvl::Buffer* const buffer : buffers) {
        // address_range.address already belongs to buffer by definition,
        // just check that end address of address_range is inferior to buffer's end address
        if (buffer->deviceAddress + buffer->GetSize() < address_range.address + address_range.size) {
            continue;
        }

        if ((buffer->usage & buffer_usage_flags) == buffer_usage_flags) {
            filtered_buffers.emplace_back(buffer);
        }
    }

    return filtered_buffers;
}

void DeviceState::TrackDeviceAddressRange(vvl::CommandBuffer& cb_state, const vvl::range<VkDeviceAddress> range,
                                          VkBufferUsageFlags2 usage) {
    if (disabled[command_buffer_state]) {
        return;
    }

    // small_vector is here to match the BufferAddressRange state object
    small_vector<vvl::Buffer*, 2> buffers;
    {
        ReadLockGuard guard(buffer_address_lock_);
        const VkDeviceAddress address = range.begin;
        auto found_it = buffer_address_map_.find(address);
        if (found_it != buffer_address_map_.end()) {
            for (vvl::Buffer* found_buffer : found_it->second) {
                if ((found_buffer->usage & usage) == usage && found_buffer->DeviceAddressRange().includes(range)) {
                    buffers.emplace_back(found_buffer);
                }
            }
        }
    }

    // This shouldn't be possible as we validate the address is in a valid buffer range already
    // But if there is already an error, we will still need to guard against this
    if (buffers.empty()) {
        return;
    }

    auto bufer_address_range_states = std::make_shared<vvl::BufferAddressRange>(buffers, range, usage);
    bufer_address_range_states->LinkChildNodes();
    cb_state.AddChild(bufer_address_range_states);
}

// NOTE:  Beware the lifespan of the rp_begin when holding  the return.  If the rp_begin isn't a "safe" copy, "IMAGELESS"
//        attachments won't persist past the API entry point exit.
static std::pair<uint32_t, const VkImageView*> GetFramebufferAttachments(const VkRenderPassBeginInfo& rp_begin,
                                                                         const Framebuffer& fb_state) {
    const VkImageView* attachments = fb_state.create_info.pAttachments;
    uint32_t count = fb_state.create_info.attachmentCount;
    if (fb_state.create_info.flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT) {
        const auto* framebuffer_attachments = vku::FindStructInPNextChain<VkRenderPassAttachmentBeginInfo>(rp_begin.pNext);
        if (framebuffer_attachments) {
            attachments = framebuffer_attachments->pAttachments;
            count = framebuffer_attachments->attachmentCount;
        }
    }
    return std::make_pair(count, attachments);
}

template <typename ImageViewPointer, typename Get>
std::vector<ImageViewPointer> GetAttachmentViewsImpl(const VkRenderPassBeginInfo& rp_begin, const Framebuffer& fb_state,
                                                     const Get& get_fn) {
    std::vector<ImageViewPointer> views;

    const auto count_attachment = GetFramebufferAttachments(rp_begin, fb_state);
    const auto attachment_count = count_attachment.first;
    const auto* attachments = count_attachment.second;
    views.resize(attachment_count, nullptr);
    for (uint32_t i = 0; i < attachment_count; i++) {
        if (attachments[i] != VK_NULL_HANDLE) {
            views[i] = get_fn(attachments[i]);
        }
    }
    return views;
}

std::vector<std::shared_ptr<const ImageView>> DeviceState::GetAttachmentViews(const VkRenderPassBeginInfo& rp_begin,
                                                                              const Framebuffer& fb_state) const {
    auto get_fn = [this](VkImageView handle) { return this->Get<ImageView>(handle); };
    return GetAttachmentViewsImpl<std::shared_ptr<const ImageView>>(rp_begin, fb_state, get_fn);
}

DescriptorSetLayoutId DeviceState::GetCanonicalId(const VkDescriptorSetLayoutCreateInfo* p_create_info) {
    return descriptor_set_layout_canonical_ids_.LookUp(DescriptorSetLayoutDef(*this, p_create_info));
}

#ifdef VK_USE_PLATFORM_ANDROID_KHR
// Android-specific validation that uses types defined only with VK_USE_PLATFORM_ANDROID_KHR
// This could also move into a seperate core_validation_android.cpp file... ?

VkFormatFeatureFlags2 DeviceState::GetExternalFormatFeaturesANDROID(const void* pNext) const {
    VkFormatFeatureFlags2 format_features = 0;
    const uint64_t external_format = GetExternalFormat(pNext);
    if ((0 != external_format)) {
        // VUID 01894 will catch if not found in map
        auto it = ahb_ext_formats_map.find(external_format);
        if (it != ahb_ext_formats_map.end()) {
            format_features = it->second;
        }
    }
    return format_features;
}

void DeviceState::PostCallRecordGetAndroidHardwareBufferPropertiesANDROID(VkDevice device, const struct AHardwareBuffer* buffer,
                                                                          VkAndroidHardwareBufferPropertiesANDROID* pProperties,
                                                                          const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    uint64_t external_format = 0;
    auto ahb_format_props2 = vku::FindStructInPNextChain<VkAndroidHardwareBufferFormatProperties2ANDROID>(pProperties->pNext);
    if (ahb_format_props2) {
        external_format = ahb_format_props2->externalFormat;
        ahb_ext_formats_map.insert(external_format, ahb_format_props2->formatFeatures);
    } else {
        auto ahb_format_props = vku::FindStructInPNextChain<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties->pNext);
        if (ahb_format_props) {
            external_format = ahb_format_props->externalFormat;
            ahb_ext_formats_map.insert(external_format, static_cast<VkFormatFeatureFlags2>(ahb_format_props->formatFeatures));
        }
    }

    // For external format resolve, we need to also track externalFormat with its color attachment property
    if (enabled_features.externalFormatResolve) {
        auto ahb_format_resolve_props =
            vku::FindStructInPNextChain<VkAndroidHardwareBufferFormatResolvePropertiesANDROID>(pProperties->pNext);
        if (ahb_format_resolve_props && external_format != 0) {
            // easy case, caller provided both structs for us
            ahb_ext_resolve_formats_map.insert(external_format, ahb_format_resolve_props->colorAttachmentFormat);
        } else {
            // If caller didn't provide both struct, re-call for them
            VkAndroidHardwareBufferFormatResolvePropertiesANDROID new_ahb_format_resolve_props = vku::InitStructHelper();
            VkAndroidHardwareBufferFormatPropertiesANDROID new_ahb_format_props =
                vku::InitStructHelper(&new_ahb_format_resolve_props);
            VkAndroidHardwareBufferPropertiesANDROID new_ahb_props = vku::InitStructHelper(&new_ahb_format_props);
            DispatchGetAndroidHardwareBufferPropertiesANDROID(device, buffer, &new_ahb_props);
            ahb_ext_resolve_formats_map.insert(new_ahb_format_props.externalFormat,
                                               new_ahb_format_resolve_props.colorAttachmentFormat);
        }
    }
}

#else

VkFormatFeatureFlags2 DeviceState::GetExternalFormatFeaturesANDROID(const void* pNext) const {
    (void)pNext;
    return 0;
}

#endif  // VK_USE_PLATFORM_ANDROID_KHR

VkFormatFeatureFlags2 InstanceState::GetImageFormatFeatures(VkPhysicalDevice physical_device, bool has_format_feature2,
                                                            bool has_drm_modifiers, VkDevice device, VkImage image, VkFormat format,
                                                            VkImageTiling tiling) {
    VkFormatFeatureFlags2 format_features = 0;

    // Add feature support according to Image Format Features (vkspec.html#resources-image-format-features)
    // if format is AHB external format then the features are already set
    if (has_format_feature2) {
        VkDrmFormatModifierPropertiesList2EXT fmt_drm_props = vku::InitStructHelper();
        auto fmt_props_3 = vku::InitStruct<VkFormatProperties3>(has_drm_modifiers ? &fmt_drm_props : nullptr);
        VkFormatProperties2 fmt_props_2 = vku::InitStructHelper(&fmt_props_3);

        DispatchGetPhysicalDeviceFormatProperties2Helper(api_version, physical_device, format, &fmt_props_2);

        fmt_props_3.linearTilingFeatures |= fmt_props_2.formatProperties.linearTilingFeatures;
        fmt_props_3.optimalTilingFeatures |= fmt_props_2.formatProperties.optimalTilingFeatures;
        fmt_props_3.bufferFeatures |= fmt_props_2.formatProperties.bufferFeatures;

        if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
            VkImageDrmFormatModifierPropertiesEXT drm_format_props = vku::InitStructHelper();

            // If the driver returns zero, apparently that means nothing is valid
            // https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/11739
            // https://gitlab.khronos.org/vulkan/vulkan/-/issues/4710
            if (fmt_drm_props.drmFormatModifierCount == 0) {
                return format_features;
            }

            // Find the image modifier
            DispatchGetImageDrmFormatModifierPropertiesEXT(device, image, &drm_format_props);

            std::vector<VkDrmFormatModifierProperties2EXT> drm_mod_props;
            drm_mod_props.resize(fmt_drm_props.drmFormatModifierCount);
            fmt_drm_props.pDrmFormatModifierProperties = &drm_mod_props[0];

            // Second query to have all the modifiers filled
            DispatchGetPhysicalDeviceFormatProperties2Helper(api_version, physical_device, format, &fmt_props_2);

            // Look for the image modifier in the list
            for (uint32_t i = 0; i < fmt_drm_props.drmFormatModifierCount; i++) {
                if (fmt_drm_props.pDrmFormatModifierProperties[i].drmFormatModifier == drm_format_props.drmFormatModifier) {
                    format_features = fmt_drm_props.pDrmFormatModifierProperties[i].drmFormatModifierTilingFeatures;
                    break;
                }
            }
        } else {
            format_features =
                (tiling == VK_IMAGE_TILING_LINEAR) ? fmt_props_3.linearTilingFeatures : fmt_props_3.optimalTilingFeatures;
        }
    } else if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
        VkImageDrmFormatModifierPropertiesEXT drm_format_properties = vku::InitStructHelper();
        DispatchGetImageDrmFormatModifierPropertiesEXT(device, image, &drm_format_properties);

        VkFormatProperties2 format_properties_2 = vku::InitStructHelper();
        VkDrmFormatModifierPropertiesListEXT drm_properties_list = vku::InitStructHelper();
        format_properties_2.pNext = (void*)&drm_properties_list;
        DispatchGetPhysicalDeviceFormatProperties2Helper(api_version, physical_device, format, &format_properties_2);
        std::vector<VkDrmFormatModifierPropertiesEXT> drm_properties;
        drm_properties.resize(drm_properties_list.drmFormatModifierCount);
        drm_properties_list.pDrmFormatModifierProperties = &drm_properties[0];
        DispatchGetPhysicalDeviceFormatProperties2Helper(api_version, physical_device, format, &format_properties_2);

        for (uint32_t i = 0; i < drm_properties_list.drmFormatModifierCount; i++) {
            if (drm_properties_list.pDrmFormatModifierProperties[i].drmFormatModifier == drm_format_properties.drmFormatModifier) {
                format_features = drm_properties_list.pDrmFormatModifierProperties[i].drmFormatModifierTilingFeatures;
                break;
            }
        }
    } else {
        VkFormatProperties format_properties;
        DispatchGetPhysicalDeviceFormatProperties(physical_device, format, &format_properties);
        format_features =
            (tiling == VK_IMAGE_TILING_LINEAR) ? format_properties.linearTilingFeatures : format_properties.optimalTilingFeatures;
    }
    return format_features;
}

std::shared_ptr<Image> DeviceState::CreateImageState(VkImage handle, const VkImageCreateInfo* create_info,
                                                     VkFormatFeatureFlags2 features) {
    return std::make_shared<Image>(*this, handle, create_info, features);
}

std::shared_ptr<Image> DeviceState::CreateImageState(VkImage handle, const VkImageCreateInfo* create_info, VkSwapchainKHR swapchain,
                                                     uint32_t swapchain_index, VkFormatFeatureFlags2 features) {
    return std::make_shared<Image>(*this, handle, create_info, swapchain, swapchain_index, features);
}

void DeviceState::PostCallRecordCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo,
                                            const VkAllocationCallbacks* pAllocator, VkImage* pImage,
                                            const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    VkFormatFeatureFlags2 format_features = 0;
    if (IsExtEnabled(extensions.vk_android_external_memory_android_hardware_buffer)) {
        format_features = GetExternalFormatFeaturesANDROID(pCreateInfo->pNext);
    }
    if (format_features == 0) {
        format_features = instance_state->GetImageFormatFeatures(physical_device, special_supported.vk_khr_format_feature_flags2,
                                                                 IsExtEnabled(extensions.vk_ext_image_drm_format_modifier), device,
                                                                 *pImage, pCreateInfo->format, pCreateInfo->tiling);
    }
    Add(CreateImageState(*pImage, pCreateInfo, format_features));
}

void DeviceState::PreCallRecordDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator,
                                            const RecordObject& record_obj) {
    Destroy<Image>(image);
}

void DeviceState::PostCallRecordCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
                                                   const VkClearColorValue* pColor, uint32_t rangeCount,
                                                   const VkImageSubresourceRange* pRanges, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) {
        return;
    }
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto image_state = Get<Image>(image);
    ASSERT_AND_RETURN(image_state);
    cb_state->AddChild(image_state);

    cb_state->RecordClearColorImage(*image_state, imageLayout, pColor, rangeCount, pRanges, record_obj.location);
}

void DeviceState::PostCallRecordCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
                                                          const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount,
                                                          const VkImageSubresourceRange* pRanges, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) {
        return;
    }
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto image_state = Get<Image>(image);
    ASSERT_AND_RETURN(image_state);
    cb_state->AddChild(image_state);

    cb_state->RecordClearDepthStencilImage(*image_state, imageLayout, pDepthStencil, rangeCount, pRanges, record_obj.location);
}

void DeviceState::PostCallRecordCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
                                                    const VkClearAttachment* pAttachments, uint32_t rectCount,
                                                    const VkClearRect* pRects, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) {
        return;
    }
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordClearAttachments(attachmentCount, pAttachments, rectCount, pRects, record_obj.location);
}

void DeviceState::PostCallRecordCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
                                             VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
                                             const VkImageCopy* pRegions, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_image_state = Get<Image>(srcImage);
    auto dst_image_state = Get<Image>(dstImage);
    ASSERT_AND_RETURN(src_image_state && dst_image_state);
    cb_state->AddChild(src_image_state);
    cb_state->AddChild(dst_image_state);
    cb_state->RecordCopyImage(*src_image_state, *dst_image_state, srcImageLayout, dstImageLayout, regionCount, pRegions,
                              record_obj.location);
}

void DeviceState::PostCallRecordCmdCopyImage2KHR(VkCommandBuffer commandBuffer, const VkCopyImageInfo2KHR* pCopyImageInfo,
                                                 const RecordObject& record_obj) {
    PostCallRecordCmdCopyImage2(commandBuffer, pCopyImageInfo, record_obj);
}

void DeviceState::PostCallRecordCmdCopyImage2(VkCommandBuffer commandBuffer, const VkCopyImageInfo2* pCopyImageInfo,
                                              const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_image_state = Get<Image>(pCopyImageInfo->srcImage);
    auto dst_image_state = Get<Image>(pCopyImageInfo->dstImage);
    ASSERT_AND_RETURN(src_image_state && dst_image_state);
    cb_state->AddChild(src_image_state);
    cb_state->AddChild(dst_image_state);
    cb_state->RecordCopyImage2(*src_image_state, *dst_image_state, pCopyImageInfo->srcImageLayout, pCopyImageInfo->dstImageLayout,
                               pCopyImageInfo->regionCount, pCopyImageInfo->pRegions, record_obj.location);
}

void DeviceState::PostCallRecordCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
                                                VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
                                                const VkImageResolve* pRegions, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_image_state = Get<Image>(srcImage);
    auto dst_image_state = Get<Image>(dstImage);
    ASSERT_AND_RETURN(src_image_state && dst_image_state);
    cb_state->AddChild(src_image_state);
    cb_state->AddChild(dst_image_state);

    cb_state->RecordResolveImage(*src_image_state, *dst_image_state, regionCount, pRegions, record_obj.location);
}

void DeviceState::PostCallRecordCmdResolveImage2KHR(VkCommandBuffer commandBuffer, const VkResolveImageInfo2KHR* pResolveImageInfo,
                                                    const RecordObject& record_obj) {
    PostCallRecordCmdResolveImage2(commandBuffer, pResolveImageInfo, record_obj);
}

void DeviceState::PostCallRecordCmdResolveImage2(VkCommandBuffer commandBuffer, const VkResolveImageInfo2* pResolveImageInfo,
                                                 const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_image_state = Get<Image>(pResolveImageInfo->srcImage);
    auto dst_image_state = Get<Image>(pResolveImageInfo->dstImage);
    ASSERT_AND_RETURN(src_image_state && dst_image_state);
    cb_state->AddChild(src_image_state);
    cb_state->AddChild(dst_image_state);

    cb_state->RecordResolveImage2(*src_image_state, *dst_image_state, pResolveImageInfo->regionCount, pResolveImageInfo->pRegions,
                                  record_obj.location);
}

void DeviceState::PostCallRecordCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
                                             VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
                                             const VkImageBlit* pRegions, VkFilter filter, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_image_state = Get<Image>(srcImage);
    auto dst_image_state = Get<Image>(dstImage);
    ASSERT_AND_RETURN(src_image_state && dst_image_state);
    cb_state->AddChild(src_image_state);
    cb_state->AddChild(dst_image_state);

    cb_state->RecordBlitImage(*src_image_state, *dst_image_state, srcImageLayout, dstImageLayout, regionCount, pRegions,
                              record_obj.location);
}

void DeviceState::PostCallRecordCmdBlitImage2KHR(VkCommandBuffer commandBuffer, const VkBlitImageInfo2KHR* pBlitImageInfo,
                                                 const RecordObject& record_obj) {
    PostCallRecordCmdBlitImage2(commandBuffer, pBlitImageInfo, record_obj);
}

void DeviceState::PostCallRecordCmdBlitImage2(VkCommandBuffer commandBuffer, const VkBlitImageInfo2* pBlitImageInfo,
                                              const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_image_state = Get<Image>(pBlitImageInfo->srcImage);
    auto dst_image_state = Get<Image>(pBlitImageInfo->dstImage);
    ASSERT_AND_RETURN(src_image_state && dst_image_state);
    cb_state->AddChild(src_image_state);
    cb_state->AddChild(dst_image_state);

    cb_state->RecordBlitImage2(*src_image_state, *dst_image_state, pBlitImageInfo->srcImageLayout, pBlitImageInfo->dstImageLayout,
                               pBlitImageInfo->regionCount, pBlitImageInfo->pRegions, record_obj.location);
}

struct BufferAddressInfillUpdateOps {
    using Map = typename DeviceState::BufferAddressRangeMap;
    using Iterator = typename Map::iterator;
    using Value = typename Map::value_type;
    using Mapped = typename Map::mapped_type;
    using Range = typename Map::key_type;
    void infill(Map& map, const Iterator& pos, const Range& infill_range) const {
        map.insert(pos, Value(infill_range, insert_value));
    }
    void update(const Iterator& pos) const {
        auto& current_buffer_list = pos->second;
        assert(!current_buffer_list.empty());
        const auto buffer_found_it = std::find(current_buffer_list.begin(), current_buffer_list.end(), insert_value[0]);
        if (buffer_found_it == current_buffer_list.end()) {
            if (current_buffer_list.capacity() <= (current_buffer_list.size() + 1)) {
                current_buffer_list.reserve(current_buffer_list.capacity() * 2);
            }
            current_buffer_list.emplace_back(insert_value[0]);
        }
    }
    const Mapped& insert_value;
};

std::shared_ptr<Buffer> DeviceState::CreateBufferState(VkBuffer handle, const VkBufferCreateInfo* create_info) {
    return std::make_shared<Buffer>(*this, handle, create_info);
}

std::shared_ptr<vvl::Tensor> DeviceState::CreateTensorState(VkTensorARM handle, const VkTensorCreateInfoARM* create_info) {
    return std::make_shared<vvl::Tensor>(*this, handle, create_info);
}

void DeviceState::PostCallRecordCreateTensorARM(VkDevice device, const VkTensorCreateInfoARM* pCreateInfo,
                                                const VkAllocationCallbacks* pAllocator, VkTensorARM* pTensor,
                                                const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) return;
    std::shared_ptr<vvl::Tensor> tensor_state = CreateTensorState(*pTensor, pCreateInfo);
    Add(std::move(tensor_state));
}

void DeviceState::PreCallRecordDestroyTensorARM(VkDevice device, VkTensorARM tensor, const VkAllocationCallbacks* pAllocator,
                                                const RecordObject& record_obj) {
    Destroy<Tensor>(tensor);
}

void DeviceState::PostCallRecordBindTensorMemoryARM(VkDevice device, uint32_t bindInfoCount,
                                                    const VkBindTensorMemoryInfoARM* pBindInfos, const RecordObject& record_obj) {
    if (VK_SUCCESS != record_obj.result) return;
    for (uint32_t i = 0; i < bindInfoCount; i++) {
        auto tensor_state = Get<vvl::Tensor>(pBindInfos[i].tensor);
        auto mem_info = Get<vvl::DeviceMemory>(pBindInfos[i].memory);
        ASSERT_AND_RETURN(tensor_state && mem_info);
        tensor_state->BindMemory(tensor_state.get(), mem_info, pBindInfos[i].memoryOffset, 0u,
                                 tensor_state->MemReqs()->memoryRequirements.size);
    }
}

void DeviceState::PostCallRecordCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo,
                                             const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer,
                                             const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    std::shared_ptr<Buffer> buffer_state = CreateBufferState(*pBuffer, pCreateInfo);

    const auto* opaque_capture_address = vku::FindStructInPNextChain<VkBufferOpaqueCaptureAddressCreateInfo>(pCreateInfo->pNext);
    if (opaque_capture_address && (opaque_capture_address->opaqueCaptureAddress != 0)) {
        WriteLockGuard guard(buffer_address_lock_);
        // address is used for GPU-AV and ray tracing buffer validation
        buffer_state->deviceAddress = opaque_capture_address->opaqueCaptureAddress;
        const vvl::range<VkDeviceAddress> address_range = buffer_state->DeviceAddressRange();

        BufferAddressInfillUpdateOps ops{{buffer_state.get()}};
        sparse_container::infill_update_range(buffer_address_map_, address_range, ops);
    }

    RecordCreateDescriptorBuffer(*buffer_state, *pCreateInfo);

    Add(std::move(buffer_state));
}

std::shared_ptr<BufferView> DeviceState::CreateBufferViewState(const std::shared_ptr<Buffer>& buffer, VkBufferView handle,
                                                               const VkBufferViewCreateInfo* create_info,
                                                               VkFormatFeatureFlags2 format_features) {
    return std::make_shared<BufferView>(buffer, handle, create_info, format_features);
}

void DeviceState::PostCallRecordCreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo,
                                                 const VkAllocationCallbacks* pAllocator, VkBufferView* pView,
                                                 const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto buffer_state = Get<Buffer>(pCreateInfo->buffer);

    VkFormatFeatureFlags2 buffer_features;
    if (special_supported.vk_khr_format_feature_flags2) {
        VkFormatProperties3 fmt_props_3 = vku::InitStructHelper();
        VkFormatProperties2 fmt_props_2 = vku::InitStructHelper(&fmt_props_3);
        DispatchGetPhysicalDeviceFormatProperties2Helper(api_version, physical_device, pCreateInfo->format, &fmt_props_2);
        buffer_features = fmt_props_3.bufferFeatures | fmt_props_2.formatProperties.bufferFeatures;
    } else {
        VkFormatProperties format_properties;
        DispatchGetPhysicalDeviceFormatProperties(physical_device, pCreateInfo->format, &format_properties);
        buffer_features = format_properties.bufferFeatures;
    }

    Add(CreateBufferViewState(buffer_state, *pView, pCreateInfo, buffer_features));
}

std::shared_ptr<vvl::DataGraphPipelineSession> DeviceState::CreateDataGraphPipelineSessionState(
    VkDataGraphPipelineSessionARM handle, const VkDataGraphPipelineSessionCreateInfoARM* pCreateInfo) {
    return std::make_shared<vvl::DataGraphPipelineSession>(*this, handle, pCreateInfo);
}

void DeviceState::PostCallRecordCreateDataGraphPipelineSessionARM(VkDevice device,
                                                                  const VkDataGraphPipelineSessionCreateInfoARM* pCreateInfo,
                                                                  const VkAllocationCallbacks* pAllocator,
                                                                  VkDataGraphPipelineSessionARM* pSession,
                                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) return;
    std::shared_ptr<vvl::DataGraphPipelineSession> pipeline_session_state =
        CreateDataGraphPipelineSessionState(*pSession, pCreateInfo);
    Add(std::move(pipeline_session_state));
}

void DeviceState::PostCallRecordBindDataGraphPipelineSessionMemoryARM(VkDevice device, uint32_t bindInfoCount,
                                                                      const VkBindDataGraphPipelineSessionMemoryInfoARM* pBindInfos,
                                                                      const RecordObject& record_obj) {
    if (VK_SUCCESS != record_obj.result) {
        return;
    }
    for (uint32_t i = 0; i < bindInfoCount; i++) {
        auto& bind_info = pBindInfos[i];
        auto session_state = Get<vvl::DataGraphPipelineSession>(bind_info.session);
        if (session_state) {
            auto mem_info = std::shared_ptr<vvl::DeviceMemory>(Get<vvl::DeviceMemory>(bind_info.memory));
            vvl::MemoryBinding binding = {mem_info, bind_info.memoryOffset, 0};
            session_state->AddBoundMemory(bind_info.bindPoint, binding);
        }
    }
}

std::shared_ptr<ImageView> DeviceState::CreateImageViewState(const std::shared_ptr<Image>& image_state, VkImageView handle,
                                                             const VkImageViewCreateInfo* create_info,
                                                             VkFormatFeatureFlags2 format_features,
                                                             const VkFilterCubicImageViewImageFormatPropertiesEXT& cubic_props) {
    return std::make_shared<ImageView>(*this, image_state, handle, create_info, format_features, cubic_props);
}

void DeviceState::PostCallRecordCreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo,
                                                const VkAllocationCallbacks* pAllocator, VkImageView* pView,
                                                const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto image_state = Get<Image>(pCreateInfo->image);
    ASSERT_AND_RETURN(image_state);

    VkFormatFeatureFlags2 format_features = 0;
    if (image_state->HasAHBFormat() == true) {
        // The ImageView uses same Image's format feature since they share same AHB
        format_features = image_state->format_features;
    } else {
        format_features =
            instance_state->GetImageFormatFeatures(physical_device, special_supported.vk_khr_format_feature_flags2,
                                                   IsExtEnabled(extensions.vk_ext_image_drm_format_modifier), device,
                                                   image_state->VkHandle(), pCreateInfo->format, image_state->GetTiling());
    }

    // filter_cubic_props is used in CmdDraw validation. But it takes a lot of performance if it does in CmdDraw.
    VkFilterCubicImageViewImageFormatPropertiesEXT filter_cubic_props = vku::InitStructHelper();
    if (IsExtEnabled(extensions.vk_ext_filter_cubic)) {
        VkPhysicalDeviceImageViewImageFormatInfoEXT imageview_format_info = vku::InitStructHelper();
        imageview_format_info.imageViewType = pCreateInfo->viewType;
        VkPhysicalDeviceImageFormatInfo2 image_format_info = vku::InitStructHelper(&imageview_format_info);
        image_format_info.type = image_state->GetImageType();
        image_format_info.format = image_state->GetFormat();
        image_format_info.tiling = image_state->GetTiling();
        auto usage_create_info = vku::FindStructInPNextChain<VkImageViewUsageCreateInfo>(pCreateInfo->pNext);
        image_format_info.usage = usage_create_info ? usage_create_info->usage : (VkImageUsageFlags)image_state->usage;
        image_format_info.flags = (VkImageCreateFlags)image_state->create_flags;

        VkImageFormatProperties2 image_format_properties = vku::InitStructHelper(&filter_cubic_props);

        DispatchGetPhysicalDeviceImageFormatProperties2Helper(api_version, physical_device, &image_format_info,
                                                              &image_format_properties);
    }

    Add(CreateImageViewState(image_state, *pView, pCreateInfo, format_features, filter_cubic_props));
}

void DeviceState::PostCallRecordCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
                                              uint32_t regionCount, const VkBufferCopy* pRegions, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_buffer_state = Get<Buffer>(srcBuffer);
    auto dst_buffer_state = Get<Buffer>(dstBuffer);
    ASSERT_AND_RETURN(src_buffer_state && dst_buffer_state);
    cb_state->AddChild(src_buffer_state);
    cb_state->AddChild(dst_buffer_state);
    cb_state->RecordCopyBuffer(*src_buffer_state, *dst_buffer_state, regionCount, pRegions, record_obj.location);
}

void DeviceState::PostCallRecordCmdCopyTensorARM(VkCommandBuffer commandBuffer, const VkCopyTensorInfoARM* pCopyTensorInfo,
                                                 const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_tensor_state = Get<Tensor>(pCopyTensorInfo->srcTensor);
    auto dst_tensor_state = Get<Tensor>(pCopyTensorInfo->dstTensor);
    ASSERT_AND_RETURN(src_tensor_state && dst_tensor_state);
    cb_state->AddChild(src_tensor_state);
    cb_state->AddChild(dst_tensor_state);
}

std::shared_ptr<vvl::TensorView> DeviceState::CreateTensorViewState(const std::shared_ptr<vvl::Tensor>& tensor,
                                                                    VkTensorViewARM handle,
                                                                    const VkTensorViewCreateInfoARM* pCreateInfo) {
    return std::make_shared<vvl::TensorView>(tensor, handle, pCreateInfo);
}

void DeviceState::PostCallRecordCreateTensorViewARM(VkDevice device, const VkTensorViewCreateInfoARM* pCreateInfo,
                                                    const VkAllocationCallbacks* pAllocator, VkTensorViewARM* pView,
                                                    const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) return;

    auto tensor_state = Get<vvl::Tensor>(pCreateInfo->tensor);
    ASSERT_AND_RETURN(tensor_state);
    Add(CreateTensorViewState(tensor_state, *pView, pCreateInfo));
}

void DeviceState::PreCallRecordDestroyTensorViewARM(VkDevice device, VkTensorViewARM tensorView,
                                                    const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<TensorView>(tensorView);
}

void DeviceState::PostCallRecordCmdCopyBuffer2KHR(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2KHR* pCopyBufferInfo,
                                                  const RecordObject& record_obj) {
    PostCallRecordCmdCopyBuffer2(commandBuffer, pCopyBufferInfo, record_obj);
}

void DeviceState::PostCallRecordCmdCopyBuffer2(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2* pCopyBufferInfo,
                                               const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_buffer_state = Get<Buffer>(pCopyBufferInfo->srcBuffer);
    auto dst_buffer_state = Get<Buffer>(pCopyBufferInfo->dstBuffer);
    ASSERT_AND_RETURN(src_buffer_state && dst_buffer_state);
    cb_state->AddChild(src_buffer_state);
    cb_state->AddChild(dst_buffer_state);
    cb_state->RecordCopyBuffer2(*src_buffer_state, *dst_buffer_state, pCopyBufferInfo->regionCount, pCopyBufferInfo->pRegions,
                                record_obj.location);
}

void DeviceState::PreCallRecordDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator,
                                                const RecordObject& record_obj) {
    Destroy<ImageView>(imageView);
}

void DeviceState::PreCallRecordDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator,
                                             const RecordObject& record_obj) {
    if (auto buffer_state = Get<Buffer>(buffer)) {
        WriteLockGuard guard(buffer_address_lock_);

        RecordDestoryDescriptorBuffer(*buffer_state);

        if (buffer_state->deviceAddress != 0) {
            const vvl::range<VkDeviceAddress> address_range = buffer_state->DeviceAddressRange();

            buffer_address_map_.erase_range_or_touch(address_range, [buffer_state_raw = buffer_state.get()](auto& buffers) {
                assert(!buffers.empty());
                const auto buffer_found_it = std::find(buffers.begin(), buffers.end(), buffer_state_raw);
                assert(buffer_found_it != buffers.end());

                // If buffer list only has one element, remove range map entry.
                // Else, remove target buffer from buffer list.
                if (buffer_found_it != buffers.end()) {
                    if (buffers.size() == 1) {
                        return true;
                    } else {
                        assert(!buffers.empty());
                        const size_t i = std::distance(buffers.begin(), buffer_found_it);
                        std::swap(buffers[i], buffers[buffers.size() - 1]);
                        buffers.resize(buffers.size() - 1);
                        return false;
                    }
                }

                return false;
            });
        }
    }
    Destroy<Buffer>(buffer);
}

void DeviceState::PreCallRecordDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator,
                                                 const RecordObject& record_obj) {
    Destroy<BufferView>(bufferView);
}

static constexpr VkBufferUsageFlags2 kDescriptorBufferUsages =
    VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT | VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT;

void DeviceState::RecordCreateDescriptorBuffer(const vvl::Buffer& buffer_state, const VkBufferCreateInfo& create_info) {
    if ((buffer_state.usage & kDescriptorBufferUsages) != 0) {
        const VkDeviceSize size = create_info.size;
        descriptor_buffer_address_space.all += size;

        if ((buffer_state.usage & VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT) != 0) {
            descriptor_buffer_address_space.resource += size;
        }

        if ((buffer_state.usage & VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT) != 0) {
            descriptor_buffer_address_space.sampler += size;
        }
    }
}

void DeviceState::RecordDestoryDescriptorBuffer(const vvl::Buffer& buffer_state) {
    if ((buffer_state.usage & kDescriptorBufferUsages) != 0) {
        const VkDeviceSize size = buffer_state.GetSize();
        descriptor_buffer_address_space.all -= size;

        if (buffer_state.usage & VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT) {
            descriptor_buffer_address_space.resource -= size;
        }

        if (buffer_state.usage & VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT) {
            descriptor_buffer_address_space.sampler -= size;
        }
    }
}

void DeviceState::PostCallRecordCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
                                              VkDeviceSize size, uint32_t data, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto buffer_state = Get<Buffer>(dstBuffer);
    ASSERT_AND_RETURN(buffer_state);
    cb_state->AddChild(buffer_state);
    cb_state->RecordFillBuffer(*buffer_state, dstOffset, size, record_obj.location);
}

void DeviceState::PostCallRecordCmdFillMemoryKHR(VkCommandBuffer commandBuffer, const VkDeviceAddressRangeKHR* pDstRange,
                                                 VkAddressCommandFlagsKHR dstFlags, uint32_t data, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) {
        return;
    }

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordFillMemory(*pDstRange, record_obj.location);

    TrackDeviceAddressRange(*cb_state, pDstRange->address, pDstRange->size, VK_BUFFER_USAGE_2_TRANSFER_DST_BIT);
}

void DeviceState::PostCallRecordCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
                                                     VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions,
                                                     const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_image_state = Get<Image>(srcImage);
    auto dst_buffer_state = Get<Buffer>(dstBuffer);
    ASSERT_AND_RETURN(src_image_state && dst_buffer_state);
    cb_state->AddChild(src_image_state);
    cb_state->AddChild(dst_buffer_state);

    cb_state->RecordCopyImageToBuffer(*src_image_state, *dst_buffer_state, srcImageLayout, regionCount, pRegions,
                                      record_obj.location);
}

void DeviceState::PostCallRecordCmdCopyImageToBuffer2KHR(VkCommandBuffer commandBuffer,
                                                         const VkCopyImageToBufferInfo2KHR* pCopyImageToBufferInfo,
                                                         const RecordObject& record_obj) {
    PostCallRecordCmdCopyImageToBuffer2(commandBuffer, pCopyImageToBufferInfo, record_obj);
}

void DeviceState::PostCallRecordCmdCopyImageToBuffer2(VkCommandBuffer commandBuffer,
                                                      const VkCopyImageToBufferInfo2* pCopyImageToBufferInfo,
                                                      const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_image_state = Get<Image>(pCopyImageToBufferInfo->srcImage);
    auto dst_buffer_state = Get<Buffer>(pCopyImageToBufferInfo->dstBuffer);
    ASSERT_AND_RETURN(src_image_state && dst_buffer_state);
    cb_state->AddChild(src_image_state);
    cb_state->AddChild(dst_buffer_state);

    cb_state->RecordCopyImageToBuffer2(*src_image_state, *dst_buffer_state, pCopyImageToBufferInfo->srcImageLayout,
                                       pCopyImageToBufferInfo->regionCount, pCopyImageToBufferInfo->pRegions, record_obj.location);
}

void DeviceState::PostCallRecordCmdCopyMemoryToImageKHR(VkCommandBuffer commandBuffer,
                                                        const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo,
                                                        const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto dst_image_state = Get<Image>(pCopyMemoryInfo->image);
    ASSERT_AND_RETURN(dst_image_state);
    cb_state->AddChild(dst_image_state);

    cb_state->RecordCopyMemoryToImage(*dst_image_state, pCopyMemoryInfo->regionCount, pCopyMemoryInfo->pRegions,
                                      record_obj.location);
    for (uint32_t i = 0; i < pCopyMemoryInfo->regionCount; ++i) {
        TrackDeviceAddressRange(*cb_state, pCopyMemoryInfo->pRegions[i].addressRange.address,
                                pCopyMemoryInfo->pRegions[i].addressRange.size, VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT);
    }
}

void DeviceState::PostCallRecordCmdCopyImageToMemoryKHR(VkCommandBuffer commandBuffer,
                                                        const VkCopyDeviceMemoryImageInfoKHR* pCopyMemoryInfo,
                                                        const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_image_state = Get<Image>(pCopyMemoryInfo->image);
    ASSERT_AND_RETURN(src_image_state);
    cb_state->AddChild(src_image_state);

    cb_state->RecordCopyImageToMemory(*src_image_state, pCopyMemoryInfo->regionCount, pCopyMemoryInfo->pRegions,
                                      record_obj.location);
    for (uint32_t i = 0; i < pCopyMemoryInfo->regionCount; ++i) {
        TrackDeviceAddressRange(*cb_state, pCopyMemoryInfo->pRegions[i].addressRange.address,
                                pCopyMemoryInfo->pRegions[i].addressRange.size, VK_BUFFER_USAGE_2_TRANSFER_DST_BIT);
    }
}

void DeviceState::PostCallRecordCmdCopyMemoryKHR(VkCommandBuffer commandBuffer, const VkCopyDeviceMemoryInfoKHR* pCopyMemoryInfo,
                                                 const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCopyMemory(pCopyMemoryInfo->regionCount, pCopyMemoryInfo->pRegions, record_obj.location);
    for (uint32_t i = 0; i < pCopyMemoryInfo->regionCount; ++i) {
        TrackDeviceAddressRange(*cb_state, pCopyMemoryInfo->pRegions[i].dstRange.address,
                                pCopyMemoryInfo->pRegions[i].dstRange.size, VK_BUFFER_USAGE_2_TRANSFER_SRC_BIT);
    }
}

void DeviceState::PostCallRecordCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
                                                     VkImageLayout dstImageLayout, uint32_t regionCount,
                                                     const VkBufferImageCopy* pRegions, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_buffer_state = Get<Buffer>(srcBuffer);
    auto dst_image_state = Get<Image>(dstImage);
    ASSERT_AND_RETURN(src_buffer_state && dst_image_state);
    cb_state->AddChild(src_buffer_state);
    cb_state->AddChild(dst_image_state);

    cb_state->RecordCopyBufferToImage(*src_buffer_state, *dst_image_state, dstImageLayout, regionCount, pRegions,
                                      record_obj.location);
}

void DeviceState::PostCallRecordCmdCopyBufferToImage2KHR(VkCommandBuffer commandBuffer,
                                                         const VkCopyBufferToImageInfo2KHR* pCopyBufferToImageInfo,
                                                         const RecordObject& record_obj) {
    PostCallRecordCmdCopyBufferToImage2(commandBuffer, pCopyBufferToImageInfo, record_obj);
}

void DeviceState::PostCallRecordCmdCopyBufferToImage2(VkCommandBuffer commandBuffer,
                                                      const VkCopyBufferToImageInfo2* pCopyBufferToImageInfo,
                                                      const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_buffer_state = Get<Buffer>(pCopyBufferToImageInfo->srcBuffer);
    auto dst_image_state = Get<Image>(pCopyBufferToImageInfo->dstImage);
    ASSERT_AND_RETURN(src_buffer_state && dst_image_state);
    cb_state->AddChild(src_buffer_state);
    cb_state->AddChild(dst_image_state);

    cb_state->RecordCopyBufferToImage2(*src_buffer_state, *dst_image_state, pCopyBufferToImageInfo->dstImageLayout,
                                       pCopyBufferToImageInfo->regionCount, pCopyBufferToImageInfo->pRegions, record_obj.location);
}

// Gets union of all features defined by Potential Format Features
// except, does not handle the external format case for AHB as that only can be used for sampled images
VkFormatFeatureFlags2 DeviceState::GetPotentialFormatFeatures(VkFormat format) const {
    VkFormatFeatureFlags2 format_features = 0;

    if (format != VK_FORMAT_UNDEFINED) {
        if (special_supported.vk_khr_format_feature_flags2) {
            VkDrmFormatModifierPropertiesList2EXT fmt_drm_props = vku::InitStructHelper();
            auto fmt_props_3 = vku::InitStruct<VkFormatProperties3>(
                IsExtEnabled(extensions.vk_ext_image_drm_format_modifier) ? &fmt_drm_props : nullptr);
            VkFormatProperties2 fmt_props_2 = vku::InitStructHelper(&fmt_props_3);

            DispatchGetPhysicalDeviceFormatProperties2Helper(api_version, physical_device, format, &fmt_props_2);

            format_features |= fmt_props_2.formatProperties.linearTilingFeatures;
            format_features |= fmt_props_2.formatProperties.optimalTilingFeatures;

            format_features |= fmt_props_3.linearTilingFeatures;
            format_features |= fmt_props_3.optimalTilingFeatures;

            if (IsExtEnabled(extensions.vk_ext_image_drm_format_modifier)) {
                std::vector<VkDrmFormatModifierProperties2EXT> drm_properties;
                drm_properties.resize(fmt_drm_props.drmFormatModifierCount);
                fmt_drm_props.pDrmFormatModifierProperties = drm_properties.data();
                DispatchGetPhysicalDeviceFormatProperties2Helper(api_version, physical_device, format, &fmt_props_2);

                for (uint32_t i = 0; i < fmt_drm_props.drmFormatModifierCount; i++) {
                    format_features |= fmt_drm_props.pDrmFormatModifierProperties[i].drmFormatModifierTilingFeatures;
                }
            }
        } else {
            VkFormatProperties format_properties;
            DispatchGetPhysicalDeviceFormatProperties(physical_device, format, &format_properties);
            format_features |= format_properties.linearTilingFeatures;
            format_features |= format_properties.optimalTilingFeatures;

            if (IsExtEnabled(extensions.vk_ext_image_drm_format_modifier)) {
                VkDrmFormatModifierPropertiesListEXT fmt_drm_props = vku::InitStructHelper();
                VkFormatProperties2 fmt_props_2 = vku::InitStructHelper(&fmt_drm_props);

                DispatchGetPhysicalDeviceFormatProperties2Helper(api_version, physical_device, format, &fmt_props_2);

                std::vector<VkDrmFormatModifierPropertiesEXT> drm_properties;
                drm_properties.resize(fmt_drm_props.drmFormatModifierCount);
                fmt_drm_props.pDrmFormatModifierProperties = drm_properties.data();
                DispatchGetPhysicalDeviceFormatProperties2Helper(api_version, physical_device, format, &fmt_props_2);

                for (uint32_t i = 0; i < fmt_drm_props.drmFormatModifierCount; i++) {
                    format_features |= fmt_drm_props.pDrmFormatModifierProperties[i].drmFormatModifierTilingFeatures;
                }
            }
        }
    }

    return format_features;
}

std::shared_ptr<Queue> DeviceState::CreateQueue(VkQueue handle, uint32_t family_index, uint32_t queue_index,
                                                VkDeviceQueueCreateFlags flags,
                                                const VkQueueFamilyProperties& queueFamilyProperties) {
    return std::make_shared<Queue>(*this, handle, family_index, queue_index, flags, queueFamilyProperties);
}

void DeviceState::FinishDeviceSetup(const VkDeviceCreateInfo* pCreateInfo, const Location& loc) {
    const auto* device_group_ci = vku::FindStructInPNextChain<VkDeviceGroupDeviceCreateInfo>(pCreateInfo->pNext);
    if (device_group_ci) {
        physical_device_count = device_group_ci->physicalDeviceCount;
        if (physical_device_count == 0) {
            physical_device_count =
                1;  // see https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkDeviceGroupDeviceCreateInfo.html
        }
        device_group_create_info = *device_group_ci;
    } else {
        device_group_create_info = vku::InitStructHelper();
        device_group_create_info.physicalDeviceCount = 1;  // see previous VkDeviceGroupDeviceCreateInfo link
        device_group_create_info.pPhysicalDevices = &physical_device;
        physical_device_count = 1;
    }

    // Store queue family data
    if (pCreateInfo->pQueueCreateInfos != nullptr) {
        uint32_t num_queue_families = 0;
        DispatchGetPhysicalDeviceQueueFamilyProperties(physical_device, &num_queue_families, nullptr);
        std::vector<VkQueueFamilyProperties> queue_family_properties_list(num_queue_families);
        DispatchGetPhysicalDeviceQueueFamilyProperties(physical_device, &num_queue_families, queue_family_properties_list.data());

        for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; ++i) {
            const VkDeviceQueueCreateInfo& queue_create_info = pCreateInfo->pQueueCreateInfos[i];
            queue_family_index_set.insert(queue_create_info.queueFamilyIndex);
            device_queue_info_list.emplace_back(
                DeviceQueueInfo{i, queue_create_info.queueFamilyIndex, queue_create_info.flags, queue_create_info.queueCount});
        }
        for (const auto& queue_info : device_queue_info_list) {
            for (uint32_t i = 0; i < queue_info.queue_count; i++) {
                VkQueue queue = VK_NULL_HANDLE;
                // vkGetDeviceQueue2() was added in vulkan 1.1, and there was never a KHR version of it.
                if (api_version >= VK_API_VERSION_1_1 && queue_info.flags != 0) {
                    VkDeviceQueueInfo2 get_info = vku::InitStructHelper();
                    get_info.flags = queue_info.flags;
                    get_info.queueFamilyIndex = queue_info.queue_family_index;
                    get_info.queueIndex = i;
                    DispatchGetDeviceQueue2(device, &get_info, &queue);
                } else {
                    DispatchGetDeviceQueue(device, queue_info.queue_family_index, i, &queue);
                }
                assert(queue != VK_NULL_HANDLE);
                Add(CreateQueue(queue, queue_info.queue_family_index, i, queue_info.flags,
                                queue_family_properties_list[queue_info.queue_family_index]));
            }
        }
    }

    // Query queue family extension properties
    if (IsExtEnabled(extensions.vk_khr_get_physical_device_properties2)) {
        uint32_t queue_family_count = (uint32_t)physical_device_state->queue_family_properties.size();
        auto& ext_props = queue_family_ext_props;
        ext_props.resize(queue_family_count);

        std::vector<VkQueueFamilyProperties2> props(queue_family_count, vku::InitStruct<VkQueueFamilyProperties2>());

        if (IsExtEnabled(extensions.vk_khr_video_queue)) {
            for (uint32_t i = 0; i < queue_family_count; ++i) {
                ext_props[i].query_result_status_props = vku::InitStructHelper();
                ext_props[i].video_props = vku::InitStructHelper(&ext_props[i].query_result_status_props);
                props[i].pNext = &ext_props[i].video_props;
            }
        }

        DispatchGetPhysicalDeviceQueueFamilyProperties2Helper(api_version, physical_device, &queue_family_count, props.data());
    }

    if (IsExtEnabled(extensions.vk_khr_performance_query)) {
        uint32_t queue_family_count = (uint32_t)physical_device_state->queue_family_properties.size();
        for (uint32_t i = 0; i < queue_family_count; ++i) {
            uint32_t counterCount;
            DispatchEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physical_device, i, &counterCount, nullptr,
                                                                                  nullptr);

            std::unique_ptr<QueueFamilyPerfCounters> queue_family_counters(new QueueFamilyPerfCounters());
            queue_family_counters->counters.resize(counterCount);

            DispatchEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(physical_device, i, &counterCount,
                                                                                  queue_family_counters->counters.data(), nullptr);

            physical_device_state->perf_counters[i] = std::move(queue_family_counters);
        }
    }

    // internal pipeline cache control
    const auto* cache_control = vku::FindStructInPNextChain<VkDevicePipelineBinaryInternalCacheControlKHR>(pCreateInfo->pNext);
    disable_internal_pipeline_cache = cache_control && cache_control->disableInternalCache;

    if (IsExtEnabled(extensions.vk_nv_cooperative_matrix)) {
        uint32_t num_cooperative_matrix_properties_nv = 0;
        DispatchGetPhysicalDeviceCooperativeMatrixPropertiesNV(physical_device, &num_cooperative_matrix_properties_nv, NULL);
        cooperative_matrix_properties_nv.resize(num_cooperative_matrix_properties_nv,
                                                vku::InitStruct<VkCooperativeMatrixPropertiesNV>());

        DispatchGetPhysicalDeviceCooperativeMatrixPropertiesNV(physical_device, &num_cooperative_matrix_properties_nv,
                                                               cooperative_matrix_properties_nv.data());
    }

    if (IsExtEnabled(extensions.vk_khr_cooperative_matrix)) {
        uint32_t num_cooperative_matrix_properties_khr = 0;
        DispatchGetPhysicalDeviceCooperativeMatrixPropertiesKHR(physical_device, &num_cooperative_matrix_properties_khr, NULL);
        cooperative_matrix_properties_khr.resize(num_cooperative_matrix_properties_khr,
                                                 vku::InitStruct<VkCooperativeMatrixPropertiesKHR>());

        DispatchGetPhysicalDeviceCooperativeMatrixPropertiesKHR(physical_device, &num_cooperative_matrix_properties_khr,
                                                                cooperative_matrix_properties_khr.data());
    }

    if (IsExtEnabled(extensions.vk_nv_cooperative_matrix2)) {
        uint32_t num_cooperative_matrix_flexible_dimensions_properties = 0;
        DispatchGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV(
            physical_device, &num_cooperative_matrix_flexible_dimensions_properties, NULL);
        cooperative_matrix_flexible_dimensions_properties.resize(
            num_cooperative_matrix_flexible_dimensions_properties,
            vku::InitStruct<VkCooperativeMatrixFlexibleDimensionsPropertiesNV>());

        DispatchGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV(
            physical_device, &num_cooperative_matrix_flexible_dimensions_properties,
            cooperative_matrix_flexible_dimensions_properties.data());
    }

    if (IsExtEnabled(extensions.vk_nv_cooperative_vector)) {
        uint32_t num_cooperative_vector_properties_nv = 0;
        DispatchGetPhysicalDeviceCooperativeVectorPropertiesNV(physical_device, &num_cooperative_vector_properties_nv, NULL);
        cooperative_vector_properties_nv.resize(num_cooperative_vector_properties_nv,
                                                vku::InitStruct<VkCooperativeVectorPropertiesNV>());

        DispatchGetPhysicalDeviceCooperativeVectorPropertiesNV(physical_device, &num_cooperative_vector_properties_nv,
                                                               cooperative_vector_properties_nv.data());
    }

    if (IsExtEnabled(extensions.vk_arm_data_graph)) {
        uint32_t n_families{0};
        DispatchGetPhysicalDeviceQueueFamilyProperties(physical_device, &n_families, nullptr);
        for (uint32_t i = 0; i < n_families; i++) {
            std::vector<VkQueueFamilyDataGraphPropertiesARM> family_properties;
            uint32_t n_properties{0};
            DispatchGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(physical_device, i, &n_properties, nullptr);
            family_properties.resize(n_properties, vku::InitStruct<VkQueueFamilyDataGraphPropertiesARM>());
            DispatchGetPhysicalDeviceQueueFamilyDataGraphPropertiesARM(physical_device, i, &n_properties, family_properties.data());
            queue_family_data_graph_properties.try_emplace(i, std::move(family_properties));
        }
    }

#if defined(VK_USE_PLATFORM_ANDROID_KHR)
    android_external_format_resolve_null_color_attachment_prop =
        phys_dev_ext_props.android_format_resolve_props.nullColorAttachmentWithExternalFormatResolve;
#endif
#if defined(VVL_TRACY_GPU)
    std::vector<VkTimeDomainKHR> time_domains;
    uint32_t time_domain_count = 0;
    VkResult result = DispatchGetPhysicalDeviceCalibrateableTimeDomainsEXT(physical_device, &time_domain_count, nullptr);
    assert(result == VK_SUCCESS);
    time_domains.resize(time_domain_count);
    result = DispatchGetPhysicalDeviceCalibrateableTimeDomainsEXT(physical_device, &time_domain_count, time_domains.data());
    assert(result == VK_SUCCESS);

    bool found_tracy_required_time_domain = false;
    for (VkTimeDomainEXT time_domain : time_domains) {
#if defined(VK_USE_PLATFORM_WIN32_KHR)
        if (time_domain == VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT) {
            found_tracy_required_time_domain = true;
            break;
        }
#else
        if (time_domain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT) {
            found_tracy_required_time_domain = true;
            break;
        }
#endif
    }
    (void)found_tracy_required_time_domain;
    assert(found_tracy_required_time_domain);

#endif
}

void DeviceState::DestroyObjectMaps() {
    command_pool_map_.clear();
    assert(command_buffer_map_.empty());
    pipeline_map_.clear();
    pipeline_cache_map_.clear();
    pipeline_layout_map_.clear();
    shader_object_map_.clear();
    render_pass_map_.clear();
    shader_module_map_.clear();
    frame_buffer_map_.clear();

    // This will also delete all sets in the pool & remove them from setMap
    descriptor_pool_map_.clear();
    // All sets should be removed
    assert(descriptor_set_map_.empty());
    desc_template_map_.clear();
    descriptor_set_layout_map_.clear();
    // Because swapchains are associated with Surfaces, which are at instance level,
    // they need to be explicitly destroyed here to avoid continued references to
    // the device we're destroying.
    for (auto& entry : swapchain_map_.snapshot()) {
        entry.second->Destroy();
    }
    swapchain_map_.clear();
    image_view_map_.clear();
    image_map_.clear();
    buffer_view_map_.clear();
    buffer_map_.clear();
    sampler_map_.clear();
    sampler_ycbcr_conversion_map_.clear();
    acceleration_structure_nv_map_.clear();
    acceleration_structure_khr_map_.clear();
    mem_obj_map_.clear();

    // Queues persist until device is destroyed
    for (auto& entry : queue_map_.snapshot()) {
        entry.second->Destroy();
    }
    queue_map_.clear();
    fence_map_.clear();
    semaphore_map_.clear();
    event_map_.clear();
    indirect_execution_set_ext_map_.clear();
    indirect_commands_layout_ext_map_.clear();
    query_pool_map_.clear();
    video_session_map_.clear();
    video_session_parameters_map_.clear();
}

void DeviceState::PreCallRecordDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator,
                                             const RecordObject& record_obj) {
    if (!device) {
        return;
    }

    DestroyObjectMaps();

    // Warning: If ever adding new destroy logic here,
    // consider that the base `DeviceState` object is destroyed
    // *before* the layer objects referencing it.
    // Ok as of writing, but this may cause issues in the future.
    // See `DestroyDevice` in chassis_manual.cpp for accurate
    // device destroy order.
}

static void UpdateCmdBufLabelStack(const CommandBuffer& cb_state, Queue& queue_state) {
    if (queue_state.found_unbalanced_cmdbuf_label) return;
    for (const auto& command : cb_state.GetLabelCommands()) {
        if (command.begin) {
            queue_state.cmdbuf_label_stack.push_back(command.label_name);
        } else {
            if (queue_state.cmdbuf_label_stack.empty()) {
                queue_state.found_unbalanced_cmdbuf_label = true;
                return;
            }
            queue_state.last_closed_cmdbuf_label = queue_state.cmdbuf_label_stack.back();
            queue_state.cmdbuf_label_stack.pop_back();
        }
    }
}

// This is a common location where we can detect queue submit about to occur.
// This is designed to capture "snapshots" of what VVL looks like, but at arbitrary time.
void DeviceState::CheckDebugCapture() const {
#if defined(DEBUG_CAPTURE_KEYBOARD)
    // Incase we want to support Android for this, a future option might not be a keyboard
    bool captured = false;
    // This will detect if the "F1" key is pressed
    captured |= IsDebugKeyPressed(instance_state->xlib_display, instance_state->xcb_connection);

    if (captured) {
        for (auto& item : proxies) {
            item.second.DebugCapture();
        }
    }
#endif
}

void DeviceState::PreCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence,
                                           const RecordObject& record_obj) {
    CheckDebugCapture();
    auto queue_state = Get<Queue>(queue);
    std::vector<QueueSubmission> submissions;
    submissions.reserve(submitCount);
    if (submitCount == 0) {
        QueueSubmission submission(record_obj.location);
        submission.AddFence(Get<Fence>(fence));
        submissions.emplace_back(std::move(submission));
    }
    // Now process each individual submit
    for (uint32_t submit_i = 0; submit_i < submitCount; submit_i++) {
        Location submit_loc = record_obj.location.dot(Struct::VkSubmitInfo, Field::pSubmits, submit_i);
        QueueSubmission submission(submit_loc);
        const VkSubmitInfo* submit = &pSubmits[submit_i];
        auto* timeline_info = vku::FindStructInPNextChain<VkTimelineSemaphoreSubmitInfo>(submit->pNext);
        for (uint32_t i = 0; i < submit->waitSemaphoreCount; ++i) {
            auto wait_semaphore = Get<Semaphore>(submit->pWaitSemaphores[i]);
            uint64_t value{0};
            if (wait_semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE && timeline_info && timeline_info->pWaitSemaphoreValues &&
                i < timeline_info->waitSemaphoreValueCount) {
                value = timeline_info->pWaitSemaphoreValues[i];
            }
            submission.AddWaitSemaphore(std::move(wait_semaphore), value);
        }
        for (uint32_t i = 0; i < submit->signalSemaphoreCount; ++i) {
            auto signal_semaphore = Get<Semaphore>(submit->pSignalSemaphores[i]);
            uint64_t value{0};
            if (signal_semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE && timeline_info && timeline_info->pSignalSemaphoreValues &&
                i < timeline_info->signalSemaphoreValueCount) {
                value = timeline_info->pSignalSemaphoreValues[i];
            }
            submission.AddSignalSemaphore(std::move(signal_semaphore), value);
        }

        const auto perf_submit = vku::FindStructInPNextChain<VkPerformanceQuerySubmitInfoKHR>(submit->pNext);
        submission.perf_submit_pass = perf_submit ? perf_submit->counterPassIndex : 0;

        for (const VkCommandBuffer& cb : make_span(submit->pCommandBuffers, submit->commandBufferCount)) {
            if (auto cb_state = GetWrite<CommandBuffer>(cb)) {
                submission.AddCommandBuffer(cb_state, queue_state->cmdbuf_label_stack);
                UpdateCmdBufLabelStack(*cb_state, *queue_state);
            }
        }
        if (submit_i == (submitCount - 1) && fence != VK_NULL_HANDLE) {
            submission.AddFence(Get<Fence>(fence));
        }
        submissions.emplace_back(std::move(submission));
    }

    queue_state->PreSubmit(std::move(submissions));
}

void DeviceState::PostCallRecordQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence,
                                            const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto queue_state = Get<Queue>(queue);
    queue_state->PostSubmit();
    queue_state->is_used_for_regular_submits = true;
}

void DeviceState::PreCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR* pSubmits, VkFence fence,
                                               const RecordObject& record_obj) {
    PreCallRecordQueueSubmit2(queue, submitCount, pSubmits, fence, record_obj);
}

void DeviceState::PreCallRecordQueueSubmit2(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence,
                                            const RecordObject& record_obj) {
    CheckDebugCapture();
    auto queue_state = Get<Queue>(queue);
    std::vector<QueueSubmission> submissions;
    submissions.reserve(submitCount);
    if (submitCount == 0) {
        QueueSubmission submission(record_obj.location);
        submission.AddFence(Get<Fence>(fence));
        submissions.emplace_back(std::move(submission));
    }

    for (uint32_t submit_i = 0; submit_i < submitCount; submit_i++) {
        Location submit_loc = record_obj.location.dot(Struct::VkSubmitInfo2, Field::pSubmits, submit_i);
        QueueSubmission submission(submit_loc);
        const VkSubmitInfo2KHR& submit = pSubmits[submit_i];
        for (const VkSemaphoreSubmitInfo& wait_sem_info : make_span(submit.pWaitSemaphoreInfos, submit.waitSemaphoreInfoCount)) {
            auto wait_semaphore = Get<Semaphore>(wait_sem_info.semaphore);
            ASSERT_AND_CONTINUE(wait_semaphore);
            const uint64_t value = (wait_semaphore->type == VK_SEMAPHORE_TYPE_BINARY) ? 0 : wait_sem_info.value;
            submission.AddWaitSemaphore(std::move(wait_semaphore), value);
        }
        for (const VkSemaphoreSubmitInfo& sig_sem_info : make_span(submit.pSignalSemaphoreInfos, submit.signalSemaphoreInfoCount)) {
            submission.AddSignalSemaphore(Get<Semaphore>(sig_sem_info.semaphore), sig_sem_info.value);
        }
        const auto perf_submit = vku::FindStructInPNextChain<VkPerformanceQuerySubmitInfoKHR>(submit.pNext);
        submission.perf_submit_pass = perf_submit ? perf_submit->counterPassIndex : 0;

        for (const VkCommandBufferSubmitInfo& cb_info : make_span(submit.pCommandBufferInfos, submit.commandBufferInfoCount)) {
            if (auto cb_state = GetWrite<CommandBuffer>(cb_info.commandBuffer)) {
                submission.AddCommandBuffer(cb_state, queue_state->cmdbuf_label_stack);
                UpdateCmdBufLabelStack(*cb_state, *queue_state);
            }
        }
        if (submit_i == (submitCount - 1)) {
            submission.AddFence(Get<Fence>(fence));
        }
        submissions.emplace_back(std::move(submission));
    }
    queue_state->PreSubmit(std::move(submissions));
}

void DeviceState::PostCallRecordQueueSubmit2KHR(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2KHR* pSubmits,
                                                VkFence fence, const RecordObject& record_obj) {
    PostCallRecordQueueSubmit2(queue, submitCount, pSubmits, fence, record_obj);
}

void DeviceState::PostCallRecordQueueSubmit2(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2* pSubmits, VkFence fence,
                                             const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto queue_state = Get<Queue>(queue);
    queue_state->PostSubmit();
    queue_state->is_used_for_regular_submits = true;
}

void DeviceState::PostCallRecordAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo,
                                               const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory,
                                               const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    const auto& memory_type = phys_dev_mem_props.memoryTypes[pAllocateInfo->memoryTypeIndex];
    const auto& memory_heap = phys_dev_mem_props.memoryHeaps[memory_type.heapIndex];
    auto fake_address = fake_memory.Alloc(pAllocateInfo->allocationSize);

    VulkanTypedHandle dedicated_binding = NullVulkanTypedHandle;
    if (const auto dedicated = vku::FindStructInPNextChain<VkMemoryDedicatedAllocateInfo>(pAllocateInfo->pNext)) {
        if (dedicated->buffer) {
            dedicated_binding = {dedicated->buffer, kVulkanObjectTypeBuffer};
        } else if (dedicated->image) {
            dedicated_binding = {dedicated->image, kVulkanObjectTypeImage};
        } else if (const auto dedicated_tensor =
                       vku::FindStructInPNextChain<VkMemoryDedicatedAllocateInfoTensorARM>(pAllocateInfo->pNext)) {
            dedicated_binding = {dedicated_tensor->tensor, kVulkanObjectTypeTensorARM};
        }
    }
    Add(CreateDeviceMemoryState(*pMemory, pAllocateInfo, fake_address, memory_type, memory_heap, dedicated_binding,
                                physical_device_count));
    return;
}

void DeviceState::PreCallRecordFreeMemory(VkDevice device, VkDeviceMemory mem, const VkAllocationCallbacks* pAllocator,
                                          const RecordObject& record_obj) {
    if (auto mem_info = Get<DeviceMemory>(mem)) {
        fake_memory.Free(mem_info->fake_base_address);
    }
#ifdef VK_USE_PLATFORM_WIN32_KHR
    {
        WriteLockGuard guard(win32_handle_map_lock_);
        for (auto it = win32_handle_map_.begin(); it != win32_handle_map_.end();) {
            if (it->second.device_memory == mem) {
                it = win32_handle_map_.erase(it);
                break;
            } else {
                ++it;
            }
        }
    }
#endif
    Destroy<DeviceMemory>(mem);
}

void DeviceState::PostCallRecordSetDeviceMemoryPriorityEXT(VkDevice device, VkDeviceMemory memory, float priority,
                                                           const RecordObject& record_obj) {
    auto mem_info = Get<vvl::DeviceMemory>(memory);
    if (mem_info) {
        mem_info->dynamic_priority.emplace(priority);
    }
}

void DeviceState::PreCallRecordQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo,
                                               VkFence fence, const RecordObject& record_obj) {
    auto queue_state = Get<Queue>(queue);

    std::vector<QueueSubmission> submissions;
    submissions.reserve(bindInfoCount);
    for (uint32_t bind_idx = 0; bind_idx < bindInfoCount; ++bind_idx) {
        const VkBindSparseInfo& bind_info = pBindInfo[bind_idx];
        // Track objects tied to memory
        for (uint32_t j = 0; j < bind_info.bufferBindCount; j++) {
            for (uint32_t k = 0; k < bind_info.pBufferBinds[j].bindCount; k++) {
                auto sparse_binding = bind_info.pBufferBinds[j].pBinds[k];
                auto memory_state = Get<DeviceMemory>(sparse_binding.memory);
                if (auto buffer_state = Get<Buffer>(bind_info.pBufferBinds[j].buffer)) {
                    buffer_state->BindMemory(buffer_state.get(), memory_state, sparse_binding.memoryOffset,
                                             sparse_binding.resourceOffset, sparse_binding.size);
                }
            }
        }
        for (uint32_t j = 0; j < bind_info.imageOpaqueBindCount; j++) {
            for (uint32_t k = 0; k < bind_info.pImageOpaqueBinds[j].bindCount; k++) {
                auto sparse_binding = bind_info.pImageOpaqueBinds[j].pBinds[k];
                auto memory_state = Get<DeviceMemory>(sparse_binding.memory);
                if (auto image_state = Get<Image>(bind_info.pImageOpaqueBinds[j].image)) {
                    image_state->BindMemory(image_state.get(), memory_state, sparse_binding.memoryOffset,
                                            sparse_binding.resourceOffset, sparse_binding.size);
                }
            }
        }
        for (uint32_t j = 0; j < bind_info.imageBindCount; j++) {
            for (uint32_t k = 0; k < bind_info.pImageBinds[j].bindCount; k++) {
                auto sparse_binding = bind_info.pImageBinds[j].pBinds[k];
                // TODO: This size is broken for non-opaque bindings, need to update to comprehend full sparse binding data
                VkDeviceSize size = sparse_binding.extent.depth * sparse_binding.extent.height * sparse_binding.extent.width * 4;
                VkDeviceSize offset = sparse_binding.offset.z * sparse_binding.offset.y * sparse_binding.offset.x * 4;
                auto memory_state = Get<DeviceMemory>(sparse_binding.memory);
                if (auto image_state = Get<Image>(bind_info.pImageBinds[j].image)) {
                    image_state->BindMemory(image_state.get(), memory_state, sparse_binding.memoryOffset, offset, size);
                }
            }
        }
        auto* timeline_info = vku::FindStructInPNextChain<VkTimelineSemaphoreSubmitInfo>(bind_info.pNext);
        Location submit_loc = record_obj.location.dot(Struct::VkBindSparseInfo, Field::pBindInfo, bind_idx);
        QueueSubmission submission(submit_loc);
        for (uint32_t i = 0; i < bind_info.waitSemaphoreCount; ++i) {
            auto wait_semaphore = Get<Semaphore>(bind_info.pWaitSemaphores[i]);
            uint64_t value{0};
            if (wait_semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE && timeline_info && timeline_info->pWaitSemaphoreValues &&
                i < timeline_info->waitSemaphoreValueCount) {
                value = timeline_info->pWaitSemaphoreValues[i];
            }
            submission.AddWaitSemaphore(std::move(wait_semaphore), value);
        }
        for (uint32_t i = 0; i < bind_info.signalSemaphoreCount; ++i) {
            auto signal_semaphore = Get<Semaphore>(bind_info.pSignalSemaphores[i]);
            uint64_t value{0};
            if (signal_semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE && timeline_info && timeline_info->pSignalSemaphoreValues &&
                i < timeline_info->signalSemaphoreValueCount) {
                value = timeline_info->pSignalSemaphoreValues[i];
            }
            submission.AddSignalSemaphore(std::move(signal_semaphore), value);
        }
        if (bind_idx == (bindInfoCount - 1)) {
            submission.AddFence(Get<Fence>(fence));
        }
        submissions.emplace_back(std::move(submission));
    }

    queue_state->PreSubmit(std::move(submissions));
}

void DeviceState::PostCallRecordQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo,
                                                VkFence fence, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto queue_state = Get<Queue>(queue);
    queue_state->PostSubmit();
    queue_state->is_used_for_regular_submits = true;
}

void DeviceState::PostCallRecordCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo,
                                                const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore,
                                                const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<Semaphore>(*this, *pSemaphore, pCreateInfo));
}

void DeviceState::RecordImportSemaphoreState(VkSemaphore semaphore, VkExternalSemaphoreHandleTypeFlagBits handle_type,
                                             VkSemaphoreImportFlags flags) {
    auto semaphore_state = Get<Semaphore>(semaphore);
    if (semaphore_state) {
        semaphore_state->Import(handle_type, flags);
    }
}

void DeviceState::PreCallRecordSignalSemaphore(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo,
                                               const RecordObject& record_obj) {
    auto semaphore_state = Get<Semaphore>(pSignalInfo->semaphore);
    if (semaphore_state) {
        auto value = pSignalInfo->value;  // const workaround
        semaphore_state->EnqueueSignal(SubmissionReference{}, value);
    }
}

void DeviceState::PreCallRecordSignalSemaphoreKHR(VkDevice device, const VkSemaphoreSignalInfo* pSignalInfo,
                                                  const RecordObject& record_obj) {
    PreCallRecordSignalSemaphore(device, pSignalInfo, record_obj);
}

void DeviceState::RecordMappedMemory(VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, void** ppData) {
    if (auto mem_info = Get<DeviceMemory>(mem)) {
        mem_info->mapped_range.offset = offset;
        mem_info->mapped_range.size = size;
        mem_info->p_driver_data = *ppData;
    }
}

void DeviceState::PostCallRecordWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll,
                                              uint64_t timeout, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    // When we know that all fences are complete we can clean/remove their CBs
    if ((VK_TRUE == waitAll) || (1 == fenceCount)) {
        for (uint32_t i = 0; i < fenceCount; i++) {
            if (auto fence_state = Get<Fence>(pFences[i])) {
                fence_state->NotifyAndWait(record_obj.location.dot(Field::pFences, i));
            }
        }
    }
    // NOTE : Alternate case not handled here is when some fences have completed. In
    //  this case for app to guarantee which fences completed it will have to call
    //  vkGetFenceStatus() at which point we'll clean/remove their CBs if complete.
}

void DeviceState::PreCallRecordWaitSemaphores(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout,
                                              const RecordObject& record_obj) {
    for (uint32_t i = 0; i < pWaitInfo->semaphoreCount; i++) {
        if (auto semaphore_state = Get<Semaphore>(pWaitInfo->pSemaphores[i])) {
            auto value = pWaitInfo->pValues[i];  // const workaround
            semaphore_state->EnqueueWait(SubmissionReference{}, value);
        }
    }
}

void DeviceState::PreCallRecordWaitSemaphoresKHR(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout,
                                                 const RecordObject& record_obj) {
    PreCallRecordWaitSemaphores(device, pWaitInfo, timeout, record_obj);
}

void DeviceState::PostCallRecordWaitSemaphores(VkDevice device, const VkSemaphoreWaitInfo* pWaitInfo, uint64_t timeout,
                                               const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    // Same logic as vkWaitForFences(). If some semaphores are not signaled, we will get their status when
    // the application calls vkGetSemaphoreCounterValue() on each of them.
    if ((pWaitInfo->flags & VK_SEMAPHORE_WAIT_ANY_BIT) == 0 || pWaitInfo->semaphoreCount == 1) {
        const Location wait_info_loc = record_obj.location.dot(Field::pWaitInfo);
        for (uint32_t i = 0; i < pWaitInfo->semaphoreCount; i++) {
            if (auto semaphore_state = Get<Semaphore>(pWaitInfo->pSemaphores[i])) {
                Location wait_value_loc = wait_info_loc.dot(Field::pValues, i);
                semaphore_state->RetireWait(nullptr, pWaitInfo->pValues[i], wait_value_loc);
            }
        }
    }
}

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

void DeviceState::PostCallRecordGetSemaphoreCounterValue(VkDevice device, VkSemaphore semaphore, uint64_t* pValue,
                                                         const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    if (auto semaphore_state = Get<Semaphore>(semaphore)) {
        semaphore_state->RetireWait(nullptr, *pValue, record_obj.location);
    }
}

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

void DeviceState::PostCallRecordGetFenceStatus(VkDevice device, VkFence fence, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    if (auto fence_state = Get<Fence>(fence)) {
        fence_state->NotifyAndWait(record_obj.location);
    }
}

void DeviceState::RecordGetDeviceQueueState(uint32_t queue_family_index, uint32_t queue_index, VkDeviceQueueCreateFlags flags,
                                            VkQueue queue) {
    if (Get<Queue>(queue) == nullptr) {
        uint32_t num_queue_families = 0;
        DispatchGetPhysicalDeviceQueueFamilyProperties(physical_device, &num_queue_families, nullptr);
        std::vector<VkQueueFamilyProperties> queue_family_properties_list(num_queue_families);
        DispatchGetPhysicalDeviceQueueFamilyProperties(physical_device, &num_queue_families, queue_family_properties_list.data());

        Add(CreateQueue(queue, queue_family_index, queue_index, flags, queue_family_properties_list[queue_family_index]));
    }
}

void DeviceState::PostCallRecordGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue,
                                               const RecordObject& record_obj) {
    RecordGetDeviceQueueState(queueFamilyIndex, queueIndex, {}, *pQueue);
}

void DeviceState::PostCallRecordGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue,
                                                const RecordObject& record_obj) {
    RecordGetDeviceQueueState(pQueueInfo->queueFamilyIndex, pQueueInfo->queueIndex, pQueueInfo->flags, *pQueue);
}

void DeviceState::PostCallRecordQueueWaitIdle(VkQueue queue, const RecordObject& record_obj) {
    // We assume this is only ever non-success if it is VK_ERROR_DEVICE_LOST, in that case we don't want to update state
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    if (auto queue_state = Get<Queue>(queue)) {
        queue_state->NotifyAndWait(record_obj.location);

        // Reset semaphore's in-use-by-swapchain state.
        // Only for pre-swapchain-maintenance1 code. New code should realy on presentation fence.
        if (!IsExtEnabled(extensions.vk_khr_swapchain_maintenance1) && !IsExtEnabled(extensions.vk_ext_swapchain_maintenance1)) {
            if (queue_state->is_used_for_presentation) {
                for (const auto& entry : semaphore_map_.snapshot()) {
                    const std::shared_ptr<vvl::Semaphore>& semaphore_state = entry.second;
                    semaphore_state->ClearSwapchainWaitInfo();
                }
            }
        }
    }
}

void DeviceState::PostCallRecordDeviceWaitIdle(VkDevice device, const RecordObject& record_obj) {
    // We assume this is only ever non-success if it is VK_ERROR_DEVICE_LOST, in that case we don't want to update state
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    // Sort the queues by id to notify in deterministic order (queue creation order).
    // This is not needed for correctness, but gives deterministic behavior to certain
    // types of bugs in the queue thread.
    std::vector<std::shared_ptr<Queue>> queues;
    queues.reserve(queue_map_.size());
    for (const auto& entry : queue_map_.snapshot()) {
        queues.push_back(entry.second);
    }
    std::sort(queues.begin(), queues.end(), [](const auto& q1, const auto& q2) { return q1->GetId() < q2->GetId(); });

    // Notify all queues before waiting.
    // NotifyAndWait is not safe here. It deadlocks when a wait depends on the not yet issued notify.
    for (auto& queue : queues) {
        queue->Notify();
    }
    // All possible forward progress is initiated. Now it's safe to wait.
    for (auto& queue : queues) {
        queue->Wait(record_obj.location);
    }
    // Reset semaphore's in-use-by-swapchain state.
    // Only for pre-swapchain-maintenance1 code. New code should rely on the presentation fence.
    if (!IsExtEnabled(extensions.vk_khr_swapchain_maintenance1) && !IsExtEnabled(extensions.vk_ext_swapchain_maintenance1)) {
        for (const auto& entry : semaphore_map_.snapshot()) {
            const std::shared_ptr<vvl::Semaphore>& semaphore_state = entry.second;
            semaphore_state->ClearSwapchainWaitInfo();
        }
    }
}

void DeviceState::PreCallRecordDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator,
                                            const RecordObject& record_obj) {
    Destroy<Fence>(fence);
}

void DeviceState::PreCallRecordDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator,
                                                const RecordObject& record_obj) {
    Destroy<Semaphore>(semaphore);
}

void DeviceState::PreCallRecordDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator,
                                            const RecordObject& record_obj) {
    Destroy<Event>(event);
}

void DeviceState::PreCallRecordDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator,
                                                const RecordObject& record_obj) {
    Destroy<QueryPool>(queryPool);
}

void DeviceState::UpdateBindBufferMemoryState(const VkBindBufferMemoryInfo& bind_info) {
    auto buffer_state = Get<Buffer>(bind_info.buffer);
    if (!buffer_state) return;

    // Track objects tied to memory
    if (auto memory_state = Get<DeviceMemory>(bind_info.memory)) {
        buffer_state->BindMemory(buffer_state.get(), memory_state, bind_info.memoryOffset, 0u, buffer_state->requirements.size);
    }
}

void DeviceState::PostCallRecordBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset,
                                                 const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    VkBindBufferMemoryInfo bind_info = vku::InitStructHelper();
    bind_info.buffer = buffer;
    bind_info.memory = memory;
    bind_info.memoryOffset = memoryOffset;
    UpdateBindBufferMemoryState(bind_info);
}

void DeviceState::PostCallRecordBindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo* pBindInfos,
                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        // if bindInfoCount is 1, we know for sure if that single buffer was bound or not
        if (bindInfoCount > 1) {
            for (uint32_t i = 0; i < bindInfoCount; i++) {
                // If user passed in VkBindMemoryStatus, we can update which buffers are valid or not
                if (auto* bind_memory_status = vku::FindStructInPNextChain<VkBindMemoryStatus>(pBindInfos[i].pNext)) {
                    if (bind_memory_status->pResult && *bind_memory_status->pResult == VK_SUCCESS) {
                        UpdateBindBufferMemoryState(pBindInfos[i]);
                    }
                } else if (auto buffer_state = Get<Buffer>(pBindInfos[i].buffer)) {
                    buffer_state->indeterminate_state = true;
                }
            }
        }
    } else {
        for (uint32_t i = 0; i < bindInfoCount; i++) {
            UpdateBindBufferMemoryState(pBindInfos[i]);
        }
    }
}

void DeviceState::PostCallRecordBindBufferMemory2KHR(VkDevice device, uint32_t bindInfoCount,
                                                     const VkBindBufferMemoryInfo* pBindInfos, const RecordObject& record_obj) {
    PostCallRecordBindBufferMemory2(device, bindInfoCount, pBindInfos, record_obj);
}

void DeviceState::PreCallRecordDestroyShaderModule(VkDevice device, VkShaderModule shaderModule,
                                                   const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<ShaderModule>(shaderModule);
}

void DeviceState::PreCallRecordDestroyShaderEXT(VkDevice device, VkShaderEXT shader, const VkAllocationCallbacks* pAllocator,
                                                const RecordObject& record_obj) {
    // Don't do state lookup if not needed
    if (enabled_features.descriptorHeap) {
        if (const auto& shader_state = Get<ShaderObject>(shader)) {
            if (shader_state->descriptor_heap_embedded_samplers_count > 0) {
                descriptor_heap_global_embedded_sampler_count_ -= shader_state->descriptor_heap_embedded_samplers_count;
            }
        }
    }

    Destroy<ShaderObject>(shader);
}

void DeviceState::PreCallRecordDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator,
                                               const RecordObject& record_obj) {
    // Don't do state lookup if not needed
    if (enabled_features.descriptorHeap) {
        if (const auto& pipeline_state = Get<Pipeline>(pipeline)) {
            if (pipeline_state->descriptor_heap_embedded_samplers_count > 0) {
                descriptor_heap_global_embedded_sampler_count_ -= pipeline_state->descriptor_heap_embedded_samplers_count;
            }
        }
    }

    Destroy<Pipeline>(pipeline);
}

void DeviceState::PostCallRecordCmdBindShadersEXT(VkCommandBuffer commandBuffer, uint32_t stageCount,
                                                  const VkShaderStageFlagBits* pStages, const VkShaderEXT* pShaders,
                                                  const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    for (uint32_t i = 0; i < stageCount; ++i) {
        ShaderObject* shader_object_state = nullptr;
        if (pShaders && pShaders[i] != VK_NULL_HANDLE) {
            shader_object_state = Get<ShaderObject>(pShaders[i]).get();
        }
        cb_state->BindShader(pStages[i], shader_object_state);

        // We use this to mark any previous pipeline bounds are invalidated now
        // vkspec.html#shaders-objects-pipeline-interaction
        cb_state->BindLastBoundPipeline(ConvertStageToVvlBindPoint(pStages[i]), nullptr);
    }
}

void DeviceState::PreCallRecordDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout,
                                                     const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<PipelineLayout>(pipelineLayout);
}

void DeviceState::PreCallRecordDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator,
                                              const RecordObject& record_obj) {
    if (!sampler) return;
    // Any bound cmd buffers are now invalid
    if (auto sampler_state = Get<Sampler>(sampler)) {
        if (sampler_state->create_info.borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
            sampler_state->create_info.borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT) {
            custom_border_color_sampler_count--;
        }
    }
    Destroy<Sampler>(sampler);
}

void DeviceState::PreCallRecordDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout,
                                                          const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<DescriptorSetLayout>(descriptorSetLayout);
}

void DeviceState::PreCallRecordDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
                                                     const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<DescriptorPool>(descriptorPool);
}

void DeviceState::PreCallRecordFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
                                                  const VkCommandBuffer* pCommandBuffers, const RecordObject& record_obj) {
    if (auto pool = Get<CommandPool>(commandPool)) {
        pool->Free(commandBufferCount, pCommandBuffers);
    }
}

std::shared_ptr<CommandPool> DeviceState::CreateCommandPoolState(VkCommandPool handle, const VkCommandPoolCreateInfo* create_info) {
    auto queue_flags = physical_device_state->queue_family_properties[create_info->queueFamilyIndex].queueFlags;
    return std::make_shared<CommandPool>(*this, handle, create_info, queue_flags);
}

void DeviceState::PostCallRecordCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo,
                                                  const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool,
                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(CreateCommandPoolState(*pCommandPool, pCreateInfo));
}

void DeviceState::PostCallRecordCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo,
                                                const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool,
                                                const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    uint32_t index_count = 0;
    uint32_t perf_queue_family_index = 0;
    uint32_t n_perf_pass = 0;
    bool has_cb = false, has_rb = false;
    if (pCreateInfo->queryType == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR) {
        const auto* perf = vku::FindStructInPNextChain<VkQueryPoolPerformanceCreateInfoKHR>(pCreateInfo->pNext);
        perf_queue_family_index = perf->queueFamilyIndex;
        index_count = perf->counterIndexCount;

        const QueueFamilyPerfCounters& counters = *physical_device_state->perf_counters[perf_queue_family_index];
        for (uint32_t i = 0; i < perf->counterIndexCount; i++) {
            const auto& counter = counters.counters[perf->pCounterIndices[i]];
            switch (counter.scope) {
                case VK_PERFORMANCE_COUNTER_SCOPE_COMMAND_BUFFER_KHR:
                    has_cb = true;
                    break;
                case VK_PERFORMANCE_COUNTER_SCOPE_RENDER_PASS_KHR:
                    has_rb = true;
                    break;
                default:
                    break;
            }
        }

        DispatchGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(physical_device_state->VkHandle(), perf, &n_perf_pass);
    }

    VkVideoEncodeFeedbackFlagsKHR video_encode_feedback_flags = 0;
    if (pCreateInfo->queryType == VK_QUERY_TYPE_VIDEO_ENCODE_FEEDBACK_KHR) {
        const auto* feedback_info = vku::FindStructInPNextChain<VkQueryPoolVideoEncodeFeedbackCreateInfoKHR>(pCreateInfo->pNext);
        if (feedback_info) {
            video_encode_feedback_flags = feedback_info->encodeFeedbackFlags;
        }
    }

    Add(std::make_shared<QueryPool>(
        *pQueryPool, pCreateInfo, index_count, perf_queue_family_index, n_perf_pass, has_cb, has_rb,
        video_profile_cache_.Get(physical_device, vku::FindStructInPNextChain<VkVideoProfileInfoKHR>(pCreateInfo->pNext)),
        video_encode_feedback_flags));
}

void DeviceState::PreCallRecordDestroyCommandPool(VkDevice device, VkCommandPool commandPool,
                                                  const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<CommandPool>(commandPool);
}

void DeviceState::PostCallRecordResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags,
                                                 const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    // Reset all of the CBs allocated from this pool
    if (auto pool = Get<CommandPool>(commandPool)) {
        pool->Reset(record_obj.location);
    }
}

void DeviceState::PostCallRecordResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences,
                                            const RecordObject& record_obj) {
    // Discussion what a failed reset with multiple fences would mean
    // https://gitlab.khronos.org/vulkan/vulkan/-/issues/4253
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    for (uint32_t i = 0; i < fenceCount; ++i) {
        if (auto fence_state = Get<Fence>(pFences[i])) {
            fence_state->Reset();
        }
    }
}

void DeviceState::PreCallRecordDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer,
                                                  const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<Framebuffer>(framebuffer);
}

void DeviceState::PreCallRecordDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator,
                                                 const RecordObject& record_obj) {
    Destroy<RenderPass>(renderPass);
}

void DeviceState::PostCallRecordCreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo,
                                            const VkAllocationCallbacks* pAllocator, VkFence* pFence,
                                            const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<Fence>(*this, *pFence, pCreateInfo));
}

std::shared_ptr<PipelineCache> DeviceState::CreatePipelineCacheState(VkPipelineCache handle,
                                                                     const VkPipelineCacheCreateInfo* create_info) const {
    return std::make_shared<PipelineCache>(handle, create_info);
}

void DeviceState::PostCallRecordCreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo,
                                                    const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache,
                                                    const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(CreatePipelineCacheState(*pPipelineCache, pCreateInfo));
}

void DeviceState::PreCallRecordDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache,
                                                    const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<PipelineCache>(pipelineCache);
}

std::shared_ptr<Pipeline> DeviceState::CreateGraphicsPipelineState(
    const VkGraphicsPipelineCreateInfo* create_info, std::shared_ptr<const PipelineCache> pipeline_cache,
    std::shared_ptr<const RenderPass>&& render_pass, std::shared_ptr<const PipelineLayout>&& layout,
    spirv::StatelessData stateless_data[kCommonMaxGraphicsShaderStages]) const {
    return std::make_shared<Pipeline>(*this, create_info, std::move(pipeline_cache), std::move(render_pass), std::move(layout),
                                      stateless_data);
}

// PreCallValidate used here to have a single global spot to build the vvl::Pipeline object so we can use it right away
bool DeviceState::PreCallValidateCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
                                                         const VkGraphicsPipelineCreateInfo* pCreateInfos,
                                                         const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                         const ErrorObject& error_obj, PipelineStates& pipeline_states,
                                                         chassis::CreateGraphicsPipelines& chassis_state) const {
    bool skip = false;
    // Set up the state that CoreChecks, gpu_validation and later StateTracker Record will use.
    pipeline_states.reserve(count);
    auto pipeline_cache = Get<PipelineCache>(pipelineCache);
    for (uint32_t i = 0; i < count; i++) {
        const auto& create_info = pCreateInfos[i];
        auto layout_state = Get<PipelineLayout>(create_info.layout);
        std::shared_ptr<const RenderPass> render_pass;

        if (pCreateInfos[i].renderPass != VK_NULL_HANDLE) {
            render_pass = Get<RenderPass>(create_info.renderPass);
        } else if (enabled_features.dynamicRendering) {
            // We need VkPipelineRenderingCreateInfo for two reasons
            //  - The viewMask (pre-raster/fragment shader)
            //  - The formats (fragment output) (also depends on rasterization being enabled)
            // We need generate our own, correct VkPipelineRenderingCreateInfo so we can make a safe struct in vvl::RenderPass
            //
            // We also need to be careful, if things like rasterization is diabled, we **need** to ignore a possible
            // VkPipelineRenderingCreateInfo that contains bad pointers (Thanks GPL!)

            VkPipelineCreateFlags2 flags = create_info.flags;
            if (auto flags2 = vku::FindStructInPNextChain<VkPipelineCreateFlags2CreateInfo>(create_info.pNext)) {
                flags = flags2->flags;
            }
            const bool is_library = (flags & VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR) != 0;

            // These are simply true for the non-GPL case (or when we are creating the final GPL pipeline)
            bool has_pre_raster_state = true;
            bool has_fragment_shader_state = true;
            bool has_fragment_output_state = true;
            if (is_library) {
                // Same as OwnsLibState() but when there is no vvl::Pipeline state
                if (auto lib_type = vku::FindStructInPNextChain<VkGraphicsPipelineLibraryCreateInfoEXT>(create_info.pNext)) {
                    has_pre_raster_state = (lib_type->flags & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) != 0;
                    has_fragment_shader_state = (lib_type->flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) != 0;
                    has_fragment_output_state =
                        (lib_type->flags & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT) != 0;
                }
            }

            const bool uses_view_mask = has_pre_raster_state | has_fragment_shader_state;
            const bool rasterization_enabled =
                has_fragment_output_state && Pipeline::EnablesRasterizationStates(*this, create_info);

            // Start with empty struct, fill in what is not ignored
            VkPipelineRenderingCreateInfo rendering_ci = vku::InitStructHelper();
            rendering_ci.viewMask = 0;
            rendering_ci.colorAttachmentCount = 0;
            rendering_ci.pColorAttachmentFormats = nullptr;
            rendering_ci.depthAttachmentFormat = VK_FORMAT_UNDEFINED;
            rendering_ci.stencilAttachmentFormat = VK_FORMAT_UNDEFINED;

            if (auto pnext_ci = vku::FindStructInPNextChain<VkPipelineRenderingCreateInfo>(create_info.pNext)) {
                if (uses_view_mask) {
                    rendering_ci.viewMask = pnext_ci->viewMask;
                }
                if (rasterization_enabled) {
                    rendering_ci.colorAttachmentCount = pnext_ci->colorAttachmentCount;
                    rendering_ci.pColorAttachmentFormats = pnext_ci->pColorAttachmentFormats;
                    rendering_ci.depthAttachmentFormat = pnext_ci->depthAttachmentFormat;
                    rendering_ci.stencilAttachmentFormat = pnext_ci->stencilAttachmentFormat;
                }
            }

            auto lib_info = vku::FindStructInPNextChain<VkPipelineLibraryCreateInfoKHR>(create_info.pNext);
            // When GPL (our favorite extension) is used, this will be the final executable pipeline and here we need to fetch all
            // the library state
            if (lib_info && lib_info->libraryCount != 0) {
                // Even if the final executable in GPL has a VkPipelineRenderingCreateInfo, we ignore (override) it
                for (VkPipeline lib : vvl::make_span(lib_info->pLibraries, lib_info->libraryCount)) {
                    auto lib_state = Get<vvl::Pipeline>(lib);
                    ASSERT_AND_CONTINUE(lib_state);
                    if (!lib_state->rendering_create_info) {
                        // chance there might not be VkPipelineRenderingCreateInfo when we except, means either a Vertex Input or an
                        // error will be caught elsewhere
                        continue;
                    }
                    if (lib_state->OwnsLibState(lib_state->fragment_output_state)) {
                        rendering_ci.colorAttachmentCount = lib_state->rendering_create_info->colorAttachmentCount;
                        rendering_ci.pColorAttachmentFormats = lib_state->rendering_create_info->pColorAttachmentFormats;
                        rendering_ci.depthAttachmentFormat = lib_state->rendering_create_info->depthAttachmentFormat;
                        rendering_ci.stencilAttachmentFormat = lib_state->rendering_create_info->stencilAttachmentFormat;
                    } else if (lib_state->OwnsLibState(lib_state->pre_raster_state)) {
                        // Could look for Fragment shader, but their viewMask must match and pre-raster is pre-raster is required
                        rendering_ci.viewMask = lib_state->rendering_create_info->viewMask;
                    }
                }
            }

            render_pass = std::make_shared<RenderPass>(rendering_ci);
        }
        pipeline_states.push_back(CreateGraphicsPipelineState(&create_info, pipeline_cache, std::move(render_pass),
                                                              std::move(layout_state), chassis_state.stateless_data));
    }
    return skip;
}

void DeviceState::PostCallRecordCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
                                                        const VkGraphicsPipelineCreateInfo* pCreateInfos,
                                                        const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                        const RecordObject& record_obj, PipelineStates& pipeline_states,
                                                        chassis::CreateGraphicsPipelines& chassis_state) {
    for (uint32_t i = 0; i < count; i++) {
        const VkPipeline pipeline_handle = pPipelines[i];
        if (pipeline_handle == VK_NULL_HANDLE) {
            continue;  // vkspec.html#pipelines-multiple
        }

        if (pCreateInfos[i].pStages) {
            if (pipeline_states[i]->descriptor_heap_embedded_samplers_count > 0) {
                descriptor_heap_global_embedded_sampler_count_ += pipeline_states[i]->descriptor_heap_embedded_samplers_count;
            }
        }

        pipeline_states[i]->SetHandle(pipeline_handle);
        Add(std::move(pipeline_states[i]));
    }
    pipeline_states.clear();
}

std::shared_ptr<Pipeline> DeviceState::CreateComputePipelineState(const VkComputePipelineCreateInfo* create_info,
                                                                  std::shared_ptr<const PipelineCache> pipeline_cache,
                                                                  std::shared_ptr<const PipelineLayout>&& layout,
                                                                  spirv::StatelessData* stateless_data) const {
    return std::make_shared<Pipeline>(*this, create_info, std::move(pipeline_cache), std::move(layout), stateless_data);
}

// PreCallValidate used here to have a single global spot to build the vvl::Pipeline object so we can use it right away
bool DeviceState::PreCallValidateCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
                                                        const VkComputePipelineCreateInfo* pCreateInfos,
                                                        const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                        const ErrorObject& error_obj, PipelineStates& pipeline_states,
                                                        chassis::CreateComputePipelines& chassis_state) const {
    pipeline_states.reserve(count);
    auto pipeline_cache = Get<PipelineCache>(pipelineCache);
    for (uint32_t i = 0; i < count; i++) {
        // Create and initialize internal tracking data structure
        pipeline_states.push_back(CreateComputePipelineState(
            &pCreateInfos[i], pipeline_cache, Get<PipelineLayout>(pCreateInfos[i].layout), &chassis_state.stateless_data));
    }
    return false;
}

void DeviceState::PostCallRecordCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
                                                       const VkComputePipelineCreateInfo* pCreateInfos,
                                                       const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                       const RecordObject& record_obj, PipelineStates& pipeline_states,
                                                       chassis::CreateComputePipelines& chassis_state) {
    for (uint32_t i = 0; i < count; i++) {
        const VkPipeline pipeline_handle = pPipelines[i];
        if (pipeline_handle == VK_NULL_HANDLE) {
            continue;  // vkspec.html#pipelines-multiple
        }

        if (pipeline_states[i]->descriptor_heap_embedded_samplers_count > 0) {
            descriptor_heap_global_embedded_sampler_count_ += pipeline_states[i]->descriptor_heap_embedded_samplers_count;
        }

        pipeline_states[i]->SetHandle(pipeline_handle);
        Add(std::move(pipeline_states[i]));
    }
    pipeline_states.clear();
}

// TODO - Add tests and pass down StatelessData
std::shared_ptr<Pipeline> DeviceState::CreateRayTracingPipelineStateNV(const VkRayTracingPipelineCreateInfoNV* create_info,
                                                                       std::shared_ptr<const PipelineCache> pipeline_cache,
                                                                       std::shared_ptr<const PipelineLayout>&& layout) const {
    return std::make_shared<Pipeline>(*this, create_info, std::move(pipeline_cache), std::move(layout));
}

// PreCallValidate used here to have a single global spot to build the vvl::Pipeline object so we can use it right away
bool DeviceState::PreCallValidateCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
                                                             const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
                                                             const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                             const ErrorObject& error_obj, PipelineStates& pipeline_states) const {
    pipeline_states.reserve(count);
    auto pipeline_cache = Get<PipelineCache>(pipelineCache);
    for (uint32_t i = 0; i < count; i++) {
        // Create and initialize internal tracking data structure
        pipeline_states.push_back(
            CreateRayTracingPipelineStateNV(&pCreateInfos[i], pipeline_cache, Get<PipelineLayout>(pCreateInfos[i].layout)));
    }
    return false;
}

void DeviceState::PostCallRecordCreateRayTracingPipelinesNV(VkDevice device, VkPipelineCache pipelineCache, uint32_t count,
                                                            const VkRayTracingPipelineCreateInfoNV* pCreateInfos,
                                                            const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                            const RecordObject& record_obj, PipelineStates& pipeline_states) {
    for (uint32_t i = 0; i < count; i++) {
        const VkPipeline pipeline_handle = pPipelines[i];
        if (pipeline_handle == VK_NULL_HANDLE) {
            continue;  // vkspec.html#pipelines-multiple
        }

        if (pipeline_states[i]->descriptor_heap_embedded_samplers_count > 0) {
            descriptor_heap_global_embedded_sampler_count_ += pipeline_states[i]->descriptor_heap_embedded_samplers_count;
        }

        pipeline_states[i]->SetHandle(pipeline_handle);
        Add(std::move(pipeline_states[i]));
    }
    pipeline_states.clear();
}

// TODO - Add tests and pass down StatelessData
std::shared_ptr<Pipeline> DeviceState::CreateRayTracingPipelineStateKHR(const VkRayTracingPipelineCreateInfoKHR* create_info,
                                                                        std::shared_ptr<const PipelineCache> pipeline_cache,
                                                                        std::shared_ptr<const PipelineLayout>&& layout,
                                                                        std::vector<spirv::StatelessData>& stateless_data) const {
    return std::make_shared<Pipeline>(*this, create_info, std::move(pipeline_cache), std::move(layout), &stateless_data);
}

// PreCallValidate used here to have a single global spot to build the vvl::Pipeline object so we can use it right away
bool DeviceState::PreCallValidateCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
                                                              VkPipelineCache pipelineCache, uint32_t count,
                                                              const VkRayTracingPipelineCreateInfoKHR* pCreateInfos,
                                                              const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                              const ErrorObject& error_obj, PipelineStates& pipeline_states,
                                                              chassis::CreateRayTracingPipelinesKHR& chassis_state) const {
    pipeline_states.reserve(count);
    auto pipeline_cache = Get<PipelineCache>(pipelineCache);
    for (uint32_t i = 0; i < count; i++) {
        // Create and initialize internal tracking data structure
        pipeline_states.push_back(CreateRayTracingPipelineStateKHR(
            &pCreateInfos[i], pipeline_cache, Get<PipelineLayout>(pCreateInfos[i].layout), chassis_state.stateless_data));
    }
    return false;
}

void DeviceState::PostCallRecordCreateRayTracingPipelinesKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
                                                             VkPipelineCache pipelineCache, uint32_t count,
                                                             const VkRayTracingPipelineCreateInfoKHR* pCreateInfos,
                                                             const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                             const RecordObject& record_obj, PipelineStates& pipeline_states,
                                                             std::shared_ptr<chassis::CreateRayTracingPipelinesKHR> chassis_state) {
    const bool is_operation_deferred = (deferredOperation != VK_NULL_HANDLE && record_obj.result == VK_OPERATION_DEFERRED_KHR);
    if (!is_operation_deferred) {
        for (uint32_t i = 0; i < count; i++) {
            const VkPipeline pipeline_handle = pPipelines[i];
            if (pipeline_handle == VK_NULL_HANDLE) {
                continue;  // vkspec.html#pipelines-multiple
            }

            if (pipeline_states[i]->descriptor_heap_embedded_samplers_count > 0) {
                descriptor_heap_global_embedded_sampler_count_ += pipeline_states[i]->descriptor_heap_embedded_samplers_count;
            }

            pipeline_states[i]->SetHandle(pipeline_handle);
            Add(std::move(pipeline_states[i]));
        }
    } else {
        // Deferred creation: pipelines will be considered created once the deferredOperation object
        // signals it, via usage of vkDeferredOperationJoinKHR and then vkGetDeferredOperationResultKHR
        // Hence pipeline state tracking needs to be deferred to the corresponding call to
        // vkGetDeferredOperationResultKHR => Store the deferred logic to do that in
        // `deferred_operation_post_check`.

        if (dispatch_device_->wrap_handles) {
            deferredOperation = dispatch_device_->Unwrap(deferredOperation);
        }
        std::vector<std::function<void(std::pair<uint32_t, VkPipeline*>)>> cleanup_fn;
        auto find_res = dispatch_device_->deferred_operation_post_check.pop(deferredOperation);
        if (find_res->first) {
            cleanup_fn = std::move(find_res->second);
        }
        // Mutable lambda because we want to move the shared pointer contained in the copied vector
        cleanup_fn.emplace_back([this, chassis_state, pipeline_states](std::pair<uint32_t, VkPipeline*> pipelines) mutable {
            // Just need to capture chassis state to maintain pipeline creations parameters alive, see
            // https://vkdoc.net/chapters/deferred-host-operations#deferred-host-operations-requesting
            (void)chassis_state;
            for (size_t i = 0; i < pipeline_states.size(); ++i) {
                if (pipeline_states[i]->descriptor_heap_embedded_samplers_count > 0) {
                    descriptor_heap_global_embedded_sampler_count_ += pipeline_states[i]->descriptor_heap_embedded_samplers_count;
                }

                pipeline_states[i]->SetHandle(pipelines.second[i]);
                this->Add(std::move(pipeline_states[i]));
            }
        });
        dispatch_device_->deferred_operation_post_check.insert(deferredOperation, cleanup_fn);
    }
}

std::shared_ptr<vvl::Pipeline> DeviceState::CreateDataGraphPipelineState(const VkDataGraphPipelineCreateInfoARM* pCreateInfo,
                                                                         std::shared_ptr<const vvl::PipelineCache> pipeline_cache,
                                                                         std::shared_ptr<const vvl::PipelineLayout>&& layout,
                                                                         spirv::StatelessData* stateless_data) const {
    return std::make_shared<vvl::Pipeline>(*this, pCreateInfo, std::move(pipeline_cache), std::move(layout), stateless_data);
}

bool DeviceState::PreCallValidateCreateDataGraphPipelinesARM(VkDevice device, VkDeferredOperationKHR deferredOperation,
                                                             VkPipelineCache pipelineCache, uint32_t count,
                                                             const VkDataGraphPipelineCreateInfoARM* pCreateInfos,
                                                             const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                             const ErrorObject& error_obj, PipelineStates& pipeline_states,
                                                             chassis::CreateDataGraphPipelinesARM& chassis_state) const {
    pipeline_states.reserve(count);
    auto pipeline_cache = Get<vvl::PipelineCache>(pipelineCache);
    for (uint32_t i = 0; i < count; i++) {
        // Create and initialize internal tracking data structure
        pipeline_states.push_back(CreateDataGraphPipelineState(
            &pCreateInfos[i], pipeline_cache, Get<vvl::PipelineLayout>(pCreateInfos[i].layout), &chassis_state.stateless_data));
    }
    return false;
}

void DeviceState::PostCallRecordCreateDataGraphPipelinesARM(VkDevice device, VkDeferredOperationKHR deferredOperation,
                                                            VkPipelineCache pipelineCache, uint32_t count,
                                                            const VkDataGraphPipelineCreateInfoARM* pCreateInfos,
                                                            const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines,
                                                            const RecordObject& record_obj, PipelineStates& pipeline_states,
                                                            chassis::CreateDataGraphPipelinesARM& chassis_state) {
    // This API may create pipelines regardless of the return value
    for (uint32_t i = 0; i < count; i++) {
        if (pPipelines[i] != VK_NULL_HANDLE) {
            pipeline_states[i]->SetHandle(pPipelines[i]);
            Add(std::move(pipeline_states[i]));
        }
    }
    pipeline_states.clear();
}

void DeviceState::PostCallRecordCmdDispatchDataGraphARM(VkCommandBuffer commandBuffer, VkDataGraphPipelineSessionARM session,
                                                        const VkDataGraphPipelineDispatchInfoARM* pInfo,
                                                        const RecordObject& record_obj) {
    auto cb_state = GetWrite<vvl::CommandBuffer>(commandBuffer);
    std::shared_ptr<vvl::DataGraphPipelineSession> pipeline_session = Get<vvl::DataGraphPipelineSession>(session);
    cb_state->AddChild(pipeline_session);
}

void DeviceState::PostCallRecordCreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo,
                                              const VkAllocationCallbacks* pAllocator, VkSampler* pSampler,
                                              const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    Add(std::make_shared<Sampler>(*pSampler, pCreateInfo));
    if (pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT ||
        pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT) {
        custom_border_color_sampler_count++;
    }
}

void DeviceState::PostCallRecordCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
                                                          const VkAllocationCallbacks* pAllocator,
                                                          VkDescriptorSetLayout* pSetLayout, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<DescriptorSetLayout>(*this, pCreateInfo, *pSetLayout));
}

void DeviceState::PostCallRecordCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo,
                                                     const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout,
                                                     const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<PipelineLayout>(*this, *pPipelineLayout, pCreateInfo));
}

std::shared_ptr<DescriptorPool> DeviceState::CreateDescriptorPoolState(VkDescriptorPool handle,
                                                                       const VkDescriptorPoolCreateInfo* create_info) {
    return std::make_shared<DescriptorPool>(*this, handle, create_info);
}

std::shared_ptr<DescriptorSet> DeviceState::CreateDescriptorSet(VkDescriptorSet handle, DescriptorPool* pool,
                                                                const std::shared_ptr<DescriptorSetLayout const>& layout,
                                                                uint32_t variable_count) {
    return std::make_shared<DescriptorSet>(handle, pool, layout, variable_count, this);
}
std::shared_ptr<vvl::DescriptorSet> DeviceState::CreatePushDescriptorSet(
    const std::shared_ptr<vvl::DescriptorSetLayout const>& layout) {
    auto ds = CreateDescriptorSet(VK_NULL_HANDLE, nullptr, layout, 0);
    NotifyCreated(*ds);
    return ds;
}

void DeviceState::PostCallRecordCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo,
                                                     const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool,
                                                     const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(CreateDescriptorPoolState(*pDescriptorPool, pCreateInfo));
}

void DeviceState::PostCallRecordResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool,
                                                    VkDescriptorPoolResetFlags flags, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    if (auto ds_pool_state = Get<DescriptorPool>(descriptorPool)) {
        ds_pool_state->Reset();
    }
}

// We do some state tracking prior so other things can use it at PreCallValidate time as well
bool DeviceState::PreCallValidateAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo,
                                                        VkDescriptorSet* pDescriptorSets, const ErrorObject& error_obj,
                                                        AllocateDescriptorSetsData& ads_state) const {
    const auto* count_allocate_info =
        vku::FindStructInPNextChain<VkDescriptorSetVariableDescriptorCountAllocateInfo>(pAllocateInfo->pNext);

    ads_state.layout_nodes.resize(pAllocateInfo->descriptorSetCount);
    for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
        if (auto layout = Get<DescriptorSetLayout>(pAllocateInfo->pSetLayouts[i])) {
            ads_state.layout_nodes[i] = layout;
            // Count total descriptors required per type
            for (uint32_t j = 0; j < layout->GetBindingCount(); ++j) {
                const auto& binding_layout = layout->GetDescriptorSetLayoutBindingPtrFromIndex(j);
                uint32_t type_index = static_cast<uint32_t>(binding_layout->descriptorType);
                uint32_t descriptor_count = binding_layout->descriptorCount;
                if (count_allocate_info && i < count_allocate_info->descriptorSetCount) {
                    // Only binding will have this flag
                    if (layout->GetDescriptorBindingFlagsFromIndex(j) & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT) {
                        descriptor_count = count_allocate_info->pDescriptorCounts[i];
                    }
                }

                // In VK_KHR_maintenance6 we can finally check for YCbCr samplers that will take multiple descriptor slots.
                // First need to check if has a YCbCr format
                if (binding_layout->pImmutableSamplers != nullptr &&
                    binding_layout->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER &&
                    IsExtEnabled(extensions.vk_khr_maintenance6)) {
                    if (const auto sampler = Get<Sampler>(*binding_layout->pImmutableSamplers)) {
                        if (sampler->sampler_conversion != VK_NULL_HANDLE) {
                            descriptor_count *= phys_dev_props_core14.maxCombinedImageSamplerDescriptorCount;
                        }
                    }
                }

                ads_state.required_descriptors_by_type[type_index] += descriptor_count;
            }
        }
        // Any unknown layouts will be flagged as errors during ValidateAllocateDescriptorSets() call
    }

    return false;
}

// This is calculated once in DeviceState::PreCallValidateAllocateDescriptorSets, but if found an error, provide a way to show how
// we calculated this
std::string DeviceState::PrintDescriptorAllocation(const VkDescriptorSetAllocateInfo& allocate_info,
                                                   const vvl::DescriptorPool& pool_state, VkDescriptorType type) const {
    std::ostringstream ss;
    ss << "Where " << string_VkDescriptorType(type) << " is found in the pool:\n";
    for (const auto [pool_size_i, pool_size] :
         vvl::enumerate(pool_state.create_info.pPoolSizes, pool_state.create_info.poolSizeCount)) {
        if (pool_size.type == type) {
            ss << "  pPoolSizes[" << pool_size_i << "].descriptorCount = " << pool_size.descriptorCount << '\n';
        }
    }

    const auto* count_allocate_info =
        vku::FindStructInPNextChain<VkDescriptorSetVariableDescriptorCountAllocateInfo>(allocate_info.pNext);
    ss << "Where the allocation are being requested:\n";
    for (const auto [set_layout_i, set_layout] : vvl::enumerate(allocate_info.pSetLayouts, allocate_info.descriptorSetCount)) {
        if (auto ds_layout_state = Get<vvl::DescriptorSetLayout>(set_layout)) {
            for (uint32_t i = 0; i < ds_layout_state->GetBindingCount(); ++i) {
                const auto& binding_layout = ds_layout_state->GetDescriptorSetLayoutBindingPtrFromIndex(i);
                if (binding_layout->descriptorType != type) {
                    continue;
                }
                bool normal_message = true;
                if (count_allocate_info && i < count_allocate_info->descriptorSetCount &&
                    (ds_layout_state->GetDescriptorBindingFlagsFromIndex(i) &
                     VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)) {
                    ss << "  pSetLayouts[" << set_layout_i << "]::pBindings[" << i
                       << "].descriptorCount = " << count_allocate_info->pDescriptorCounts[i]
                       << " (adjusted for VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT)\n";
                    normal_message = false;
                } else if (binding_layout->pImmutableSamplers != nullptr && type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER &&
                           IsExtEnabled(extensions.vk_khr_maintenance6)) {
                    if (const auto sampler = Get<Sampler>(*binding_layout->pImmutableSamplers)) {
                        if (sampler->sampler_conversion != VK_NULL_HANDLE) {
                            const uint32_t ycbcr_count =
                                binding_layout->descriptorCount * phys_dev_props_core14.maxCombinedImageSamplerDescriptorCount;
                            ss << "  pSetLayouts[" << set_layout_i << "]::pBindings[" << i << "].descriptorCount = " << ycbcr_count
                               << " (adjusted by multiplying maxCombinedImageSamplerDescriptorCount which is "
                               << phys_dev_props_core14.maxCombinedImageSamplerDescriptorCount << ")\n";
                            normal_message = false;
                        }
                    }
                }

                if (normal_message) {
                    ss << "  pSetLayouts[" << set_layout_i << "]::pBindings[" << i
                       << "].descriptorCount = " << binding_layout->descriptorCount << '\n';
                }
            }
        }
    }

    return ss.str();
}

// Allocation state was good and call down chain was made so update state based on allocating descriptor sets
void DeviceState::PostCallRecordAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo,
                                                       VkDescriptorSet* pDescriptorSets, const RecordObject& record_obj,
                                                       AllocateDescriptorSetsData& ads_state) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    // All the updates are contained in a single vvl function
    if (auto ds_pool_state = Get<DescriptorPool>(pAllocateInfo->descriptorPool)) {
        ds_pool_state->Allocate(pAllocateInfo, pDescriptorSets, ads_state);
    }
}

void DeviceState::PreCallRecordFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count,
                                                  const VkDescriptorSet* pDescriptorSets, const RecordObject& record_obj) {
    if (auto ds_pool_state = Get<DescriptorPool>(descriptorPool)) {
        ds_pool_state->Free(count, pDescriptorSets);
    }
}

void DeviceState::PerformUpdateDescriptorSets(uint32_t write_count, const VkWriteDescriptorSet* p_wds, uint32_t copy_count,
                                              const VkCopyDescriptorSet* p_cds) {
    // Write updates first
    for (uint32_t i = 0; i < write_count; ++i) {
        const VkDescriptorSet dst_set = p_wds[i].dstSet;
        if (auto set_node = Get<DescriptorSet>(dst_set)) {
            set_node->PerformWriteUpdate(p_wds[i]);
        }
    }
    // Now copy updates
    for (uint32_t i = 0; i < copy_count; ++i) {
        const VkDescriptorSet dst_set = p_cds[i].dstSet;
        const VkDescriptorSet src_set = p_cds[i].srcSet;
        auto src_node = Get<DescriptorSet>(src_set);
        auto dst_node = Get<DescriptorSet>(dst_set);
        if (src_node && dst_node) {
            dst_node->PerformCopyUpdate(p_cds[i], *src_node);
        }
    }
}

void DeviceState::PreCallRecordUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount,
                                                    const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount,
                                                    const VkCopyDescriptorSet* pDescriptorCopies, const RecordObject& record_obj) {
    PerformUpdateDescriptorSets(descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
}

void DeviceState::PostCallRecordAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo,
                                                       VkCommandBuffer* pCommandBuffers, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    if (auto pool = Get<CommandPool>(pAllocateInfo->commandPool)) {
        pool->Allocate(pAllocateInfo, pCommandBuffers);
    }
}

void DeviceState::PreCallRecordBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo,
                                                  const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->Begin(pBeginInfo);
}

void DeviceState::PostCallRecordEndCommandBuffer(VkCommandBuffer commandBuffer, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->End(record_obj.result);
}

void DeviceState::PostCallRecordResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags,
                                                   const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->Reset(record_obj.location);
}

void DeviceState::PostCallRecordCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
                                                VkPipeline pipeline, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    auto pipeline_state = Get<Pipeline>(pipeline);
    ASSERT_AND_RETURN(pipeline_state);
    cb_state->RecordBindPipeline(pipelineBindPoint, *pipeline_state);

    if (!disabled[command_buffer_state]) {
        cb_state->AddChild(pipeline_state);
    }
}

void DeviceState::PostCallRecordCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount,
                                               const VkViewport* pViewports, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetViewport(firstViewport, viewportCount, pViewports);
}

void DeviceState::PostCallRecordCmdSetExclusiveScissorNV(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor,
                                                         uint32_t exclusiveScissorCount, const VkRect2D* pExclusiveScissors,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV);
    // TODO: We don't have VUIDs for validating that all exclusive scissors have been set.
    // cb_state->exclusiveScissorMask |= ((1u << exclusiveScissorCount) - 1u) << firstExclusiveScissor;

    cb_state->dynamic_state_value.exclusive_scissor_first = firstExclusiveScissor;
    cb_state->dynamic_state_value.exclusive_scissor_count = exclusiveScissorCount;
    cb_state->dynamic_state_value.exclusive_scissors.resize(firstExclusiveScissor + exclusiveScissorCount);
    for (size_t i = 0; i < exclusiveScissorCount; ++i) {
        cb_state->dynamic_state_value.exclusive_scissors[firstExclusiveScissor + i] = pExclusiveScissors[i];
    }
}

void DeviceState::PostCallRecordCmdSetExclusiveScissorEnableNV(VkCommandBuffer commandBuffer, uint32_t firstExclusiveScissor,
                                                               uint32_t exclusiveScissorCount,
                                                               const VkBool32* pExclusiveScissorEnables,
                                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV);

    cb_state->dynamic_state_value.exclusive_scissor_enable_first = firstExclusiveScissor;
    cb_state->dynamic_state_value.exclusive_scissor_enable_count = exclusiveScissorCount;
    cb_state->dynamic_state_value.exclusive_scissor_enables.resize(firstExclusiveScissor + exclusiveScissorCount);
    for (size_t i = 0; i < exclusiveScissorCount; ++i) {
        cb_state->dynamic_state_value.exclusive_scissor_enables[firstExclusiveScissor + i] = pExclusiveScissorEnables[i];
    }
}

void DeviceState::PostCallRecordCmdBindShadingRateImageNV(VkCommandBuffer commandBuffer, VkImageView imageView,
                                                          VkImageLayout imageLayout, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);

    if (imageView != VK_NULL_HANDLE) {
        auto view_state = Get<ImageView>(imageView);
        cb_state->AddChild(view_state);
    }
}

void DeviceState::PostCallRecordCmdSetViewportShadingRatePaletteNV(VkCommandBuffer commandBuffer, uint32_t firstViewport,
                                                                   uint32_t viewportCount,
                                                                   const VkShadingRatePaletteNV* pShadingRatePalettes,
                                                                   const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV);
    // TODO: We don't have VUIDs for validating that all shading rate palettes have been set.
    // cb_state->shadingRatePaletteMask |= ((1u << viewportCount) - 1u) << firstViewport;
    cb_state->dynamic_state_value.shading_rate_palette_count = viewportCount;
}

std::shared_ptr<AccelerationStructureNV> DeviceState::CreateAccelerationStructureState(
    VkAccelerationStructureNV handle, const VkAccelerationStructureCreateInfoNV* create_info) {
    return std::make_shared<AccelerationStructureNV>(device, handle, create_info);
}

void DeviceState::PostCallRecordCreateAccelerationStructureNV(VkDevice device,
                                                              const VkAccelerationStructureCreateInfoNV* pCreateInfo,
                                                              const VkAllocationCallbacks* pAllocator,
                                                              VkAccelerationStructureNV* pAccelerationStructure,
                                                              const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(CreateAccelerationStructureState(*pAccelerationStructure, pCreateInfo));
}

void DeviceState::PostCallRecordCreateAccelerationStructureKHR(VkDevice device,
                                                               const VkAccelerationStructureCreateInfoKHR* pCreateInfo,
                                                               const VkAllocationCallbacks* pAllocator,
                                                               VkAccelerationStructureKHR* pAccelerationStructure,
                                                               const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<AccelerationStructureKHR>(*this, pCreateInfo, *pAccelerationStructure));
}

void DeviceState::PostCallRecordCreateAccelerationStructure2KHR(VkDevice device,
                                                                const VkAccelerationStructureCreateInfo2KHR* pCreateInfo,
                                                                const VkAllocationCallbacks* pAllocator,
                                                                VkAccelerationStructureKHR* pAccelerationStructure,
                                                                const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<AccelerationStructureKHR>(*this, pCreateInfo, *pAccelerationStructure));
}

void DeviceState::PostCallRecordBuildAccelerationStructuresKHR(
    VkDevice device, VkDeferredOperationKHR deferredOperation, uint32_t infoCount,
    const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
    const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos, const RecordObject& record_obj) {
    // Discussion what a failed build with multiple AccelerationStructures would mean
    // https://gitlab.khronos.org/vulkan/vulkan/-/issues/4254
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    for (uint32_t i = 0; i < infoCount; ++i) {
        if (auto dst_as_state = Get<AccelerationStructureKHR>(pInfos[i].dstAccelerationStructure)) {
            dst_as_state->Build(&pInfos[i], true, *ppBuildRangeInfos);
        }
    }
}

// helper method for device side acceleration structure builds
void DeviceState::RecordDeviceAccelerationStructureBuildInfo(CommandBuffer& cb_state,
                                                             const VkAccelerationStructureBuildGeometryInfoKHR& info) {
    auto dst_as_state = Get<AccelerationStructureKHR>(info.dstAccelerationStructure);
    if (dst_as_state) {
        dst_as_state->Build(&info, false, nullptr);
    }
    if (disabled[command_buffer_state]) {
        return;
    }
    if (dst_as_state) {
        cb_state.AddChild(dst_as_state);
    }
    auto src_as_state = Get<AccelerationStructureKHR>(info.srcAccelerationStructure);
    if (src_as_state) {
        cb_state.AddChild(src_as_state);
    }

    // Issue https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/6461
    // showed that it is incorrect to try to add buffers obtained through a call to GetBuffersByAddress as children to a command
    // buffer
}

void DeviceState::PostCallRecordCmdBuildAccelerationStructuresKHR(
    VkCommandBuffer commandBuffer, uint32_t infoCount, const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
    const VkAccelerationStructureBuildRangeInfoKHR* const* ppBuildRangeInfos, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);

    cb_state->RecordCommand(record_obj.location);
    for (const auto [i, info] : enumerate(pInfos, infoCount)) {
        RecordDeviceAccelerationStructureBuildInfo(*cb_state, info);
        if (auto dst_as_state = Get<AccelerationStructureKHR>(info.dstAccelerationStructure)) {
            dst_as_state->UpdateBuildRangeInfos(ppBuildRangeInfos[i], info.geometryCount);
        }
    }
}

void DeviceState::PostCallRecordCmdBuildAccelerationStructuresIndirectKHR(VkCommandBuffer commandBuffer, uint32_t infoCount,
                                                                          const VkAccelerationStructureBuildGeometryInfoKHR* pInfos,
                                                                          const VkDeviceAddress* pIndirectDeviceAddresses,
                                                                          const uint32_t* pIndirectStrides,
                                                                          const uint32_t* const* ppMaxPrimitiveCounts,
                                                                          const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);

    cb_state->RecordCommand(record_obj.location);
    for (uint32_t i = 0; i < infoCount; i++) {
        RecordDeviceAccelerationStructureBuildInfo(*cb_state, pInfos[i]);

        // Issue https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/6461
        // showed that it is incorrect to try to add buffers obtained through a call to GetBuffersByAddress as children to a command
        // buffer
    }
}

void DeviceState::PostCallRecordGetAccelerationStructureMemoryRequirementsNV(
    VkDevice device, const VkAccelerationStructureMemoryRequirementsInfoNV* pInfo, VkMemoryRequirements2* pMemoryRequirements,
    const RecordObject& record_obj) {
    if (auto as_state = Get<AccelerationStructureNV>(pInfo->accelerationStructure)) {
        if (pInfo->type == VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV) {
            as_state->memory_requirements_checked = true;
        } else if (pInfo->type == VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV) {
            as_state->build_scratch_memory_requirements_checked = true;
        } else if (pInfo->type == VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV) {
            as_state->update_scratch_memory_requirements_checked = true;
        }
    }
}

void DeviceState::PostCallRecordBindAccelerationStructureMemoryNV(VkDevice device, uint32_t bindInfoCount,
                                                                  const VkBindAccelerationStructureMemoryInfoNV* pBindInfos,
                                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    for (uint32_t i = 0; i < bindInfoCount; i++) {
        const VkBindAccelerationStructureMemoryInfoNV& info = pBindInfos[i];

        if (auto as_state = Get<AccelerationStructureNV>(info.accelerationStructure)) {
            // Track objects tied to memory
            if (auto memory_state = Get<DeviceMemory>(info.memory)) {
                as_state->BindMemory(as_state.get(), memory_state, info.memoryOffset, 0u, as_state->memory_requirements.size);
            }

            // GPU validation of top level acceleration structure building needs acceleration structure handles.
            // XXX TODO: Query device address for KHR extension
            if (enabled[gpu_validation]) {
                DispatchGetAccelerationStructureHandleNV(device, info.accelerationStructure, 8, &as_state->opaque_handle);
            }
        }
    }
}

void DeviceState::PostCallRecordCmdBuildAccelerationStructureNV(VkCommandBuffer commandBuffer,
                                                                const VkAccelerationStructureInfoNV* pInfo, VkBuffer instanceData,
                                                                VkDeviceSize instanceOffset, VkBool32 update,
                                                                VkAccelerationStructureNV dst, VkAccelerationStructureNV src,
                                                                VkBuffer scratch, VkDeviceSize scratchOffset,
                                                                const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    if (!cb_state) {
        return;
    }
    cb_state->RecordCommand(record_obj.location);

    auto dst_as_state = Get<AccelerationStructureNV>(dst);
    if (dst_as_state) {
        dst_as_state->Build(pInfo);
        if (!disabled[command_buffer_state]) {
            cb_state->AddChild(dst_as_state);
        }
    }
    if (!disabled[command_buffer_state]) {
        if (auto src_as_state = Get<AccelerationStructureNV>(src)) {
            cb_state->AddChild(src_as_state);
        }
        if (auto instance_buffer = Get<Buffer>(instanceData)) {
            cb_state->AddChild(instance_buffer);
        }
        if (auto scratch_buffer = Get<Buffer>(scratch)) {
            cb_state->AddChild(scratch_buffer);
        }

        for (uint32_t i = 0; i < pInfo->geometryCount; i++) {
            const auto& geom = pInfo->pGeometries[i];

            if (auto vertex_buffer = Get<Buffer>(geom.geometry.triangles.vertexData)) {
                cb_state->AddChild(vertex_buffer);
            }
            if (auto index_buffer = Get<Buffer>(geom.geometry.triangles.indexData)) {
                cb_state->AddChild(index_buffer);
            }
            if (auto transform_buffer = Get<Buffer>(geom.geometry.triangles.transformData)) {
                cb_state->AddChild(transform_buffer);
            }
            if (auto aabb_buffer = Get<Buffer>(geom.geometry.aabbs.aabbData)) {
                cb_state->AddChild(aabb_buffer);
            }
        }
    }
}

void DeviceState::PostCallRecordCmdCopyAccelerationStructureNV(VkCommandBuffer commandBuffer, VkAccelerationStructureNV dst,
                                                               VkAccelerationStructureNV src,
                                                               VkCopyAccelerationStructureModeNV mode,
                                                               const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto src_as_state = Get<AccelerationStructureNV>(src);
    auto dst_as_state = Get<AccelerationStructureNV>(dst);
    ASSERT_AND_RETURN(src_as_state && dst_as_state);
    cb_state->AddChild(src_as_state);
    cb_state->AddChild(dst_as_state);

    cb_state->RecordCommand(record_obj.location);
    dst_as_state->built = true;
    dst_as_state->build_info = src_as_state->build_info;
}

void DeviceState::PreCallRecordDestroyAccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR accelerationStructure,
                                                               const VkAllocationCallbacks* pAllocator,
                                                               const RecordObject& record_obj) {
    if (auto as_state = Get<vvl::AccelerationStructureKHR>(accelerationStructure)) {
        if (as_state->GetAccelerationStructureAddress() != 0) {
            WriteLockGuard lock(as_with_addresses.array_mutex);
            auto as_found_it = std::find(as_with_addresses.array.begin(), as_with_addresses.array.end(), as_state.get());
            while (as_found_it != as_with_addresses.array.end()) {
                const size_t i = std::distance(as_with_addresses.array.begin(), as_found_it);
                std::swap(as_with_addresses.array[i], as_with_addresses.array[as_with_addresses.array.size() - 1]);
                as_with_addresses.array.resize(as_with_addresses.array.size() - 1);

                as_found_it = std::find(as_with_addresses.array.begin() + i, as_with_addresses.array.end(), as_state.get());
            }
            as_state->SetAccelerationStructureAddress(0);
        }
    }
    Destroy<AccelerationStructureKHR>(accelerationStructure);
}

void DeviceState::PreCallRecordDestroyAccelerationStructureNV(VkDevice device, VkAccelerationStructureNV accelerationStructure,
                                                              const VkAllocationCallbacks* pAllocator,
                                                              const RecordObject& record_obj) {
    Destroy<AccelerationStructureNV>(accelerationStructure);
}

void DeviceState::PostCallRecordCmdSetViewportWScalingNV(VkCommandBuffer commandBuffer, uint32_t firstViewport,
                                                         uint32_t viewportCount, const VkViewportWScalingNV* pViewportWScalings,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV);
    cb_state->dynamic_state_value.viewport_w_scaling_first = firstViewport;
    cb_state->dynamic_state_value.viewport_w_scaling_count = viewportCount;
    cb_state->dynamic_state_value.viewport_w_scalings.resize(viewportCount);
    for (size_t i = 0; i < viewportCount; ++i) {
        cb_state->dynamic_state_value.viewport_w_scalings[i] = pViewportWScalings[i];
    }
}

void DeviceState::PostCallRecordCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_LINE_WIDTH);
}

void DeviceState::PostCallRecordCmdSetLineStipple(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor,
                                                  uint16_t lineStipplePattern, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_LINE_STIPPLE);
}

void DeviceState::PostCallRecordCmdSetLineStippleEXT(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor,
                                                     uint16_t lineStipplePattern, const RecordObject& record_obj) {
    PostCallRecordCmdSetLineStipple(commandBuffer, lineStippleFactor, lineStipplePattern, record_obj);
}

void DeviceState::PostCallRecordCmdSetLineStippleKHR(VkCommandBuffer commandBuffer, uint32_t lineStippleFactor,
                                                     uint16_t lineStipplePattern, const RecordObject& record_obj) {
    PostCallRecordCmdSetLineStipple(commandBuffer, lineStippleFactor, lineStipplePattern, record_obj);
}

void DeviceState::PostCallRecordCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp,
                                                float depthBiasSlopeFactor, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DEPTH_BIAS);
}

void DeviceState::PostCallRecordCmdSetDepthBias2EXT(VkCommandBuffer commandBuffer, const VkDepthBiasInfoEXT* pDepthBiasInfo,
                                                    const RecordObject& record_obj) {
    PostCallRecordCmdSetDepthBias(commandBuffer, pDepthBiasInfo->depthBiasConstantFactor, pDepthBiasInfo->depthBiasClamp,
                                  pDepthBiasInfo->depthBiasSlopeFactor, record_obj);
}

void DeviceState::PostCallRecordCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount,
                                              const VkRect2D* pScissors, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetScissor(firstScissor, scissorCount);
}

void DeviceState::PostCallRecordCmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4],
                                                     const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_BLEND_CONSTANTS);
}

void DeviceState::PostCallRecordCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds,
                                                  const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DEPTH_BOUNDS);
}

void DeviceState::PostCallRecordCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
                                                         uint32_t compareMask, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_STENCIL_COMPARE_MASK);
}

void DeviceState::PostCallRecordCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
                                                       uint32_t writeMask, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_STENCIL_WRITE_MASK);
    if (faceMask == VK_STENCIL_FACE_FRONT_BIT || faceMask == VK_STENCIL_FACE_FRONT_AND_BACK) {
        cb_state->dynamic_state_value.write_mask_front = writeMask;
    }
    if (faceMask == VK_STENCIL_FACE_BACK_BIT || faceMask == VK_STENCIL_FACE_FRONT_AND_BACK) {
        cb_state->dynamic_state_value.write_mask_back = writeMask;
    }
}

void DeviceState::PostCallRecordCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask,
                                                       uint32_t reference, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_STENCIL_REFERENCE);
}

// Update the bound state for the bind point, including the effects of incompatible pipeline layouts
void DeviceState::PostCallRecordCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
                                                      VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount,
                                                      const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount,
                                                      const uint32_t* pDynamicOffsets, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto pipeline_layout = Get<PipelineLayout>(layout);
    if (!cb_state || !pipeline_layout) {
        return;
    }
    cb_state->RecordCommand(record_obj.location);

    // legacy descriptor binding invalidates any previous call to vkCmdBindDescriptorBuffersEXT
    cb_state->descriptor_buffer.binding_info.clear();

    std::shared_ptr<DescriptorSet> no_push_desc;

    cb_state->UpdateLastBoundDescriptorSets(pipelineBindPoint, pipeline_layout, firstSet, setCount, pDescriptorSets, no_push_desc,
                                            dynamicOffsetCount, pDynamicOffsets, record_obj.location);

    cb_state->SetDescriptorMode(vvl::DescriptorModeClassic, record_obj.location.function);
}

void DeviceState::PostCallRecordCmdBindDescriptorSets2(VkCommandBuffer commandBuffer,
                                                       const VkBindDescriptorSetsInfo* pBindDescriptorSetsInfo,
                                                       const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto pipeline_layout = Get<PipelineLayout>(pBindDescriptorSetsInfo->layout);
    ASSERT_AND_RETURN(cb_state && pipeline_layout);

    cb_state->RecordCommand(record_obj.location);

    // legacy descriptor binding invalidates any previous call to vkCmdBindDescriptorBuffersEXT
    cb_state->descriptor_buffer.binding_info.clear();

    std::shared_ptr<DescriptorSet> no_push_desc;

    if (IsStageInPipelineBindPoint(pBindDescriptorSetsInfo->stageFlags, VK_PIPELINE_BIND_POINT_GRAPHICS)) {
        cb_state->UpdateLastBoundDescriptorSets(
            VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, pBindDescriptorSetsInfo->firstSet,
            pBindDescriptorSetsInfo->descriptorSetCount, pBindDescriptorSetsInfo->pDescriptorSets, no_push_desc,
            pBindDescriptorSetsInfo->dynamicOffsetCount, pBindDescriptorSetsInfo->pDynamicOffsets, record_obj.location);
    }
    if (IsStageInPipelineBindPoint(pBindDescriptorSetsInfo->stageFlags, VK_PIPELINE_BIND_POINT_COMPUTE)) {
        cb_state->UpdateLastBoundDescriptorSets(
            VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, pBindDescriptorSetsInfo->firstSet,
            pBindDescriptorSetsInfo->descriptorSetCount, pBindDescriptorSetsInfo->pDescriptorSets, no_push_desc,
            pBindDescriptorSetsInfo->dynamicOffsetCount, pBindDescriptorSetsInfo->pDynamicOffsets, record_obj.location);
    }
    if (IsStageInPipelineBindPoint(pBindDescriptorSetsInfo->stageFlags, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR)) {
        cb_state->UpdateLastBoundDescriptorSets(
            VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline_layout, pBindDescriptorSetsInfo->firstSet,
            pBindDescriptorSetsInfo->descriptorSetCount, pBindDescriptorSetsInfo->pDescriptorSets, no_push_desc,
            pBindDescriptorSetsInfo->dynamicOffsetCount, pBindDescriptorSetsInfo->pDynamicOffsets, record_obj.location);
    }

    cb_state->SetDescriptorMode(vvl::DescriptorModeClassic, record_obj.location.function);
}

void DeviceState::PostCallRecordCmdBindDescriptorSets2KHR(VkCommandBuffer commandBuffer,
                                                          const VkBindDescriptorSetsInfoKHR* pBindDescriptorSetsInfo,
                                                          const RecordObject& record_obj) {
    PostCallRecordCmdBindDescriptorSets2(commandBuffer, pBindDescriptorSetsInfo, record_obj);
}

void DeviceState::PostCallRecordCmdPushDescriptorSet(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
                                                     VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount,
                                                     const VkWriteDescriptorSet* pDescriptorWrites,
                                                     const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto pipeline_layout = Get<PipelineLayout>(layout);
    ASSERT_AND_RETURN(pipeline_layout);
    cb_state->PushDescriptorSetState(pipelineBindPoint, pipeline_layout, set, descriptorWriteCount, pDescriptorWrites,
                                     record_obj.location);

    if (pipeline_layout->has_descriptor_buffer) {
        cb_state->SetDescriptorMode(vvl::DescriptorModeBuffer, record_obj.location.function);
    } else {
        cb_state->SetDescriptorMode(vvl::DescriptorModeClassic, record_obj.location.function);
    }
}

void DeviceState::PostCallRecordCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
                                                        VkPipelineLayout layout, uint32_t set, uint32_t descriptorWriteCount,
                                                        const VkWriteDescriptorSet* pDescriptorWrites,
                                                        const RecordObject& record_obj) {
    PostCallRecordCmdPushDescriptorSet(commandBuffer, pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites,
                                       record_obj);
}

void DeviceState::PostCallRecordCmdPushDescriptorSet2(VkCommandBuffer commandBuffer,
                                                      const VkPushDescriptorSetInfo* pPushDescriptorSetInfo,
                                                      const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto pipeline_layout = Get<PipelineLayout>(pPushDescriptorSetInfo->layout);
    ASSERT_AND_RETURN(pipeline_layout);
    if (IsStageInPipelineBindPoint(pPushDescriptorSetInfo->stageFlags, VK_PIPELINE_BIND_POINT_GRAPHICS)) {
        cb_state->PushDescriptorSetState(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, pPushDescriptorSetInfo->set,
                                         pPushDescriptorSetInfo->descriptorWriteCount, pPushDescriptorSetInfo->pDescriptorWrites,
                                         record_obj.location);
    }
    if (IsStageInPipelineBindPoint(pPushDescriptorSetInfo->stageFlags, VK_PIPELINE_BIND_POINT_COMPUTE)) {
        cb_state->PushDescriptorSetState(VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, pPushDescriptorSetInfo->set,
                                         pPushDescriptorSetInfo->descriptorWriteCount, pPushDescriptorSetInfo->pDescriptorWrites,
                                         record_obj.location);
    }
    if (IsStageInPipelineBindPoint(pPushDescriptorSetInfo->stageFlags, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR)) {
        cb_state->PushDescriptorSetState(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline_layout, pPushDescriptorSetInfo->set,
                                         pPushDescriptorSetInfo->descriptorWriteCount, pPushDescriptorSetInfo->pDescriptorWrites,
                                         record_obj.location);
    }

    if (pipeline_layout->has_descriptor_buffer) {
        cb_state->SetDescriptorMode(vvl::DescriptorModeBuffer, record_obj.location.function);
    } else {
        cb_state->SetDescriptorMode(vvl::DescriptorModeClassic, record_obj.location.function);
    }
}

void DeviceState::PostCallRecordCmdPushDescriptorSet2KHR(VkCommandBuffer commandBuffer,
                                                         const VkPushDescriptorSetInfoKHR* pPushDescriptorSetInfo,
                                                         const RecordObject& record_obj) {
    PostCallRecordCmdPushDescriptorSet2(commandBuffer, pPushDescriptorSetInfo, record_obj);
}

void DeviceState::PostCallRecordCmdBindDescriptorBuffersEXT(VkCommandBuffer commandBuffer, uint32_t bufferCount,
                                                            const VkDescriptorBufferBindingInfoEXT* pBindingInfos,
                                                            const RecordObject& record_obj) {
    auto cb_state = Get<CommandBuffer>(commandBuffer);
    cb_state->descriptor_buffer.ever_bound = true;

    cb_state->descriptor_buffer.binding_info.resize(bufferCount);
    for (uint32_t i = 0; i < bufferCount; i++) {
        const VkDescriptorBufferBindingInfoEXT& binding_info = pBindingInfos[i];
        VkBufferUsageFlags2 buffer_usage = binding_info.usage;
        if (const auto usage_flags2 = vku::FindStructInPNextChain<VkBufferUsageFlags2CreateInfo>(binding_info.pNext)) {
            buffer_usage = usage_flags2->usage;
        }

        cb_state->descriptor_buffer.binding_info[i] = {binding_info.address, buffer_usage};
    }

    // So really this should be set at vkCmdSetDescriptorBufferOffsetsEXT time where the bindpoint is known.
    // In practice, setting it here is better as if the app messes up, it might crash things.
    cb_state->SetDescriptorMode(DescriptorModeBuffer, record_obj.location.function);
}

void DeviceState::PostCallRecordCmdBindDescriptorBufferEmbeddedSamplersEXT(VkCommandBuffer commandBuffer,
                                                                           VkPipelineBindPoint pipelineBindPoint,
                                                                           VkPipelineLayout layout, uint32_t set,
                                                                           const RecordObject& record_obj) {
    auto cb_state = Get<CommandBuffer>(commandBuffer);
    cb_state->SetDescriptorMode(DescriptorModeBuffer, record_obj.location.function);
}

void DeviceState::PostCallRecordCmdBindDescriptorBufferEmbeddedSamplers2EXT(
    VkCommandBuffer commandBuffer, const VkBindDescriptorBufferEmbeddedSamplersInfoEXT* pBindDescriptorBufferEmbeddedSamplersInfo,
    const RecordObject& record_obj) {
    auto cb_state = Get<CommandBuffer>(commandBuffer);
    cb_state->SetDescriptorMode(DescriptorModeBuffer, record_obj.location.function);
}

void DeviceState::PostCallRecordCmdSetDescriptorBufferOffsetsEXT(VkCommandBuffer commandBuffer,
                                                                 VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
                                                                 uint32_t firstSet, uint32_t setCount,
                                                                 const uint32_t* pBufferIndices, const VkDeviceSize* pOffsets,
                                                                 const RecordObject& record_obj) {
    auto cb_state = Get<CommandBuffer>(commandBuffer);
    auto pipeline_layout = Get<PipelineLayout>(layout);
    ASSERT_AND_RETURN(pipeline_layout);

    cb_state->UpdateLastBoundDescriptorBuffers(pipelineBindPoint, pipeline_layout, firstSet, setCount, pBufferIndices, pOffsets);

    cb_state->SetDescriptorMode(vvl::DescriptorModeBuffer, record_obj.location.function);
}

void DeviceState::PostCallRecordCmdSetDescriptorBufferOffsets2EXT(
    VkCommandBuffer commandBuffer, const VkSetDescriptorBufferOffsetsInfoEXT* pSetDescriptorBufferOffsetsInfo,
    const RecordObject& record_obj) {
    auto cb_state = Get<CommandBuffer>(commandBuffer);
    auto pipeline_layout = Get<PipelineLayout>(pSetDescriptorBufferOffsetsInfo->layout);
    ASSERT_AND_RETURN(pipeline_layout);

    if (IsStageInPipelineBindPoint(pSetDescriptorBufferOffsetsInfo->stageFlags, VK_PIPELINE_BIND_POINT_GRAPHICS)) {
        cb_state->UpdateLastBoundDescriptorBuffers(
            VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, pSetDescriptorBufferOffsetsInfo->firstSet,
            pSetDescriptorBufferOffsetsInfo->setCount, pSetDescriptorBufferOffsetsInfo->pBufferIndices,
            pSetDescriptorBufferOffsetsInfo->pOffsets);
    }
    if (IsStageInPipelineBindPoint(pSetDescriptorBufferOffsetsInfo->stageFlags, VK_PIPELINE_BIND_POINT_COMPUTE)) {
        cb_state->UpdateLastBoundDescriptorBuffers(
            VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, pSetDescriptorBufferOffsetsInfo->firstSet,
            pSetDescriptorBufferOffsetsInfo->setCount, pSetDescriptorBufferOffsetsInfo->pBufferIndices,
            pSetDescriptorBufferOffsetsInfo->pOffsets);
    }
    if (IsStageInPipelineBindPoint(pSetDescriptorBufferOffsetsInfo->stageFlags, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR)) {
        cb_state->UpdateLastBoundDescriptorBuffers(
            VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline_layout, pSetDescriptorBufferOffsetsInfo->firstSet,
            pSetDescriptorBufferOffsetsInfo->setCount, pSetDescriptorBufferOffsetsInfo->pBufferIndices,
            pSetDescriptorBufferOffsetsInfo->pOffsets);
    }

    cb_state->SetDescriptorMode(vvl::DescriptorModeBuffer, record_obj.location.function);
}

void DeviceState::PostCallRecordCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout,
                                                 VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues,
                                                 const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto pipeline_layout_state = Get<PipelineLayout>(layout);
    ASSERT_AND_RETURN(cb_state && pipeline_layout_state);

    cb_state->RecordCommand(record_obj.location);
    cb_state->RecordPushConstants(*pipeline_layout_state, stageFlags, offset, size, pValues);

    cb_state->InvalidateDescriptorMode(vvl::DescriptorModeHeap, record_obj.location.function);
}

void DeviceState::PostCallRecordCmdPushConstants2(VkCommandBuffer commandBuffer, const VkPushConstantsInfo* pPushConstantsInfo,
                                                  const RecordObject& record_obj) {
    PostCallRecordCmdPushConstants(commandBuffer, pPushConstantsInfo->layout, pPushConstantsInfo->stageFlags,
                                   pPushConstantsInfo->offset, pPushConstantsInfo->size, pPushConstantsInfo->pValues, record_obj);
}

void DeviceState::PostCallRecordCmdPushConstants2KHR(VkCommandBuffer commandBuffer,
                                                     const VkPushConstantsInfoKHR* pPushConstantsInfo,
                                                     const RecordObject& record_obj) {
    PostCallRecordCmdPushConstants2(commandBuffer, pPushConstantsInfo, record_obj);
}

static VkDeviceSize GetBufferRegionSize(const std::shared_ptr<const Buffer>& buffer_state, VkDeviceSize offset, VkDeviceSize size) {
    if (buffer_state) {
        const auto buffer_size = buffer_state->GetSize();
        if (offset < buffer_size) {
            if (size == VK_WHOLE_SIZE) {
                return buffer_size - offset;
            } else if ((offset + size) <= buffer_size) {
                return size;
            }
        }
    }
    return 0;
}

void DeviceState::PostCallRecordCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                   VkIndexType indexType, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordBindIndexbuffer(record_obj.location);

    if (buffer == VK_NULL_HANDLE) {
        if (enabled_features.maintenance6) {
            cb_state->index_buffer_binding.bound = true;
        }
    } else {
        auto buffer_state = Get<Buffer>(buffer);
        // Being able to set the size was added in VK_KHR_maintenance5 via vkCmdBindIndexBuffer2KHR
        // Using this function is the same as passing in VK_WHOLE_SIZE
        VkDeviceSize buffer_size = GetBufferRegionSize(buffer_state, offset, VK_WHOLE_SIZE);
        cb_state->index_buffer_binding = IndexBufferBinding(buffer, buffer_size, offset, indexType);

        // Add binding for this index buffer to this commandbuffer
        if (!disabled[command_buffer_state]) {
            cb_state->AddChild(buffer_state);
        }
    }
}

void DeviceState::PostCallRecordCmdBindIndexBuffer2(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                    VkDeviceSize size, VkIndexType indexType, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordBindIndexbuffer(record_obj.location);

    if (buffer == VK_NULL_HANDLE) {
        if (enabled_features.maintenance6) {
            cb_state->index_buffer_binding.bound = true;
        }
    } else {
        auto buffer_state = Get<Buffer>(buffer);
        VkDeviceSize buffer_size = GetBufferRegionSize(buffer_state, offset, size);
        cb_state->index_buffer_binding = IndexBufferBinding(buffer, buffer_size, offset, indexType);

        // Add binding for this index buffer to this commandbuffer
        if (!disabled[command_buffer_state]) {
            cb_state->AddChild(buffer_state);
        }
    }
}

void DeviceState::PostCallRecordCmdBindIndexBuffer2KHR(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                       VkDeviceSize size, VkIndexType indexType, const RecordObject& record_obj) {
    PostCallRecordCmdBindIndexBuffer2(commandBuffer, buffer, offset, size, indexType, record_obj);
}

void DeviceState::PostCallRecordCmdBindIndexBuffer3KHR(VkCommandBuffer commandBuffer, const VkBindIndexBuffer3InfoKHR* pInfo,
                                                       const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordBindIndexbuffer(record_obj.location);
    cb_state->index_buffer_binding = IndexBufferBinding(pInfo->addressRange.address, pInfo->addressRange.size, pInfo->indexType);
    TrackDeviceAddressRange(*cb_state, pInfo->addressRange.address, pInfo->addressRange.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount,
                                                     const VkBuffer* pBuffers, const VkDeviceSize* pOffsets,
                                                     const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    cb_state->bind_vertex_buffer_3_used = false;

    for (uint32_t i = 0; i < bindingCount; ++i) {
        auto buffer_state = Get<Buffer>(pBuffers[i]);
        // the stride is set from the pipeline or dynamic state
        const VkDeviceSize effective_size = GetBufferRegionSize(buffer_state, pOffsets[i], VK_WHOLE_SIZE);
        cb_state->current_vertex_buffer_binding_info[i + firstBinding].Set(pBuffers[i], effective_size, pOffsets[i], nullptr);

        // Add binding for this vertex buffer to this commandbuffer
        if (pBuffers[i] && !disabled[command_buffer_state]) {
            cb_state->AddChild(buffer_state);
        }
    }
}

void DeviceState::PostCallRecordCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
                                                VkDeviceSize dataSize, const void* pData, const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) return;

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto buffer_state = Get<Buffer>(dstBuffer);
    ASSERT_AND_RETURN(buffer_state);
    cb_state->AddChild(buffer_state);
    cb_state->RecordUpdateBuffer(*buffer_state, dstOffset, dataSize, record_obj.location);
}

void DeviceState::PostCallRecordCmdUpdateMemoryKHR(VkCommandBuffer commandBuffer, const VkDeviceAddressRangeKHR* pDstRange,
                                                   VkAddressCommandFlagsKHR dstFlags, VkDeviceSize dataSize, const void* pData,
                                                   const RecordObject& record_obj) {
    if (disabled[command_buffer_state]) {
        return;
    }

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordUpdateMemory(*pDstRange, record_obj.location);

    TrackDeviceAddressRange(*cb_state, pDstRange->address, pDstRange->size, VK_BUFFER_USAGE_2_TRANSFER_DST_BIT);
}

void DeviceState::PostCallRecordCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask,
                                            const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetEvent(event, stageMask, nullptr, record_obj.location);
}

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

void DeviceState::PostCallRecordCmdSetEvent2(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo* pDependencyInfo,
                                             const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto exec_scopes = sync_utils::GetExecScopes(*pDependencyInfo);

    cb_state->RecordSetEvent(event, exec_scopes.src, pDependencyInfo, record_obj.location);
    cb_state->RecordBarrierObjects(*pDependencyInfo, record_obj.location.dot(vvl::Field::pDependencyInfo));
}

void DeviceState::PostCallRecordCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask,
                                              const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordResetEvent(event, stageMask, record_obj.location);
}

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

void DeviceState::PostCallRecordCmdResetEvent2(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask,
                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordResetEvent(event, stageMask, record_obj.location);
}

void DeviceState::PostCallRecordCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents,
                                              VkPipelineStageFlags sourceStageMask, VkPipelineStageFlags dstStageMask,
                                              uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
                                              uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers,
                                              uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers,
                                              const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    cb_state->RecordWaitEvents(eventCount, pEvents, sourceStageMask, nullptr, record_obj.location);
    cb_state->RecordBarrierObjects(bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers,
                                   sourceStageMask, dstStageMask, record_obj.location);
}

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

void DeviceState::PostCallRecordCmdWaitEvents2(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents,
                                               const VkDependencyInfo* pDependencyInfos, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    for (uint32_t i = 0; i < eventCount; i++) {
        const auto& dep_info = pDependencyInfos[i];
        auto exec_scopes = sync_utils::GetExecScopes(dep_info);
        const Location& dep_info_loc = record_obj.location.dot(vvl::Field::pDependencyInfos, i);
        cb_state->RecordWaitEvents(1, &pEvents[i], exec_scopes.src, &pDependencyInfos[i], dep_info_loc);
        cb_state->RecordBarrierObjects(dep_info, dep_info_loc);
    }
}

void DeviceState::PostCallRecordCmdPipelineBarrier(
    VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
    VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers,
    uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount,
    const VkImageMemoryBarrier* pImageMemoryBarriers, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    cb_state->RecordBarrierObjects(bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers,
                                   srcStageMask, dstStageMask, record_obj.location);
}

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

void DeviceState::PostCallRecordCmdPipelineBarrier2(VkCommandBuffer commandBuffer, const VkDependencyInfo* pDependencyInfo,
                                                    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    cb_state->RecordBarrierObjects(*pDependencyInfo, record_obj.location.dot(vvl::Field::pDependencyInfo));
}

void DeviceState::PostCallRecordCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot,
                                              VkQueryControlFlags flags, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    if (disabled[query_validation]) {
        return;
    }

    QueryCount query_count(*cb_state);

    for (uint32_t i = 0; i < query_count.count; ++i) {
        QueryObject query_obj = {queryPool, slot + i, flags};
        query_obj.inside_render_pass = query_count.inside_render_pass;
        query_obj.subpass = query_count.subpass;
        cb_state->RecordBeginQuery(query_obj, record_obj.location);
    }

    if (!disabled[command_buffer_state]) {
        auto pool_state = Get<QueryPool>(queryPool);
        cb_state->AddChild(pool_state);
    }
}

void DeviceState::PostCallRecordCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot,
                                            const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    if (disabled[query_validation]) {
        return;
    }

    QueryCount query_count(*cb_state);

    for (uint32_t i = 0; i < query_count.count; ++i) {
        QueryObject query_obj = {queryPool, slot + i};
        query_obj.inside_render_pass = query_count.inside_render_pass;
        query_obj.subpass = query_count.subpass;
        query_obj.end_command_index = cb_state->command_count;  // counting this command
        cb_state->RecordEndQuery(query_obj, record_obj.location);
    }

    if (!disabled[command_buffer_state]) {
        auto pool_state = Get<QueryPool>(queryPool);
        cb_state->AddChild(pool_state);
    }
}

void DeviceState::PostCallRecordCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery,
                                                  uint32_t queryCount, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordResetQueryPool(queryPool, firstQuery, queryCount, record_obj.location);
}

void DeviceState::PostCallRecordCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery,
                                                        uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset,
                                                        VkDeviceSize stride, VkQueryResultFlags flags,
                                                        const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCopyQueryPoolResults(queryPool, dstBuffer, firstQuery, queryCount, dstOffset, stride, flags,
                                         record_obj.location);
}

void DeviceState::PostCallRecordCmdCopyQueryPoolResultsToMemoryKHR(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
                                                                   uint32_t firstQuery, uint32_t queryCount,
                                                                   const VkStridedDeviceAddressRangeKHR* pDstRange,
                                                                   VkAddressCommandFlagsKHR dstFlags,
                                                                   VkQueryResultFlags queryResultFlags,
                                                                   const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCopyQueryPoolResultsToMemory(queryPool, firstQuery, queryCount, pDstRange, dstFlags, queryResultFlags,
                                                 record_obj.location);
    TrackDeviceAddressRange(*cb_state, pDstRange->address, pDstRange->size, VK_BUFFER_USAGE_2_TRANSFER_DST_BIT);
}

void DeviceState::PostCallRecordCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage,
                                                  VkQueryPool queryPool, uint32_t slot, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordWriteTimestamp(queryPool, slot, record_obj.location);
}

void DeviceState::PostCallRecordCmdWriteTimestamp2KHR(VkCommandBuffer commandBuffer, VkPipelineStageFlags2KHR pipelineStage,
                                                      VkQueryPool queryPool, uint32_t slot, const RecordObject& record_obj) {
    PostCallRecordCmdWriteTimestamp2(commandBuffer, pipelineStage, queryPool, slot, record_obj);
}

void DeviceState::PostCallRecordCmdWriteTimestamp2(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 pipelineStage,
                                                   VkQueryPool queryPool, uint32_t slot, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordWriteTimestamp(queryPool, slot, record_obj.location);
}

void DeviceState::PostCallRecordCmdWriteAccelerationStructuresPropertiesKHR(
    VkCommandBuffer commandBuffer, uint32_t accelerationStructureCount, const VkAccelerationStructureKHR* pAccelerationStructures,
    VkQueryType queryType, VkQueryPool queryPool, uint32_t firstQuery, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordWriteAccelerationStructuresProperties(queryPool, firstQuery, accelerationStructureCount, record_obj.location);
}

void DeviceState::PostCallRecordCreateVideoSessionKHR(VkDevice device, const VkVideoSessionCreateInfoKHR* pCreateInfo,
                                                      const VkAllocationCallbacks* pAllocator, VkVideoSessionKHR* pVideoSession,
                                                      const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    auto profile_desc = video_profile_cache_.Get(physical_device, pCreateInfo->pVideoProfile);
    Add(std::make_shared<VideoSession>(*this, *pVideoSession, pCreateInfo, std::move(profile_desc)));
}

void DeviceState::PostCallRecordGetVideoSessionMemoryRequirementsKHR(VkDevice device, VkVideoSessionKHR videoSession,
                                                                     uint32_t* pMemoryRequirementsCount,
                                                                     VkVideoSessionMemoryRequirementsKHR* pMemoryRequirements,
                                                                     const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    auto vs_state = Get<VideoSession>(videoSession);
    ASSERT_AND_RETURN(vs_state);

    if (pMemoryRequirements != nullptr) {
        if (*pMemoryRequirementsCount > vs_state->memory_bindings_queried) {
            vs_state->memory_bindings_queried = *pMemoryRequirementsCount;
        }
    } else {
        vs_state->memory_binding_count_queried = true;
    }
}

void DeviceState::PostCallRecordBindVideoSessionMemoryKHR(VkDevice device, VkVideoSessionKHR videoSession,
                                                          uint32_t bindSessionMemoryInfoCount,
                                                          const VkBindVideoSessionMemoryInfoKHR* pBindSessionMemoryInfos,
                                                          const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    auto vs_state = Get<VideoSession>(videoSession);
    ASSERT_AND_RETURN(vs_state);

    for (uint32_t i = 0; i < bindSessionMemoryInfoCount; ++i) {
        vs_state->BindMemoryBindingIndex(pBindSessionMemoryInfos[i].memoryBindIndex);
    }
}

void DeviceState::PreCallRecordDestroyVideoSessionKHR(VkDevice device, VkVideoSessionKHR videoSession,
                                                      const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<VideoSession>(videoSession);
}

void DeviceState::PostCallRecordCreateVideoSessionParametersKHR(VkDevice device,
                                                                const VkVideoSessionParametersCreateInfoKHR* pCreateInfo,
                                                                const VkAllocationCallbacks* pAllocator,
                                                                VkVideoSessionParametersKHR* pVideoSessionParameters,
                                                                const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    Add(std::make_shared<VideoSessionParameters>(*pVideoSessionParameters, pCreateInfo,
                                                 Get<VideoSession>(pCreateInfo->videoSession),
                                                 Get<VideoSessionParameters>(pCreateInfo->videoSessionParametersTemplate)));
}

void DeviceState::PostCallRecordUpdateVideoSessionParametersKHR(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters,
                                                                const VkVideoSessionParametersUpdateInfoKHR* pUpdateInfo,
                                                                const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    Get<VideoSessionParameters>(videoSessionParameters)->Update(pUpdateInfo);
}

void DeviceState::PreCallRecordDestroyVideoSessionParametersKHR(VkDevice device, VkVideoSessionParametersKHR videoSessionParameters,
                                                                const VkAllocationCallbacks* pAllocator,
                                                                const RecordObject& record_obj) {
    Destroy<VideoSessionParameters>(videoSessionParameters);
}

void DeviceState::PostCallRecordCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo,
                                                  const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer,
                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    std::vector<std::shared_ptr<ImageView>> views;
    if ((pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT) == 0) {
        views.resize(pCreateInfo->attachmentCount);

        for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
            views[i] = Get<ImageView>(pCreateInfo->pAttachments[i]);
        }
    }

    Add(std::make_shared<Framebuffer>(*pFramebuffer, pCreateInfo, Get<RenderPass>(pCreateInfo->renderPass), std::move(views)));
}

void DeviceState::PostCallRecordCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo,
                                                 const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass,
                                                 const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<RenderPass>(*pRenderPass, pCreateInfo));
}

void DeviceState::PostCallRecordCreateRenderPass2KHR(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo,
                                                     const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass,
                                                     const RecordObject& record_obj) {
    PostCallRecordCreateRenderPass2(device, pCreateInfo, pAllocator, pRenderPass, record_obj);
}

void DeviceState::PostCallRecordCreateRenderPass2(VkDevice device, const VkRenderPassCreateInfo2* pCreateInfo,
                                                  const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass,
                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    Add(std::make_shared<RenderPass>(*pRenderPass, pCreateInfo));
}

void DeviceState::PostCallRecordCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin,
                                                   VkSubpassContents contents, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    VkSubpassBeginInfo subpass_begin_info = vku::InitStructHelper();
    subpass_begin_info.contents = contents;
    cb_state->RecordBeginRenderPass(*pRenderPassBegin, subpass_begin_info, record_obj.location);
}

void DeviceState::PostCallRecordCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin,
                                                       const VkSubpassBeginInfo* pSubpassBeginInfo,
                                                       const RecordObject& record_obj) {
    PostCallRecordCmdBeginRenderPass2(commandBuffer, pRenderPassBegin, pSubpassBeginInfo, record_obj);
}

void DeviceState::PostCallRecordCmdBeginCustomResolveEXT(VkCommandBuffer commandBuffer,
                                                         const VkBeginCustomResolveInfoEXT* pBeginCustomResolveInfo,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordBeginCustomResolve(record_obj.location);
}

void DeviceState::PostCallRecordCmdBeginVideoCodingKHR(VkCommandBuffer commandBuffer, const VkVideoBeginCodingInfoKHR* pBeginInfo,
                                                       const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordBeginVideoCoding(*pBeginInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer,
                                                             uint32_t counterBufferCount, const VkBuffer* pCounterBuffers,
                                                             const VkDeviceSize* pCounterBufferOffsets,
                                                             const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    cb_state->transform_feedback_active = true;
}

void DeviceState::PostCallRecordCmdBeginTransformFeedback2EXT(VkCommandBuffer commandBuffer, uint32_t firstCounterRange,
                                                              uint32_t counterRangeCount,
                                                              const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos,
                                                              const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    cb_state->transform_feedback_active = true;
    for (uint32_t i = 0; i < counterRangeCount; ++i) {
        TrackDeviceAddressRange(*cb_state, pCounterInfos[i].addressRange.address, pCounterInfos[i].addressRange.size,
                                VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT);
    }
}

void DeviceState::PostCallRecordCmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer, uint32_t firstCounterBuffer,
                                                           uint32_t counterBufferCount, const VkBuffer* pCounterBuffers,
                                                           const VkDeviceSize* pCounterBufferOffsets,
                                                           const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    cb_state->transform_feedback_active = false;
}

void DeviceState::PostCallRecordCmdEndTransformFeedback2EXT(VkCommandBuffer commandBuffer, uint32_t firstCounterRange,
                                                            uint32_t counterRangeCount,
                                                            const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfos,
                                                            const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    cb_state->transform_feedback_active = false;
    for (uint32_t i = 0; i < counterRangeCount; ++i) {
        TrackDeviceAddressRange(*cb_state, pCounterInfos[i].addressRange.address, pCounterInfos[i].addressRange.size,
                                VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT);
    }
}

void DeviceState::PostCallRecordCmdDrawIndirectByteCount2EXT(VkCommandBuffer commandBuffer, uint32_t instanceCount,
                                                             uint32_t firstInstance,
                                                             const VkBindTransformFeedbackBuffer2InfoEXT* pCounterInfo,
                                                             uint32_t counterOffset, uint32_t vertexStride,
                                                             const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pCounterInfo->addressRange.address, pCounterInfo->addressRange.size,
                            VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT);
}

void DeviceState::PostCallRecordCmdWriteMarkerToMemoryAMD(VkCommandBuffer commandBuffer, const VkMemoryMarkerInfoAMD* pInfo,
                                                          const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pInfo->dstRange.address, pInfo->dstRange.size, VK_BUFFER_USAGE_2_TRANSFER_DST_BIT);
}

void DeviceState::PostCallRecordCmdBeginConditionalRenderingEXT(
    VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfoEXT* pConditionalRenderingBegin,
    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordBeginConditionalRendering(record_obj.location);
}

void DeviceState::PostCallRecordCmdEndConditionalRenderingEXT(VkCommandBuffer commandBuffer, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordEndConditionalRendering(record_obj.location);
}

void DeviceState::PostCallRecordCmdBeginConditionalRendering2EXT(
    VkCommandBuffer commandBuffer, const VkConditionalRenderingBeginInfo2EXT* pConditionalRenderingBegin,
    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordBeginConditionalRendering(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pConditionalRenderingBegin->addressRange.address,
                            pConditionalRenderingBegin->addressRange.size, VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT);
}

void DeviceState::PostCallRecordCmdBindTileMemoryQCOM(VkCommandBuffer commandBuffer,
                                                      const VkTileMemoryBindInfoQCOM* pTileMemoryBindInfo,
                                                      const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    // The bound tile memory can be reset by the application
    cb_state->bound_tile_memory = pTileMemoryBindInfo ? Get<vvl::DeviceMemory>(pTileMemoryBindInfo->memory) : nullptr;
}

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

void DeviceState::PostCallRecordCmdBeginRendering(VkCommandBuffer commandBuffer, const VkRenderingInfo* pRenderingInfo,
                                                  const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordBeginRendering(*pRenderingInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdEndRenderingKHR(VkCommandBuffer commandBuffer, const RecordObject& record_obj) {
    PostCallRecordCmdEndRendering(commandBuffer, record_obj);
}

void DeviceState::PostCallRecordCmdEndRendering(VkCommandBuffer commandBuffer, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordEndRendering(nullptr, record_obj.location);
}

void DeviceState::PostCallRecordCmdEndRendering2EXT(VkCommandBuffer commandBuffer, const VkRenderingEndInfoEXT* pRenderingEndInfo,
                                                    const RecordObject& record_obj) {
    PostCallRecordCmdEndRendering2KHR(commandBuffer, pRenderingEndInfo, record_obj);
}

void DeviceState::PostCallRecordCmdEndRendering2KHR(VkCommandBuffer commandBuffer, const VkRenderingEndInfoKHR* pRenderingEndInfo,
                                                    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordEndRendering(pRenderingEndInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdBeginRenderPass2(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin,
                                                    const VkSubpassBeginInfo* pSubpassBeginInfo, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordBeginRenderPass(*pRenderPassBegin, *pSubpassBeginInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents,
                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    VkSubpassBeginInfo subpass_begin_info = vku::InitStructHelper();
    subpass_begin_info.contents = contents;
    cb_state->RecordNextSubpass(subpass_begin_info, nullptr, record_obj.location);
}

void DeviceState::PostCallRecordCmdNextSubpass2KHR(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo,
                                                   const VkSubpassEndInfo* pSubpassEndInfo, const RecordObject& record_obj) {
    PostCallRecordCmdNextSubpass2(commandBuffer, pSubpassBeginInfo, pSubpassEndInfo, record_obj);
}

void DeviceState::PostCallRecordCmdNextSubpass2(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo* pSubpassBeginInfo,
                                                const VkSubpassEndInfo* pSubpassEndInfo, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordNextSubpass(*pSubpassBeginInfo, pSubpassEndInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdEndRenderPass(VkCommandBuffer commandBuffer, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordEndRenderPass(nullptr, record_obj.location);
}

void DeviceState::PostCallRecordCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo,
                                                     const RecordObject& record_obj) {
    PostCallRecordCmdEndRenderPass2(commandBuffer, pSubpassEndInfo, record_obj);
}

void DeviceState::PostCallRecordCmdEndRenderPass2(VkCommandBuffer commandBuffer, const VkSubpassEndInfo* pSubpassEndInfo,
                                                  const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordEndRenderPass(pSubpassEndInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdEndVideoCodingKHR(VkCommandBuffer commandBuffer, const VkVideoEndCodingInfoKHR* pEndCodingInfo,
                                                     const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordEndVideoCoding(record_obj.location);
}

void DeviceState::PostCallRecordCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount,
                                                   const VkCommandBuffer* pCommandBuffers, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordExecuteCommands({pCommandBuffers, commandBuffersCount}, record_obj.location);
}

void DeviceState::PostCallRecordMapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size,
                                          VkFlags flags, void** ppData, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordMappedMemory(mem, offset, size, ppData);
}

void DeviceState::PostCallRecordMapMemory2(VkDevice device, const VkMemoryMapInfo* pMemoryMapInfo, void** ppData,
                                           const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordMappedMemory(pMemoryMapInfo->memory, pMemoryMapInfo->offset, pMemoryMapInfo->size, ppData);
}

void DeviceState::PostCallRecordMapMemory2KHR(VkDevice device, const VkMemoryMapInfoKHR* pMemoryMapInfo, void** ppData,
                                              const RecordObject& record_obj) {
    PostCallRecordMapMemory2(device, pMemoryMapInfo, ppData, record_obj);
}

void DeviceState::PreCallRecordUnmapMemory(VkDevice device, VkDeviceMemory mem, const RecordObject& record_obj) {
    if (auto mem_info = Get<DeviceMemory>(mem)) {
        mem_info->mapped_range = MemRange();
        mem_info->p_driver_data = nullptr;
    }
}

void DeviceState::PreCallRecordUnmapMemory2(VkDevice device, const VkMemoryUnmapInfo* pMemoryUnmapInfo,
                                            const RecordObject& record_obj) {
    if (auto mem_info = Get<DeviceMemory>(pMemoryUnmapInfo->memory)) {
        mem_info->mapped_range = MemRange();
        mem_info->p_driver_data = nullptr;
    }
}

void DeviceState::PreCallRecordUnmapMemory2KHR(VkDevice device, const VkMemoryUnmapInfoKHR* pMemoryUnmapInfo,
                                               const RecordObject& record_obj) {
    PreCallRecordUnmapMemory2(device, pMemoryUnmapInfo, record_obj);
}

void DeviceState::UpdateBindImageMemoryState(const VkBindImageMemoryInfo& bind_info) {
    auto image_state = Get<Image>(bind_info.image);
    if (!image_state) return;

    const auto swapchain_info = vku::FindStructInPNextChain<VkBindImageMemorySwapchainInfoKHR>(bind_info.pNext);
    if (swapchain_info) {
        if (auto swapchain = Get<Swapchain>(swapchain_info->swapchain)) {
            // All images bound to this swapchain and index are aliases
            image_state->SetSwapchain(swapchain, swapchain_info->imageIndex);
        }
    } else {
        // Track bound memory range information
        if (auto mem_info = Get<DeviceMemory>(bind_info.memory)) {
            VkDeviceSize plane_index = 0u;
            if (image_state->disjoint && image_state->IsExternalBuffer() == false) {
                auto plane_info = vku::FindStructInPNextChain<VkBindImagePlaneMemoryInfo>(bind_info.pNext);
                plane_index = vkuGetPlaneIndex(plane_info->planeAspect);
            }
            image_state->BindMemory(
                image_state.get(), mem_info, bind_info.memoryOffset, plane_index,
                image_state->requirements[static_cast<decltype(image_state->requirements)::size_type>(plane_index)].size);
        }
    }
}

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

void DeviceState::PostCallRecordBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo* pBindInfos,
                                                 const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        // if bindInfoCount is 1, we know for sure if that single image was bound or not
        if (bindInfoCount > 1) {
            for (uint32_t i = 0; i < bindInfoCount; i++) {
                // If user passed in VkBindMemoryStatus, we can update which images are valid or not
                if (auto* bind_memory_status = vku::FindStructInPNextChain<VkBindMemoryStatus>(pBindInfos[i].pNext)) {
                    if (bind_memory_status->pResult && *bind_memory_status->pResult == VK_SUCCESS) {
                        UpdateBindImageMemoryState(pBindInfos[i]);
                    }
                } else if (auto image_state = Get<Image>(pBindInfos[i].image)) {
                    image_state->indeterminate_state = true;
                }
            }
        }
    } else {
        for (uint32_t i = 0; i < bindInfoCount; i++) {
            UpdateBindImageMemoryState(pBindInfos[i]);
        }
    }
}

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

void DeviceState::PreCallRecordSetEvent(VkDevice device, VkEvent event, const RecordObject& record_obj) {
    if (auto event_state = Get<Event>(event)) {
        event_state->signaled = true;
        event_state->signal_src_stage_mask = VK_PIPELINE_STAGE_HOST_BIT;
        event_state->signaling_queue = VK_NULL_HANDLE;
    }
}

void DeviceState::PostCallRecordImportSemaphoreFdKHR(VkDevice device, const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo,
                                                     const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordImportSemaphoreState(pImportSemaphoreFdInfo->semaphore, pImportSemaphoreFdInfo->handleType,
                               pImportSemaphoreFdInfo->flags);
}

void DeviceState::RecordGetExternalSemaphoreState(Semaphore& semaphore_state, VkExternalSemaphoreHandleTypeFlagBits handle_type) {
    semaphore_state.Export(handle_type);
}

#ifdef VK_USE_PLATFORM_WIN32_KHR
void InstanceState::PostCallRecordCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo,
                                                        const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                        const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}

void DeviceState::PostCallRecordAcquireFullScreenExclusiveModeEXT(VkDevice device, VkSwapchainKHR swapchain,
                                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto swapchain_state = Get<Swapchain>(swapchain);
    ASSERT_AND_RETURN(swapchain_state);
    swapchain_state->exclusive_full_screen_access = true;
}

void DeviceState::PostCallRecordReleaseFullScreenExclusiveModeEXT(VkDevice device, VkSwapchainKHR swapchain,
                                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto swapchain_state = Get<Swapchain>(swapchain);
    ASSERT_AND_RETURN(swapchain_state);
    swapchain_state->exclusive_full_screen_access = false;
}

void DeviceState::PostCallRecordImportSemaphoreWin32HandleKHR(
    VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordImportSemaphoreState(pImportSemaphoreWin32HandleInfo->semaphore, pImportSemaphoreWin32HandleInfo->handleType,
                               pImportSemaphoreWin32HandleInfo->flags);
}

void DeviceState::PostCallRecordGetSemaphoreWin32HandleKHR(VkDevice device,
                                                           const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo,
                                                           HANDLE* pHandle, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    if (auto semaphore_state = Get<Semaphore>(pGetWin32HandleInfo->semaphore)) {
        RecordGetExternalSemaphoreState(*semaphore_state, pGetWin32HandleInfo->handleType);
    }
}

void DeviceState::PostCallRecordImportFenceWin32HandleKHR(VkDevice device,
                                                          const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo,
                                                          const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordImportFenceState(pImportFenceWin32HandleInfo->fence, pImportFenceWin32HandleInfo->handleType,
                           pImportFenceWin32HandleInfo->flags);
}

void DeviceState::PostCallRecordGetFenceWin32HandleKHR(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo,
                                                       HANDLE* pHandle, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordGetExternalFenceState(pGetWin32HandleInfo->fence, pGetWin32HandleInfo->handleType, record_obj.location);
}

void DeviceState::PostCallRecordGetMemoryWin32HandleKHR(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo,
                                                        HANDLE* pHandle, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    if (const auto memory_state = Get<DeviceMemory>(pGetWin32HandleInfo->memory)) {
        // For validation purposes we need to keep allocation size and memory type index.
        // There is no need to keep pNext chain.
        ExternalOpaqueInfo external_info = {};
        external_info.allocation_size = memory_state->allocate_info.allocationSize;
        external_info.memory_type_index = memory_state->allocate_info.memoryTypeIndex;
        external_info.dedicated_buffer = memory_state->GetDedicatedBuffer();
        external_info.dedicated_image = memory_state->GetDedicatedImage();
        external_info.device_memory = pGetWin32HandleInfo->memory;

        WriteLockGuard guard(win32_handle_map_lock_);
        // `insert_or_assign` ensures that information is updated when the system decides to re-use
        // closed handle value for a new handle. The validation layer does not track handle close operation
        // which is performed by 'CloseHandle' system call.
        win32_handle_map_.insert_or_assign(*pHandle, external_info);
    }
}
#endif  // VK_USE_PLATFORM_WIN32_KHR

#ifdef VK_USE_PLATFORM_FUCHSIA
void DeviceState::PostCallRecordImportSemaphoreZirconHandleFUCHSIA(
    VkDevice device, const VkImportSemaphoreZirconHandleInfoFUCHSIA* pImportSemaphoreZirconHandleInfo,
    const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordImportSemaphoreState(pImportSemaphoreZirconHandleInfo->semaphore, pImportSemaphoreZirconHandleInfo->handleType,
                               pImportSemaphoreZirconHandleInfo->flags);
}

void DeviceState::PostCallRecordGetSemaphoreZirconHandleFUCHSIA(VkDevice device,
                                                                const VkSemaphoreGetZirconHandleInfoFUCHSIA* pGetZirconHandleInfo,
                                                                zx_handle_t* pZirconHandle, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    if (auto semaphore_state = Get<vvl::Semaphore>(pGetZirconHandleInfo->semaphore)) {
        RecordGetExternalSemaphoreState(*semaphore_state, pGetZirconHandleInfo->handleType);
    }
}
#endif  // VK_USE_PLATFORM_FUCHSIA

void DeviceState::PostCallRecordGetSemaphoreFdKHR(VkDevice device, const VkSemaphoreGetFdInfoKHR* pGetFdInfo, int* pFd,
                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    if (auto semaphore_state = Get<Semaphore>(pGetFdInfo->semaphore)) {
        // Record before locking with the WriteLockGuard
        RecordGetExternalSemaphoreState(*semaphore_state, pGetFdInfo->handleType);
    }
}

void DeviceState::RecordImportFenceState(VkFence fence, VkExternalFenceHandleTypeFlagBits handle_type, VkFenceImportFlags flags) {
    if (auto fence_node = Get<Fence>(fence)) {
        fence_node->Import(handle_type, flags);
    }
}

void DeviceState::PostCallRecordImportFenceFdKHR(VkDevice device, const VkImportFenceFdInfoKHR* pImportFenceFdInfo,
                                                 const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordImportFenceState(pImportFenceFdInfo->fence, pImportFenceFdInfo->handleType, pImportFenceFdInfo->flags);
}

void DeviceState::RecordGetExternalFenceState(VkFence fence, VkExternalFenceHandleTypeFlagBits handle_type, const Location& loc) {
    if (auto fence_state = Get<Fence>(fence)) {
        // We no longer can track inflight fence after the export - perform early retire.
        fence_state->NotifyAndWait(loc);
        fence_state->Export(handle_type);
    }
}

void DeviceState::PostCallRecordGetFenceFdKHR(VkDevice device, const VkFenceGetFdInfoKHR* pGetFdInfo, int* pFd,
                                              const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordGetExternalFenceState(pGetFdInfo->fence, pGetFdInfo->handleType, record_obj.location);
}

void DeviceState::PostCallRecordCreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo,
                                            const VkAllocationCallbacks* pAllocator, VkEvent* pEvent,
                                            const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<Event>(*pEvent, pCreateInfo));
}

void DeviceState::RecordCreateSwapchainState(VkResult result, const VkSwapchainCreateInfoKHR* pCreateInfo,
                                             VkSwapchainKHR* pSwapchain, std::shared_ptr<Surface>&& surface_state,
                                             Swapchain* old_swapchain_state) {
    if (result == VK_SUCCESS) {
        if (surface_state->swapchain) {
            surface_state->RemoveParent(surface_state->swapchain);
        }
        auto swapchain = CreateSwapchainState(pCreateInfo, *pSwapchain);
        surface_state->AddParent(swapchain.get());
        surface_state->swapchain = swapchain.get();
        swapchain->surface = std::move(surface_state);
        auto swapchain_present_modes_ci = vku::FindStructInPNextChain<VkSwapchainPresentModesCreateInfoKHR>(pCreateInfo->pNext);
        if (swapchain_present_modes_ci) {
            const uint32_t present_mode_count = swapchain_present_modes_ci->presentModeCount;
            swapchain->present_modes.reserve(present_mode_count);
            std::copy(swapchain_present_modes_ci->pPresentModes, swapchain_present_modes_ci->pPresentModes + present_mode_count,
                      std::back_inserter(swapchain->present_modes));
        }

        // Initialize swapchain image state
        {
            uint32_t swapchain_image_count = 0;
            DispatchGetSwapchainImagesKHR(device, *pSwapchain, &swapchain_image_count, nullptr);
            std::vector<VkImage> swapchain_images(swapchain_image_count);
            VkResult res = DispatchGetSwapchainImagesKHR(device, *pSwapchain, &swapchain_image_count, swapchain_images.data());
            if (res != VK_SUCCESS) {
                // There is a chance the application is out of memory, it will also fail for the user, but we want to avoid crashing
                // here
                return;
            }
            swapchain->images.resize(swapchain_image_count);
            const auto& image_ci = swapchain->image_create_info;
            for (uint32_t i = 0; i < swapchain_image_count; ++i) {
                auto format_features =
                    instance_state->GetImageFormatFeatures(physical_device, special_supported.vk_khr_format_feature_flags2,
                                                           IsExtEnabled(extensions.vk_ext_image_drm_format_modifier), device,
                                                           swapchain_images[i], image_ci.format, image_ci.tiling);
                auto image_state = CreateImageState(swapchain_images[i], image_ci.ptr(), swapchain->VkHandle(), i, format_features);

                // Detect image resuse from the old swapchain
                //
                // NOTE: The device image map uses VkImage as a key, so only one state object
                // can exist per VkImage handle. In case of handle reuse:
                //  * The image state for the new swapchain replaces the old state in the device map
                //  * The old swapchain's image is updated to point to the new state object
                if (old_swapchain_state) {
                    for (auto& old_swapchain_image : old_swapchain_state->images) {
                        const vvl::Image* old_image_state = old_swapchain_image.image_state;
                        if (old_image_state && old_image_state->VkHandle() == image_state->VkHandle()) {
                            old_swapchain_image.image_state = image_state.get();
                            break;
                        }
                    }
                }

                // Create a copy since image state is needed after move. SetSwapchain modifies image substates.
                auto image_state_ptr_copy = image_state;
                Add(std::move(image_state_ptr_copy));

                image_state->SetSwapchain(swapchain, i);
                image_state->SetInitialLayoutMap();
                swapchain->images[i].image_state = image_state.get();
            }
        }
        if (old_swapchain_state) {
            old_swapchain_state->new_swapchain = swapchain;
            swapchain->old_swapchain = old_swapchain_state->shared_from_this();
        }
        Add(std::move(swapchain));
    } else {
        surface_state->swapchain = nullptr;
    }
    // Spec requires that even if CreateSwapchainKHR fails, oldSwapchain is retired
    // Retired swapchains remain associated with the surface until they are destroyed.
    if (old_swapchain_state) {
        old_swapchain_state->retired = true;
    }
}

void DeviceState::PostCallRecordCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo,
                                                   const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain,
                                                   const RecordObject& record_obj) {
    // Handle result in RecordCreateSwapchainState
    auto surface_state = instance_state->Get<Surface>(pCreateInfo->surface);
    auto old_swapchain_state = Get<Swapchain>(pCreateInfo->oldSwapchain);
    RecordCreateSwapchainState(record_obj.result, pCreateInfo, pSwapchain, std::move(surface_state), old_swapchain_state.get());
}

void DeviceState::PreCallRecordDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain,
                                                   const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<Swapchain>(swapchain);
}

void InstanceState::PostCallRecordCreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display,
                                                       const VkDisplayModeCreateInfoKHR* pCreateInfo,
                                                       const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode,
                                                       const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        std::ostringstream ss;
        ss << "failed with " << string_VkResult(record_obj.result)
           << ", likely because the pCreateInfo->parameters (visibleRegion: "
           << string_VkExtent2D(pCreateInfo->parameters.visibleRegion) << ", refreshRate: " << pCreateInfo->parameters.refreshRate
           << ") are not compatible.\nHere are the results from vkGetDisplayModePropertiesKHR:\n";
        uint32_t mode_count = 0;
        DispatchGetDisplayModePropertiesKHR(physicalDevice, display, &mode_count, nullptr);
        if (mode_count == 0) {
            ss << "No VkDisplayModePropertiesKHR found for " << FormatHandle(display);
        } else {
            std::vector<VkDisplayModePropertiesKHR> mode_props(mode_count);
            DispatchGetDisplayModePropertiesKHR(physicalDevice, display, &mode_count, mode_props.data());
            for (uint32_t i = 0; i < mode_count; i++) {
                const VkDisplayModePropertiesKHR& mode_prop = mode_props[i];
                ss << " - [" << i << "] " << FormatHandle(mode_prop.displayMode) << '\n';
                ss << "    - visibleRegion: " << string_VkExtent2D(mode_prop.parameters.visibleRegion) << '\n';
                ss << "    - refreshRate: " << mode_prop.parameters.refreshRate << " ( "
                   << (float)mode_prop.parameters.refreshRate / 1000.0f << " Hz)\n";
            }
        }
        LogWarning("WARNING-CreateDisplayModeKHR-Failed", display, record_obj.location, "%s", ss.str().c_str());
        return;
    }
    if (!pMode) return;
    Add(std::make_shared<DisplayMode>(*pMode, physicalDevice, display));
}

void DeviceState::PostCallRecordQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo,
                                                const RecordObject& record_obj) {
    // spec: If vkQueuePresentKHR fails to enqueue the corresponding set of queue operations, it may return
    // VK_ERROR_OUT_OF_HOST_MEMORY or VK_ERROR_OUT_OF_DEVICE_MEMORY. If it does, the implementation must ensure that the state and
    // contents of any resources or synchronization primitives referenced is unaffected by the call or its failure.
    //
    // If vkQueuePresentKHR fails in such a way that the implementation is unable to make that guarantee, the implementation must
    // return VK_ERROR_DEVICE_LOST.
    //
    // However, if the presentation request is rejected by the presentation engine with an error VK_ERROR_OUT_OF_DATE_KHR,
    // VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT, or VK_ERROR_SURFACE_LOST_KHR, the set of queue operations are still considered
    // to be enqueued and thus any semaphore wait operation specified in VkPresentInfoKHR will execute when the corresponding queue
    // operation is complete.
    if (record_obj.result == VK_ERROR_OUT_OF_HOST_MEMORY || record_obj.result == VK_ERROR_OUT_OF_DEVICE_MEMORY ||
        record_obj.result == VK_ERROR_DEVICE_LOST) {
        return;
    }

    const Location present_loc = record_obj.location.dot(Field::pPresentInfo);
    const auto* present_fence_info = vku::FindStructInPNextChain<VkSwapchainPresentFenceInfoKHR>(pPresentInfo->pNext);

    std::vector<QueueSubmission> present_submissions;  // TODO: use small_vector. Update interfaces to use span
    for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
        QueueSubmission& present_submission = present_submissions.emplace_back(present_loc.dot(Field::pSwapchains, i));
        if (present_fence_info) {
            present_submission.AddFence(Get<Fence>(present_fence_info->pFences[i]));
        }
        present_submission.swapchain = Get<Swapchain>(pPresentInfo->pSwapchains[i]);
    }

    vvl::Semaphore::SwapchainWaitInfo semaphore_swapchain_info;
    // Swapchain semaphore tracking reports additional details for the common case of a single swapchain.
    // For multi-swapchain presentation, the semaphore error will also be reported but without some details.
    if (pPresentInfo->swapchainCount == 1) {
        semaphore_swapchain_info.swapchain = Get<Swapchain>(pPresentInfo->pSwapchains[0]);
        semaphore_swapchain_info.image_index = pPresentInfo->pImageIndices[0];

        // Store the value of the acquire counter that corresponds to the presented image.
        // When we get an error we can find where in the acquire history this semaphore was used the last time.
        semaphore_swapchain_info.acquire_counter_value = semaphore_swapchain_info.swapchain->acquire_request_count;

        // Usually acquire_counter_value it's the current vvl::Swapchain::acquire_count but for the case when
        // application acquires multiple images before presenting we iterate to find specific image index.
        if (uint32_t history_length = semaphore_swapchain_info.swapchain->GetAcquireHistoryLength(); history_length > 0) {
            for (int32_t history_index = int32_t(history_length - 1); history_index >= 0; history_index--) {
                uint32_t image_index =
                    semaphore_swapchain_info.swapchain->GetAcquiredImageIndexFromHistory(uint32_t(history_index));
                if (image_index == pPresentInfo->pImageIndices[0]) {
                    break;
                }
                semaphore_swapchain_info.acquire_counter_value--;
            }
        }
    }

    small_vector<std::shared_ptr<vvl::Semaphore>, 1> present_wait_semaphores;
    for (uint32_t i = 0; i < pPresentInfo->waitSemaphoreCount; ++i) {
        if (auto semaphore_state = Get<Semaphore>(pPresentInfo->pWaitSemaphores[i])) {
            semaphore_state->SetSwapchainWaitInfo(semaphore_swapchain_info);
            present_wait_semaphores.emplace_back(semaphore_state);

            // Register present wait semaphores only in the first present batch.
            // NOTE: when presenting images from multiple swapchains, if some swapchains use
            // present fences, waiting on any present fence will retire all previous present batches.
            // As a result, the present wait semaphores from the first batch will always be retired.
            if (!present_submissions.empty()) {
                present_submissions[0].AddWaitSemaphore(std::move(semaphore_state), 0);
            }
        }
    }

    // Provide present fences with information about present wait semaphores.
    // If we wait on the present fence, then it can update present semaphores
    // that they are no longer in use by the swapchain.
    bool has_external_fence = false;
    for (QueueSubmission& present_submission : present_submissions) {
        if (present_submission.fence) {
            present_submission.fence->SetPresentWaitSemaphores(present_wait_semaphores);
            if (present_submission.fence->Scope() != Fence::kInternal) {
                has_external_fence = true;
            }
        }
    }

    auto queue_state = Get<Queue>(queue);
    queue_state->is_used_for_presentation = true;
    const uint64_t last_present_seq = queue_state->PreSubmit(std::move(present_submissions));
    const SubmissionReference present_submission_ref(queue_state.get(), last_present_seq);

    if (!queue_state->is_used_for_regular_submits) {
        queue_state->UpdatePresentOnlyQueueProgress(*this);
    }

    const auto* present_id_info = vku::FindStructInPNextChain<VkPresentIdKHR>(pPresentInfo->pNext);
    const auto* present_id_info_2 = vku::FindStructInPNextChain<VkPresentId2KHR>(pPresentInfo->pNext);
    const auto* present_timings_info = vku::FindStructInPNextChain<VkPresentTimingsInfoEXT>(pPresentInfo->pNext);
    for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
        auto swapchain_data = Get<Swapchain>(pPresentInfo->pSwapchains[i]);
        if (!swapchain_data) {
            continue;
        }

        // For multi-swapchain present pResults are always available (chassis adds pResults if necessary)
        assert(pPresentInfo->swapchainCount < 2 || pPresentInfo->pResults);
        auto local_result = pPresentInfo->pResults ? pPresentInfo->pResults[i] : record_obj.result;

        // If the present timing queue reports as full, any waits would have been enqueued and therefore need to
        // be tracked here, however the presentation will be dropped
        if (local_result == VK_ERROR_PRESENT_TIMING_QUEUE_FULL_EXT) {
            queue_state->Notify(last_present_seq);
            for (const auto& semaphore : present_wait_semaphores) {
                semaphore->ClearSwapchainWaitInfo();
            }
            continue;
        }

        // Mark the image as having been released to the WSI
        uint64_t present_id = 0;
        // TODO - need to know what happens if both are included
        // https://gitlab.khronos.org/vulkan/vulkan/-/issues/4317
        if (present_id_info_2 && i < present_id_info_2->swapchainCount) {
            present_id = present_id_info_2->pPresentIds[i];
        } else if (present_id_info && i < present_id_info->swapchainCount) {
            present_id = present_id_info->pPresentIds[i];
        }

        if (present_timings_info && present_timings_info->pTimingInfos[i].presentStageQueries) {
            const Swapchain::PresentTimingInfo presentTimingInfo{
                CountSetBits(present_timings_info->pTimingInfos[i].presentStageQueries), present_submission_ref};
            swapchain_data->present_timing_stage_queries.push_back({present_id, presentTimingInfo});
        }

        // spec: "However, if the presentation request is rejected by the presentation engine with an error
        // VK_ERROR_OUT_OF_DATE_KHR, VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT, or VK_ERROR_SURFACE_LOST_KHR, the set of queue
        // operations are still considered to be enqueued and thus any semaphore wait operation specified in VkPresentInfoKHR will
        // execute when the corresponding queue operation is complete."
        if (!IsValueIn(local_result, {VK_SUCCESS, VK_SUBOPTIMAL_KHR, VK_ERROR_OUT_OF_DATE_KHR,
                                      VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT, VK_ERROR_SURFACE_LOST_KHR})) {
            continue;
        }

        swapchain_data->PresentImage(pPresentInfo->pImageIndices[i], present_id, present_submission_ref, present_wait_semaphores);
    }

    // Wait on the external fence because we may not be able to track when it's signaled
    if (has_external_fence) {
        queue_state->NotifyAndWait(record_obj.location, last_present_seq);
    }
}

void DeviceState::PostCallRecordReleaseSwapchainImagesKHR(VkDevice device, const VkReleaseSwapchainImagesInfoKHR* pReleaseInfo,
                                                          const RecordObject& record_obj) {
    if (auto swapchain_data = Get<Swapchain>(pReleaseInfo->swapchain)) {
        for (uint32_t i = 0; i < pReleaseInfo->imageIndexCount; ++i) {
            swapchain_data->ReleaseImage(pReleaseInfo->pImageIndices[i]);
        }
    }
}

void DeviceState::PostCallRecordReleaseSwapchainImagesEXT(VkDevice device, const VkReleaseSwapchainImagesInfoEXT* pReleaseInfo,
                                                          const RecordObject& record_obj) {
    PostCallRecordReleaseSwapchainImagesKHR(device, pReleaseInfo, record_obj);
}

void DeviceState::PostCallRecordSetSwapchainPresentTimingQueueSizeEXT(VkDevice device, VkSwapchainKHR swapchain, uint32_t size,
                                                                      const RecordObject& record_obj) {
    auto swapchain_state = Get<Swapchain>(swapchain);
    swapchain_state->present_timing_queue_size = size;
}

void DeviceState::PostCallRecordGetSwapchainTimeDomainPropertiesEXT(
    VkDevice device, VkSwapchainKHR swapchain, VkSwapchainTimeDomainPropertiesEXT* pSwapchainTimeDomainProperties,
    uint64_t* pTimeDomainsCounter, const RecordObject& record_obj) {
    auto swapchain_state = Get<Swapchain>(swapchain);
    if (pSwapchainTimeDomainProperties->pTimeDomainIds) {
        for (uint32_t i = 0; i < pSwapchainTimeDomainProperties->timeDomainCount; ++i) {
            swapchain_state->time_domains[pSwapchainTimeDomainProperties->pTimeDomainIds[i]] =
                pSwapchainTimeDomainProperties->pTimeDomains[i];
        }
    }
}

void DeviceState::PostCallRecordGetPastPresentationTimingEXT(
    VkDevice device, const VkPastPresentationTimingInfoEXT* pPastPresentationTimingInfo,
    VkPastPresentationTimingPropertiesEXT* pPastPresentationTimingProperties, const RecordObject& record_obj) {
    if (pPastPresentationTimingProperties->pPresentationTimings != nullptr) {
        auto swapchain = Get<Swapchain>(pPastPresentationTimingInfo->swapchain);
        for (uint32_t i = 0; i < pPastPresentationTimingProperties->presentationTimingCount; ++i) {
            if (pPastPresentationTimingProperties->pPresentationTimings[i].reportComplete) {
                const SubmissionReference present_submission_ref =
                    swapchain->present_timing_stage_queries.front().second.present_submission_ref;
                present_submission_ref.queue->NotifyAndWait(record_obj.location, present_submission_ref.seq);
                swapchain->present_timing_stage_queries.pop_front();
            }
        }
    }
}

void DeviceState::PostCallRecordCreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount,
                                                          const VkSwapchainCreateInfoKHR* pCreateInfos,
                                                          const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains,
                                                          const RecordObject& record_obj) {
    // Handle result in RecordCreateSwapchainState
    if (pCreateInfos) {
        for (uint32_t i = 0; i < swapchainCount; i++) {
            const VkSwapchainCreateInfoKHR& create_info = pCreateInfos[i];
            auto surface_state = instance_state->Get<Surface>(create_info.surface);
            auto old_swapchain_state = Get<Swapchain>(create_info.oldSwapchain);
            RecordCreateSwapchainState(record_obj.result, &create_info, &pSwapchains[i], std::move(surface_state),
                                       old_swapchain_state.get());
        }
    }
}

void DeviceState::RecordAcquireNextImageState(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore,
                                              VkFence fence, uint32_t* pImageIndex, Func command) {
    auto fence_state = Get<Fence>(fence);
    if (fence_state) {
        // Treat as inflight since it is valid to wait on this fence, even in cases where it is technically a temporary
        // import
        fence_state->EnqueueSignal(nullptr, 0);
    }

    auto semaphore_state = Get<Semaphore>(semaphore);
    if (semaphore_state) {
        // Treat as signaled since it is valid to wait on this semaphore, even in cases where it is technically a
        // temporary import
        semaphore_state->EnqueueAcquire(command);
    }

    // Mark the image as acquired.
    auto swapchain_data = Get<Swapchain>(swapchain);
    if (swapchain_data) {
        swapchain_data->AcquireImage(*pImageIndex, semaphore_state, fence_state);
    }
}

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

void DeviceState::PostCallRecordAcquireNextImage2KHR(VkDevice device, const VkAcquireNextImageInfoKHR* pAcquireInfo,
                                                     uint32_t* pImageIndex, const RecordObject& record_obj) {
    if ((VK_SUCCESS != record_obj.result) && (VK_SUBOPTIMAL_KHR != record_obj.result)) return;
    RecordAcquireNextImageState(device, pAcquireInfo->swapchain, pAcquireInfo->timeout, pAcquireInfo->semaphore,
                                pAcquireInfo->fence, pImageIndex, record_obj.location.function);
}

void DeviceState::RecordWaitForPresent(VkDevice device, VkSwapchainKHR swapchain, uint64_t present_id, const Location& location) {
    if (auto swapchain_state = Get<Swapchain>(swapchain)) {
        // Find the smallest registered present id >= the given present id,
        // and ensure that the queue has progressed to the corresponding seq location
        const uint32_t present_id_info_count = swapchain_state->GetPresentIdInfoCount();
        for (uint32_t i = 0; i < present_id_info_count; i++) {
            const Swapchain::PresentIdInfo present_id_info = swapchain_state->GetPresentIdInfo(i);
            if (present_id_info.present_id >= present_id) {
                present_id_info.present_submission_ref.queue->NotifyAndWait(location, present_id_info.present_submission_ref.seq);
                break;
            }
        }
    }
}

void DeviceState::PostCallRecordWaitForPresentKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t presentId, uint64_t timeout,
                                                  const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS && record_obj.result != VK_SUBOPTIMAL_KHR) {
        return;
    }
    RecordWaitForPresent(device, swapchain, presentId, record_obj.location);
}

void DeviceState::PostCallRecordWaitForPresent2KHR(VkDevice device, VkSwapchainKHR swapchain,
                                                   const VkPresentWait2InfoKHR* pPresentWait2Info, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS && record_obj.result != VK_SUBOPTIMAL_KHR) {
        return;
    }
    RecordWaitForPresent(device, swapchain, pPresentWait2Info->presentId, record_obj.location);
}

std::shared_ptr<PhysicalDevice> InstanceState::CreatePhysicalDeviceState(VkPhysicalDevice handle) {
    return std::make_shared<PhysicalDevice>(handle);
}

void InstanceState::PostCallRecordCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator,
                                                 VkInstance* pInstance, const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    uint32_t count = 0;
    // this can fail if the allocator fails
    VkResult result = DispatchEnumeratePhysicalDevices(*pInstance, &count, nullptr);
    if (result != VK_SUCCESS) {
        return;
    }
    std::vector<VkPhysicalDevice> physdev_handles(count);
    result = DispatchEnumeratePhysicalDevices(*pInstance, &count, physdev_handles.data());
    if (result != VK_SUCCESS) {
        return;
    }

    for (auto physdev : physdev_handles) {
        Add(CreatePhysicalDeviceState(physdev));
    }

#ifdef VK_USE_PLATFORM_METAL_EXT
    auto export_metal_object_info = vku::FindStructInPNextChain<VkExportMetalObjectCreateInfoEXT>(pCreateInfo->pNext);
    while (export_metal_object_info) {
        export_metal_flags.push_back(export_metal_object_info->exportObjectType);
        export_metal_object_info = vku::FindStructInPNextChain<VkExportMetalObjectCreateInfoEXT>(export_metal_object_info->pNext);
    }
#endif  // VK_USE_PLATFORM_METAL_EXT
}

void InstanceState::PreCallRecordCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo,
                                              const VkAllocationCallbacks* pAllocator, VkDevice* pDevice,
                                              const RecordObject& record_obj, vku::safe_VkDeviceCreateInfo* modified_create_info) {
#if defined(VVL_TRACY_GPU)
    auto ext_already_enabled = [](const vku::safe_VkDeviceCreateInfo* dci, const char* ext_name) {
        bool ext_enabled = false;
        for (auto ext : make_span(dci->ppEnabledExtensionNames, dci->enabledExtensionCount)) {
            if (strcmp(ext, ext_name) == 0) {
                ext_enabled = true;
                break;
            }
        }
        return ext_enabled;
    };

    auto enable_ext = [](vku::safe_VkDeviceCreateInfo* dci, const char* ext_name) {
        const char** tmp_ppEnabledExtensionNames = new const char*[dci->enabledExtensionCount + 1];
        for (uint32_t i = 0; i < dci->enabledExtensionCount; ++i) {
            tmp_ppEnabledExtensionNames[i] = vku::SafeStringCopy(dci->ppEnabledExtensionNames[i]);
        }
        tmp_ppEnabledExtensionNames[dci->enabledExtensionCount] = vku::SafeStringCopy(ext_name);
        dci->ppEnabledExtensionNames = tmp_ppEnabledExtensionNames;
        ++dci->enabledExtensionCount;
    };

    if (!ext_already_enabled(modified_create_info, VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME)) {
        enable_ext(modified_create_info, VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME);
    }
    auto host_query_reset_feature = const_cast<VkPhysicalDeviceHostQueryResetFeatures*>(
        vku::FindStructInPNextChain<VkPhysicalDeviceHostQueryResetFeatures>(pCreateInfo->pNext));
    if (host_query_reset_feature) {
        host_query_reset_feature->hostQueryReset = VK_TRUE;
    } else {
        VkPhysicalDeviceHostQueryResetFeatures new_host_query_reset_feature = vku::InitStructHelper();
        new_host_query_reset_feature.hostQueryReset = VK_TRUE;
        vku::AddToPnext(*modified_create_info, new_host_query_reset_feature);
    }

    if (!ext_already_enabled(modified_create_info, VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME)) {
        enable_ext(modified_create_info, VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME);
    }
#endif
}

// Common function to update state for GetPhysicalDeviceQueueFamilyProperties & 2KHR version
static void StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(PhysicalDevice* pd_state, uint32_t count) {
    pd_state->queue_family_known_count = std::max(pd_state->queue_family_known_count, count);
}

void InstanceState::PostCallRecordGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
                                                                         uint32_t* pQueueFamilyPropertyCount,
                                                                         VkQueueFamilyProperties* pQueueFamilyProperties,
                                                                         const RecordObject& record_obj) {
    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state.get(), *pQueueFamilyPropertyCount);
}

void InstanceState::PostCallRecordGetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
                                                                          uint32_t* pQueueFamilyPropertyCount,
                                                                          VkQueueFamilyProperties2* pQueueFamilyProperties,
                                                                          const RecordObject& record_obj) {
    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    StateUpdateCommonGetPhysicalDeviceQueueFamilyProperties(pd_state.get(), *pQueueFamilyPropertyCount);
}

void InstanceState::PostCallRecordGetPhysicalDeviceQueueFamilyProperties2KHR(VkPhysicalDevice physicalDevice,
                                                                             uint32_t* pQueueFamilyPropertyCount,
                                                                             VkQueueFamilyProperties2* pQueueFamilyProperties,
                                                                             const RecordObject& record_obj) {
    PostCallRecordGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties,
                                                          record_obj);
}

void InstanceState::PreCallRecordDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
                                                   const VkAllocationCallbacks* pAllocator, const RecordObject& record_obj) {
    Destroy<Surface>(surface);
}

void InstanceState::RecordVulkanSurface(VkSurfaceKHR* pSurface) { Add(std::make_shared<Surface>(*pSurface)); }

void InstanceState::PostCallRecordCreateDisplayPlaneSurfaceKHR(VkInstance instance,
                                                               const VkDisplaySurfaceCreateInfoKHR* pCreateInfo,
                                                               const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                               const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}

#ifdef VK_USE_PLATFORM_ANDROID_KHR
void InstanceState::PostCallRecordCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
                                                          const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                          const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}
#endif  // VK_USE_PLATFORM_ANDROID_KHR

#ifdef VK_USE_PLATFORM_FUCHSIA
void InstanceState::PostCallRecordCreateImagePipeSurfaceFUCHSIA(VkInstance instance,
                                                                const VkImagePipeSurfaceCreateInfoFUCHSIA* pCreateInfo,
                                                                const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                                const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}
#endif  // VK_USE_PLATFORM_FUCHSIA

#ifdef VK_USE_PLATFORM_IOS_MVK
void InstanceState::PostCallRecordCreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK* pCreateInfo,
                                                      const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                      const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}
#endif  // VK_USE_PLATFORM_IOS_MVK

#ifdef VK_USE_PLATFORM_MACOS_MVK
void InstanceState::PostCallRecordCreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK* pCreateInfo,
                                                        const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                        const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}
#endif  // VK_USE_PLATFORM_MACOS_MVK

#ifdef VK_USE_PLATFORM_METAL_EXT
void InstanceState::PostCallRecordCreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo,
                                                        const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                        const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}
#endif  // VK_USE_PLATFORM_METAL_EXT

#ifdef VK_USE_PLATFORM_WAYLAND_KHR
void InstanceState::PostCallRecordCreateWaylandSurfaceKHR(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo,
                                                          const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                          const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}
#endif  // VK_USE_PLATFORM_WAYLAND_KHR

#ifdef VK_USE_PLATFORM_XCB_KHR
void InstanceState::PostCallRecordCreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo,
                                                      const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                      const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
#if defined(DEBUG_CAPTURE_KEYBOARD)
    xcb_connection = (void*)pCreateInfo->connection;
#endif
    RecordVulkanSurface(pSurface);
}
#endif  // VK_USE_PLATFORM_XCB_KHR

#ifdef VK_USE_PLATFORM_XLIB_KHR
void InstanceState::PostCallRecordCreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo,
                                                       const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                       const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
#if defined(DEBUG_CAPTURE_KEYBOARD)
    xlib_display = (void*)pCreateInfo->dpy;
#endif
    RecordVulkanSurface(pSurface);
}
#endif  // VK_USE_PLATFORM_XLIB_KHR

#ifdef VK_USE_PLATFORM_SCREEN_QNX
void InstanceState::PostCallRecordCreateScreenSurfaceQNX(VkInstance instance, const VkScreenSurfaceCreateInfoQNX* pCreateInfo,
                                                         const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                         const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}
#endif  // VK_USE_PLATFORM_SCREEN_QNX

void InstanceState::PostCallRecordCreateHeadlessSurfaceEXT(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT* pCreateInfo,
                                                           const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface,
                                                           const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    RecordVulkanSurface(pSurface);
}

void InstanceState::PostCallRecordGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
                                                                          VkSurfaceCapabilitiesKHR* pSurfaceCapabilities,
                                                                          const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    ASSERT_AND_RETURN(pd_state);
    pd_state->SetCallState(record_obj.location.function, CallState::QueryDetails);

    auto surface_state = Get<Surface>(surface);
    ASSERT_AND_RETURN(surface_state);
    surface_state->UpdateCapabilitiesCache(physicalDevice, *pSurfaceCapabilities);
}

void InstanceState::PostCallRecordGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,
                                                                           const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
                                                                           VkSurfaceCapabilities2KHR* pSurfaceCapabilities,
                                                                           const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    ASSERT_AND_RETURN(pd_state);

    pd_state->SetCallState(record_obj.location.function, CallState::QueryDetails);

    if (pSurfaceInfo->surface) {
        auto surface_state = Get<Surface>(pSurfaceInfo->surface);
        ASSERT_AND_RETURN(surface_state);
        if (!pSurfaceInfo->pNext) {
            surface_state->UpdateCapabilitiesCache(physicalDevice, pSurfaceCapabilities->surfaceCapabilities);
        } else if (IsExtEnabled(extensions.vk_khr_surface_maintenance1) || IsExtEnabled(extensions.vk_ext_surface_maintenance1)) {
            const auto* surface_present_mode = vku::FindStructInPNextChain<VkSurfacePresentModeKHR>(pSurfaceInfo->pNext);
            if (surface_present_mode) {
                // The surface caps caching should take into account pSurfaceInfo->pNext chain structure,
                // because each pNext element can affect query result. Here we support caching for a common
                // case when pNext chain is a single VkSurfacePresentModeKHR structure.
                const bool single_pnext_element = (pSurfaceInfo->pNext == surface_present_mode) && !surface_present_mode->pNext;
                if (single_pnext_element) {
                    surface_state->UpdateCapabilitiesCache(physicalDevice, *pSurfaceCapabilities,
                                                           surface_present_mode->presentMode);
                }
            }
        }
    } else if (IsExtEnabled(extensions.vk_google_surfaceless_query) &&
               vku::FindStructInPNextChain<VkSurfaceProtectedCapabilitiesKHR>(pSurfaceCapabilities->pNext)) {
        pd_state->surfaceless_query_state.capabilities = vku::safe_VkSurfaceCapabilities2KHR(pSurfaceCapabilities);
    }
}

void InstanceState::PostCallRecordGetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
                                                                           VkSurfaceCapabilities2EXT* pSurfaceCapabilities,
                                                                           const RecordObject& record_obj) {
    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    ASSERT_AND_RETURN(pd_state);
    pd_state->SetCallState(record_obj.location.function, CallState::Uncalled);

    const VkSurfaceCapabilitiesKHR caps{
        pSurfaceCapabilities->minImageCount,           pSurfaceCapabilities->maxImageCount,
        pSurfaceCapabilities->currentExtent,           pSurfaceCapabilities->minImageExtent,
        pSurfaceCapabilities->maxImageExtent,          pSurfaceCapabilities->maxImageArrayLayers,
        pSurfaceCapabilities->supportedTransforms,     pSurfaceCapabilities->currentTransform,
        pSurfaceCapabilities->supportedCompositeAlpha, pSurfaceCapabilities->supportedUsageFlags,
    };
    auto surface_state = Get<Surface>(surface);
    ASSERT_AND_RETURN(surface_state);
    surface_state->UpdateCapabilitiesCache(physicalDevice, caps);
}

void InstanceState::PostCallRecordGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex,
                                                                     VkSurfaceKHR surface, VkBool32* pSupported,
                                                                     const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    auto surface_state = Get<Surface>(surface);
    ASSERT_AND_RETURN(surface_state);
    surface_state->SetQueueSupport(physicalDevice, queueFamilyIndex, (*pSupported == VK_TRUE));
}

void InstanceState::PostCallRecordGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
                                                                          uint32_t* pPresentModeCount,
                                                                          VkPresentModeKHR* pPresentModes,
                                                                          const RecordObject& record_obj) {
    if ((VK_SUCCESS != record_obj.result) && (VK_INCOMPLETE != record_obj.result)) return;

    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    ASSERT_AND_RETURN(pd_state);

    pd_state->SetCallState(record_obj.location.function, pPresentModes != nullptr);

    if (pPresentModes) {
        if (surface) {
            auto surface_state = Get<Surface>(surface);
            ASSERT_AND_RETURN(surface_state);
            surface_state->SetPresentModes(physicalDevice, span<const VkPresentModeKHR>(pPresentModes, *pPresentModeCount));
        } else if (IsExtEnabled(extensions.vk_google_surfaceless_query)) {
            pd_state->surfaceless_query_state.present_modes =
                std::vector<VkPresentModeKHR>(pPresentModes, pPresentModes + *pPresentModeCount);
        }
    }
}

void InstanceState::PostCallRecordGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
                                                                     uint32_t* pSurfaceFormatCount,
                                                                     VkSurfaceFormatKHR* pSurfaceFormats,
                                                                     const RecordObject& record_obj) {
    if ((VK_SUCCESS != record_obj.result) && (VK_INCOMPLETE != record_obj.result)) return;

    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    if (!pd_state) {
        return;
    }

    pd_state->SetCallState(record_obj.location.function, pSurfaceFormats != nullptr);

    if (pSurfaceFormatCount) {
        pd_state->surface_formats_count = *pSurfaceFormatCount;
    }
    if (pSurfaceFormats) {
        std::vector<vku::safe_VkSurfaceFormat2KHR> formats2(*pSurfaceFormatCount);
        for (uint32_t surface_format_index = 0; surface_format_index < *pSurfaceFormatCount; surface_format_index++) {
            formats2[surface_format_index].surfaceFormat = pSurfaceFormats[surface_format_index];
        }
        if (surface) {
            auto surface_state = Get<Surface>(surface);
            ASSERT_AND_RETURN(surface_state);
            surface_state->SetFormats(physicalDevice, std::move(formats2));
        } else if (IsExtEnabled(extensions.vk_google_surfaceless_query)) {
            ASSERT_AND_RETURN(pd_state);
            pd_state->surfaceless_query_state.formats = std::move(formats2);
        }
    }
}

void InstanceState::PostCallRecordGetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
                                                                      const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
                                                                      uint32_t* pSurfaceFormatCount,
                                                                      VkSurfaceFormat2KHR* pSurfaceFormats,
                                                                      const RecordObject& record_obj) {
    if ((VK_SUCCESS != record_obj.result) && (VK_INCOMPLETE != record_obj.result)) return;

    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    ASSERT_AND_RETURN(pd_state);
    pd_state->SetCallState(record_obj.location.function, pSurfaceFormats != nullptr);
    if (*pSurfaceFormatCount) {
        pd_state->surface_formats_count = *pSurfaceFormatCount;
    }
    if (pSurfaceFormats) {
        if (pSurfaceInfo->surface) {
            auto surface_state = Get<Surface>(pSurfaceInfo->surface);
            ASSERT_AND_RETURN(surface_state);
            std::vector<vku::safe_VkSurfaceFormat2KHR> formats2(*pSurfaceFormatCount);
            for (uint32_t surface_format_index = 0; surface_format_index < *pSurfaceFormatCount; surface_format_index++) {
                formats2[surface_format_index].initialize(&pSurfaceFormats[surface_format_index]);
            }
            surface_state->SetFormats(physicalDevice, std::move(formats2));
        } else if (IsExtEnabled(extensions.vk_google_surfaceless_query)) {
            pd_state->surfaceless_query_state.formats.clear();
            pd_state->surfaceless_query_state.formats.reserve(*pSurfaceFormatCount);
            for (uint32_t surface_format_index = 0; surface_format_index < *pSurfaceFormatCount; ++surface_format_index) {
                pd_state->surfaceless_query_state.formats.emplace_back(&pSurfaceFormats[surface_format_index]);
            }
        }
    }
}

void DeviceState::PreCallRecordCmdBeginDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo,
                                                          const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    debug_report->BeginCmdDebugUtilsLabel(commandBuffer, pLabelInfo);
}

void DeviceState::PostCallRecordCmdBeginDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo,
                                                           const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->BeginLabel((pLabelInfo && pLabelInfo->pLabelName) ? pLabelInfo->pLabelName : "");
}

void DeviceState::PostCallRecordCmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    cb_state->EndLabel();
    debug_report->EndCmdDebugUtilsLabel(commandBuffer);
}

void DeviceState::PreCallRecordCmdInsertDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, const VkDebugUtilsLabelEXT* pLabelInfo,
                                                           const RecordObject& record_obj) {
    debug_report->InsertCmdDebugUtilsLabel(commandBuffer, pLabelInfo);

    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
}

void DeviceState::PostCallRecordAcquireProfilingLockKHR(VkDevice device, const VkAcquireProfilingLockInfoKHR* pInfo,
                                                        const RecordObject& record_obj) {
    if (record_obj.result == VK_SUCCESS) performance_lock_acquired = true;
}

void DeviceState::PostCallRecordReleaseProfilingLockKHR(VkDevice device, const RecordObject& record_obj) {
    performance_lock_acquired = false;
    for (auto& cmd_buffer : command_buffer_map_.snapshot()) {
        cmd_buffer.second->performance_lock_released = true;
    }
}

void DeviceState::PreCallRecordDestroyDescriptorUpdateTemplate(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate,
                                                               const VkAllocationCallbacks* pAllocator,
                                                               const RecordObject& record_obj) {
    Destroy<DescriptorUpdateTemplate>(descriptorUpdateTemplate);
}

void DeviceState::PreCallRecordDestroyDescriptorUpdateTemplateKHR(VkDevice device,
                                                                  VkDescriptorUpdateTemplate descriptorUpdateTemplate,
                                                                  const VkAllocationCallbacks* pAllocator,
                                                                  const RecordObject& record_obj) {
    PreCallRecordDestroyDescriptorUpdateTemplate(device, descriptorUpdateTemplate, pAllocator, record_obj);
}

void DeviceState::PostCallRecordCreateDescriptorUpdateTemplate(VkDevice device,
                                                               const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
                                                               const VkAllocationCallbacks* pAllocator,
                                                               VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate,
                                                               const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<DescriptorUpdateTemplate>(*pDescriptorUpdateTemplate, pCreateInfo));
}

void DeviceState::PostCallRecordCreateDescriptorUpdateTemplateKHR(VkDevice device,
                                                                  const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo,
                                                                  const VkAllocationCallbacks* pAllocator,
                                                                  VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate,
                                                                  const RecordObject& record_obj) {
    PostCallRecordCreateDescriptorUpdateTemplate(device, pCreateInfo, pAllocator, pDescriptorUpdateTemplate, record_obj);
}

void DeviceState::PreCallRecordUpdateDescriptorSetWithTemplate(VkDevice device, VkDescriptorSet descriptorSet,
                                                               VkDescriptorUpdateTemplate descriptorUpdateTemplate,
                                                               const void* pData, const RecordObject& record_obj) {
    if (auto const template_state = Get<DescriptorUpdateTemplate>(descriptorUpdateTemplate)) {
        // TODO: Record template push descriptor updates
        if (template_state->create_info.templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET) {
            PerformUpdateDescriptorSetsWithTemplateKHR(descriptorSet, *template_state, pData);
        }
    }
}

void DeviceState::PreCallRecordUpdateDescriptorSetWithTemplateKHR(VkDevice device, VkDescriptorSet descriptorSet,
                                                                  VkDescriptorUpdateTemplate descriptorUpdateTemplate,
                                                                  const void* pData, const RecordObject& record_obj) {
    PreCallRecordUpdateDescriptorSetWithTemplate(device, descriptorSet, descriptorUpdateTemplate, pData, record_obj);
}

void DeviceState::PostCallRecordCmdPushDescriptorSetWithTemplate(VkCommandBuffer commandBuffer,
                                                                 VkDescriptorUpdateTemplate descriptorUpdateTemplate,
                                                                 VkPipelineLayout layout, uint32_t set, const void* pData,
                                                                 const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto template_state = Get<DescriptorUpdateTemplate>(descriptorUpdateTemplate);
    auto pipeline_layout = Get<PipelineLayout>(layout);

    if (pipeline_layout->has_descriptor_buffer) {
        cb_state->SetDescriptorMode(vvl::DescriptorModeBuffer, record_obj.location.function);
    } else {
        cb_state->SetDescriptorMode(vvl::DescriptorModeClassic, record_obj.location.function);
    }

    if (!template_state || !pipeline_layout) {
        return;
    }

    cb_state->RecordCommand(record_obj.location);
    auto dsl = pipeline_layout->set_layouts.list[set];
    // Decode the template into a set of write updates
    DecodedTemplateUpdate decoded_template(*this, VK_NULL_HANDLE, *template_state, pData, dsl->VkHandle());
    cb_state->PushDescriptorSetState(template_state->create_info.pipelineBindPoint, pipeline_layout, set,
                                     static_cast<uint32_t>(decoded_template.desc_writes.size()),
                                     decoded_template.desc_writes.data(), record_obj.location);
}

void DeviceState::PostCallRecordCmdPushDescriptorSetWithTemplateKHR(VkCommandBuffer commandBuffer,
                                                                    VkDescriptorUpdateTemplate descriptorUpdateTemplate,
                                                                    VkPipelineLayout layout, uint32_t set, const void* pData,
                                                                    const RecordObject& record_obj) {
    PostCallRecordCmdPushDescriptorSetWithTemplate(commandBuffer, descriptorUpdateTemplate, layout, set, pData, record_obj);
}

void DeviceState::PostCallRecordCmdPushDescriptorSetWithTemplate2(
    VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfo* pPushDescriptorSetWithTemplateInfo,
    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto template_state = Get<DescriptorUpdateTemplate>(pPushDescriptorSetWithTemplateInfo->descriptorUpdateTemplate);
    auto pipeline_layout = Get<PipelineLayout>(pPushDescriptorSetWithTemplateInfo->layout);

    if (pipeline_layout->has_descriptor_buffer) {
        cb_state->SetDescriptorMode(vvl::DescriptorModeBuffer, record_obj.location.function);
    } else {
        cb_state->SetDescriptorMode(vvl::DescriptorModeClassic, record_obj.location.function);
    }

    if (!template_state || !pipeline_layout) {
        return;
    }

    cb_state->RecordCommand(record_obj.location);
    auto dsl = pipeline_layout->set_layouts.list[pPushDescriptorSetWithTemplateInfo->set];
    // Decode the template into a set of write updates
    DecodedTemplateUpdate decoded_template(*this, VK_NULL_HANDLE, *template_state, pPushDescriptorSetWithTemplateInfo->pData,
                                           dsl->VkHandle());
    cb_state->PushDescriptorSetState(
        template_state->create_info.pipelineBindPoint, pipeline_layout, pPushDescriptorSetWithTemplateInfo->set,
        static_cast<uint32_t>(decoded_template.desc_writes.size()), decoded_template.desc_writes.data(), record_obj.location);
}

void DeviceState::PostCallRecordCmdPushDescriptorSetWithTemplate2KHR(
    VkCommandBuffer commandBuffer, const VkPushDescriptorSetWithTemplateInfoKHR* pPushDescriptorSetWithTemplateInfo,
    const RecordObject& record_obj) {
    PostCallRecordCmdPushDescriptorSetWithTemplate2(commandBuffer, pPushDescriptorSetWithTemplateInfo, record_obj);
}

void InstanceState::PostCallRecordGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures,
                                                            const RecordObject& record_obj) {
    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    pd_state->SetCallState(record_obj.location.function, true);
}

void InstanceState::PostCallRecordGetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2* pFeatures,
                                                             const RecordObject& record_obj) {
    auto pd_state = Get<PhysicalDevice>(physicalDevice);
    pd_state->SetCallState(record_obj.location.function, true);
}

void InstanceState::PostCallRecordGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice,
                                                                VkPhysicalDeviceFeatures2* pFeatures,
                                                                const RecordObject& record_obj) {
    PostCallRecordGetPhysicalDeviceFeatures2(physicalDevice, pFeatures, record_obj);
}

void DeviceState::PostCallRecordCmdBeginQueryIndexedEXT(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot,
                                                        VkQueryControlFlags flags, uint32_t index, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    if (disabled[query_validation]) {
        return;
    }

    QueryCount query_count(*cb_state);

    for (uint32_t i = 0; i < query_count.count; ++i) {
        QueryObject query_obj = {queryPool, slot, flags, 0, true, index + i};
        query_obj.inside_render_pass = query_count.inside_render_pass;
        query_obj.subpass = query_count.subpass;
        cb_state->RecordBeginQuery(query_obj, record_obj.location);
    }

    if (!disabled[command_buffer_state]) {
        auto pool_state = Get<QueryPool>(queryPool);
        cb_state->AddChild(pool_state);
    }
}

void DeviceState::PostCallRecordCmdEndQueryIndexedEXT(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot,
                                                      uint32_t index, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    if (disabled[query_validation]) {
        return;
    }

    QueryCount query_count(*cb_state);

    for (uint32_t i = 0; i < query_count.count; ++i) {
        QueryObject query_obj = {queryPool, slot, 0, 0, true, index + i};
        query_obj.inside_render_pass = query_count.inside_render_pass;
        query_obj.subpass = query_count.subpass;
        query_obj.end_command_index = cb_state->command_count;  // counting this command
        cb_state->RecordEndQuery(query_obj, record_obj.location);
    }

    if (!disabled[command_buffer_state]) {
        auto pool_state = Get<QueryPool>(queryPool);
        cb_state->AddChild(pool_state);
    }
}

void DeviceState::PostCallRecordCreateSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
                                                             const VkAllocationCallbacks* pAllocator,
                                                             VkSamplerYcbcrConversion* pYcbcrConversion,
                                                             const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    VkFormatFeatureFlags2 format_features = 0;

    if (pCreateInfo->format != VK_FORMAT_UNDEFINED) {
        format_features = GetPotentialFormatFeatures(pCreateInfo->format);
    } else if (IsExtEnabled(extensions.vk_android_external_memory_android_hardware_buffer)) {
        // If format is VK_FORMAT_UNDEFINED, format_features will be set by external AHB features
        format_features = GetExternalFormatFeaturesANDROID(pCreateInfo->pNext);
    }

    Add(std::make_shared<SamplerYcbcrConversion>(*pYcbcrConversion, pCreateInfo, format_features));
}

void DeviceState::PostCallRecordCreateSamplerYcbcrConversionKHR(VkDevice device,
                                                                const VkSamplerYcbcrConversionCreateInfo* pCreateInfo,
                                                                const VkAllocationCallbacks* pAllocator,
                                                                VkSamplerYcbcrConversion* pYcbcrConversion,
                                                                const RecordObject& record_obj) {
    PostCallRecordCreateSamplerYcbcrConversion(device, pCreateInfo, pAllocator, pYcbcrConversion, record_obj);
}

void DeviceState::PreCallRecordDestroySamplerYcbcrConversion(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion,
                                                             const VkAllocationCallbacks* pAllocator,
                                                             const RecordObject& record_obj) {
    Destroy<SamplerYcbcrConversion>(ycbcrConversion);
}

void DeviceState::PreCallRecordDestroySamplerYcbcrConversionKHR(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion,
                                                                const VkAllocationCallbacks* pAllocator,
                                                                const RecordObject& record_obj) {
    PreCallRecordDestroySamplerYcbcrConversion(device, ycbcrConversion, pAllocator, record_obj);
}

void DeviceState::PostCallRecordResetQueryPoolEXT(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
                                                  const RecordObject& record_obj) {
    PostCallRecordResetQueryPool(device, queryPool, firstQuery, queryCount, record_obj);
}

void DeviceState::PostCallRecordResetQueryPool(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
                                               const RecordObject& record_obj) {
    // Do nothing if the feature is not enabled.
    if (!enabled_features.hostQueryReset) {
        return;
    } else if (disabled[query_validation]) {
        return;
    }

    // Do nothing if the query pool has been destroyed.
    auto query_pool_state = Get<QueryPool>(queryPool);
    ASSERT_AND_RETURN(query_pool_state);

    // Reset the state of existing entries.
    const uint32_t max_query_count = std::min(queryCount, query_pool_state->create_info.queryCount - firstQuery);
    for (uint32_t i = 0; i < max_query_count; ++i) {
        auto query_index = firstQuery + i;
        query_pool_state->SetQueryState(query_index, 0, QUERYSTATE_RESET);
        if (query_pool_state->create_info.queryType == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR) {
            for (uint32_t pass_index = 0; pass_index < query_pool_state->n_performance_passes; pass_index++) {
                query_pool_state->SetQueryState(query_index, pass_index, QUERYSTATE_RESET);
            }
        }
    }
}

void DeviceState::PerformUpdateDescriptorSetsWithTemplateKHR(VkDescriptorSet descriptorSet,
                                                             const DescriptorUpdateTemplate& template_state, const void* pData) {
    // Translate the templated update into a normal update for validation...
    DecodedTemplateUpdate decoded_template(*this, descriptorSet, template_state, pData);
    PerformUpdateDescriptorSets(static_cast<uint32_t>(decoded_template.desc_writes.size()), decoded_template.desc_writes.data(), 0,
                                NULL);
}

void DeviceState::PostCallRecordCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
                                        uint32_t firstVertex, uint32_t firstInstance, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
}

void DeviceState::PostCallRecordCmdDrawMultiEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
                                                const VkMultiDrawInfoEXT* pVertexInfo, uint32_t instanceCount,
                                                uint32_t firstInstance, uint32_t stride, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
}

void DeviceState::PostCallRecordCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount,
                                               uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance,
                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
}

void DeviceState::PostCallRecordCmdDrawMultiIndexedEXT(VkCommandBuffer commandBuffer, uint32_t drawCount,
                                                       const VkMultiDrawIndexedInfoEXT* pIndexInfo, uint32_t instanceCount,
                                                       uint32_t firstInstance, uint32_t stride, const int32_t* pVertexOffset,
                                                       const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
}

void DeviceState::PostCallRecordCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count,
                                                uint32_t stride, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto buffer_state = Get<Buffer>(buffer);
    cb_state->RecordDraw(record_obj.location);
    if (!disabled[command_buffer_state]) {
        cb_state->AddChild(buffer_state);
    }
}

void DeviceState::PostCallRecordCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                       uint32_t count, uint32_t stride, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    auto buffer_state = Get<Buffer>(buffer);
    cb_state->RecordDraw(record_obj.location);
    if (!disabled[command_buffer_state]) {
        cb_state->AddChild(buffer_state);
    }
}

void DeviceState::PostCallRecordCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z,
                                            const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDispatch(record_obj.location);
}

void DeviceState::PostCallRecordCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDispatch(record_obj.location);
    if (!disabled[command_buffer_state]) {
        auto buffer_state = Get<Buffer>(buffer);
        cb_state->AddChild(buffer_state);
    }
}

void DeviceState::PostCallRecordCmdDispatchBaseKHR(VkCommandBuffer commandBuffer, uint32_t base_x, uint32_t base_y, uint32_t base_z,
                                                   uint32_t x, uint32_t y, uint32_t z, const RecordObject& record_obj) {
    PostCallRecordCmdDispatchBase(commandBuffer, x, y, z, base_x, base_y, base_z, record_obj);
}

void DeviceState::PostCallRecordCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,
                                                uint32_t, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDispatch(record_obj.location);
}

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

void DeviceState::PostCallRecordCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                     VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                                     uint32_t stride, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    if (!disabled[command_buffer_state]) {
        auto buffer_state = Get<Buffer>(buffer);
        auto count_buffer_state = Get<Buffer>(countBuffer);
        cb_state->AddChild(buffer_state);
        cb_state->AddChild(count_buffer_state);
    }
}

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

void DeviceState::PostCallRecordCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                            VkBuffer countBuffer, VkDeviceSize countBufferOffset,
                                                            uint32_t maxDrawCount, uint32_t stride,
                                                            const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    if (!disabled[command_buffer_state]) {
        auto buffer_state = Get<Buffer>(buffer);
        auto count_buffer_state = Get<Buffer>(countBuffer);
        cb_state->AddChild(buffer_state);
        cb_state->AddChild(count_buffer_state);
    }
}

void DeviceState::PostCallRecordCmdDrawMeshTasksNV(VkCommandBuffer commandBuffer, uint32_t taskCount, uint32_t firstTask,
                                                   const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
}

void DeviceState::PostCallRecordCmdDrawMeshTasksIndirectNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                           uint32_t drawCount, uint32_t stride, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    auto buffer_state = Get<Buffer>(buffer);
    if (!disabled[command_buffer_state] && buffer_state) {
        cb_state->AddChild(buffer_state);
    }
}

void DeviceState::PostCallRecordCmdDrawMeshTasksIndirectCountNV(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                                VkBuffer countBuffer, VkDeviceSize countBufferOffset,
                                                                uint32_t maxDrawCount, uint32_t stride,
                                                                const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    if (!disabled[command_buffer_state]) {
        if (auto buffer_state = Get<Buffer>(buffer)) {
            cb_state->AddChild(buffer_state);
        }
        if (auto count_buffer_state = Get<Buffer>(countBuffer)) {
            cb_state->AddChild(count_buffer_state);
        }
    }
}

void DeviceState::PostCallRecordCmdDrawMeshTasksEXT(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY,
                                                    uint32_t groupCountZ, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
}

void DeviceState::PostCallRecordCmdDrawMeshTasksIndirectEXT(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
                                                            uint32_t drawCount, uint32_t stride, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    auto buffer_state = Get<Buffer>(buffer);
    if (!disabled[command_buffer_state] && buffer_state) {
        cb_state->AddChild(buffer_state);
    }
}

void DeviceState::PostCallRecordCmdDrawMeshTasksIndirectCountEXT(VkCommandBuffer commandBuffer, VkBuffer buffer,
                                                                 VkDeviceSize offset, VkBuffer countBuffer,
                                                                 VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
                                                                 uint32_t stride, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    if (!disabled[command_buffer_state]) {
        if (auto buffer_state = Get<Buffer>(buffer)) {
            cb_state->AddChild(buffer_state);
        }
        if (auto count_buffer_state = Get<Buffer>(countBuffer)) {
            cb_state->AddChild(count_buffer_state);
        }
    }
}

void DeviceState::PostCallRecordCmdDispatchIndirect2KHR(VkCommandBuffer commandBuffer, const VkDispatchIndirect2InfoKHR* pInfo,
                                                        const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDispatch(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pInfo->addressRange.address, pInfo->addressRange.size,
                            VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdDrawIndexedIndirect2KHR(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo,
                                                           const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pInfo->addressRange.address, pInfo->addressRange.size,
                            VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdDrawIndirect2KHR(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo,
                                                    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pInfo->addressRange.address, pInfo->addressRange.size,
                            VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdDrawIndirectCount2KHR(VkCommandBuffer commandBuffer, const VkDrawIndirectCount2InfoKHR* pInfo,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pInfo->addressRange.address, pInfo->addressRange.size,
                            VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdDrawIndexedIndirectCount2KHR(VkCommandBuffer commandBuffer,
                                                                const VkDrawIndirectCount2InfoKHR* pInfo,
                                                                const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pInfo->addressRange.address, pInfo->addressRange.size,
                            VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdDrawMeshTasksIndirect2EXT(VkCommandBuffer commandBuffer, const VkDrawIndirect2InfoKHR* pInfo,
                                                             const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pInfo->addressRange.address, pInfo->addressRange.size,
                            VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdDrawMeshTasksIndirectCount2EXT(VkCommandBuffer commandBuffer,
                                                                  const VkDrawIndirectCount2InfoKHR* pInfo,
                                                                  const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDraw(record_obj.location);
    TrackDeviceAddressRange(*cb_state, pInfo->addressRange.address, pInfo->addressRange.size,
                            VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdTraceRaysNV(VkCommandBuffer commandBuffer, VkBuffer raygenShaderBindingTableBuffer,
                                               VkDeviceSize raygenShaderBindingOffset, VkBuffer missShaderBindingTableBuffer,
                                               VkDeviceSize missShaderBindingOffset, VkDeviceSize missShaderBindingStride,
                                               VkBuffer hitShaderBindingTableBuffer, VkDeviceSize hitShaderBindingOffset,
                                               VkDeviceSize hitShaderBindingStride, VkBuffer callableShaderBindingTableBuffer,
                                               VkDeviceSize callableShaderBindingOffset, VkDeviceSize callableShaderBindingStride,
                                               uint32_t width, uint32_t height, uint32_t depth, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordTraceRay(record_obj.location.function);
}

void DeviceState::PostCallRecordCmdTraceRaysKHR(VkCommandBuffer commandBuffer,
                                                const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable,
                                                const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable,
                                                const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable,
                                                const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, uint32_t width,
                                                uint32_t height, uint32_t depth, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordTraceRay(record_obj.location.function);
    TrackDeviceAddressRange(*cb_state, pRaygenShaderBindingTable->deviceAddress, pRaygenShaderBindingTable->size,
                            VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR);
    TrackDeviceAddressRange(*cb_state, pMissShaderBindingTable->deviceAddress, pMissShaderBindingTable->size,
                            VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR);
    TrackDeviceAddressRange(*cb_state, pHitShaderBindingTable->deviceAddress, pHitShaderBindingTable->size,
                            VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR);
    TrackDeviceAddressRange(*cb_state, pCallableShaderBindingTable->deviceAddress, pCallableShaderBindingTable->size,
                            VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR);
}

void DeviceState::PostCallRecordCmdTraceRaysIndirectKHR(VkCommandBuffer commandBuffer,
                                                        const VkStridedDeviceAddressRegionKHR* pRaygenShaderBindingTable,
                                                        const VkStridedDeviceAddressRegionKHR* pMissShaderBindingTable,
                                                        const VkStridedDeviceAddressRegionKHR* pHitShaderBindingTable,
                                                        const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable,
                                                        VkDeviceAddress indirectDeviceAddress, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordTraceRay(record_obj.location.function);
    TrackDeviceAddressRange(*cb_state, pRaygenShaderBindingTable->deviceAddress, pRaygenShaderBindingTable->size,
                            VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR);
    TrackDeviceAddressRange(*cb_state, pMissShaderBindingTable->deviceAddress, pMissShaderBindingTable->size,
                            VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR);
    TrackDeviceAddressRange(*cb_state, pHitShaderBindingTable->deviceAddress, pHitShaderBindingTable->size,
                            VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR);
    TrackDeviceAddressRange(*cb_state, pCallableShaderBindingTable->deviceAddress, pCallableShaderBindingTable->size,
                            VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR);
}

void DeviceState::PostCallRecordCmdTraceRaysIndirect2KHR(VkCommandBuffer commandBuffer, VkDeviceAddress indirectDeviceAddress,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordTraceRay(record_obj.location.function);
}

void DeviceState::PostCallRecordCmdExecuteGeneratedCommandsEXT(VkCommandBuffer commandBuffer, VkBool32 isPreprocessed,
                                                               const VkGeneratedCommandsInfoEXT* pGeneratedCommandsInfo,
                                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordExecuteGeneratedCommands(*pGeneratedCommandsInfo, record_obj.location);

    // Spec says to check preprocessSize, not preprocessAddress
    if (pGeneratedCommandsInfo->preprocessSize != 0) {
        TrackDeviceAddressRange(*cb_state, pGeneratedCommandsInfo->preprocessAddress, pGeneratedCommandsInfo->preprocessSize,
                                VK_BUFFER_USAGE_2_PREPROCESS_BUFFER_BIT_EXT);
    }
    if (pGeneratedCommandsInfo->sequenceCountAddress != 0) {
        TrackDeviceAddressRange(*cb_state, pGeneratedCommandsInfo->sequenceCountAddress, sizeof(uint32_t),
                                VK_BUFFER_USAGE_2_INDIRECT_BUFFER_BIT_KHR);
    }
    // TODO - Track indirectAddress as well, need usage flag
    // https://gitlab.khronos.org/vulkan/vulkan/-/issues/4780
}

void DeviceState::PreCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo,
                                                  const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule,
                                                  const RecordObject& record_obj, chassis::CreateShaderModule& chassis_state) {
    if (pCreateInfo->codeSize == 0 || !pCreateInfo->pCode) {
        return;
    } else if (chassis_state.module_state) {
        // We store the shader module at a chassis stack level (because we need it for PostCallRecord in things like GPU-AV)
        // Only one validation object needs to create it
        return;
    }

    chassis_state.module_state =
        CreateSpirvModuleState(pCreateInfo->codeSize, pCreateInfo->pCode, global_settings, &chassis_state.stateless_data);
    if (chassis_state.module_state && chassis_state.stateless_data.has_group_decoration) {
        spv_target_env spirv_environment = PickSpirvEnv(api_version, IsExtEnabled(extensions.vk_khr_spirv_1_4));
        spvtools::Optimizer optimizer(spirv_environment);
        optimizer.RegisterPass(spvtools::CreateFlattenDecorationPass());
        std::vector<uint32_t> optimized_binary;
        // Run optimizer to flatten decorations only, set skip_validation so as to not re-run validator
        auto result = optimizer.Run(chassis_state.module_state->words_.data(), chassis_state.module_state->words_.size(),
                                    &optimized_binary, spvtools::ValidatorOptions(), true);

        if (result) {
            // Easier to just re-create the ShaderModule as StaticData uses itself when building itself up
            // It is really rare this will get here as Group Decorations have been deprecated and before this was added no one ever
            // raised an issue for a bug that would crash the layers that was around for many releases.
            //
            // We also ignore doing this for any newer way to provide SPIR-V (GPL, shaderObject, RTX, etc) for same reason.
            chassis_state.module_state = CreateSpirvModuleState(optimized_binary.size() * sizeof(uint32_t), optimized_binary.data(),
                                                                global_settings, &chassis_state.stateless_data);
        }
    }
}

void DeviceState::PreCallRecordCreateShadersEXT(VkDevice device, uint32_t createInfoCount,
                                                const VkShaderCreateInfoEXT* pCreateInfos, const VkAllocationCallbacks* pAllocator,
                                                VkShaderEXT* pShaders, const RecordObject& record_obj,
                                                chassis::ShaderObject& chassis_state) {
    for (uint32_t i = 0; i < createInfoCount; ++i) {
        const VkShaderCreateInfoEXT& create_info = pCreateInfos[i];
        if (create_info.codeSize == 0 || !create_info.pCode || create_info.codeType != VK_SHADER_CODE_TYPE_SPIRV_EXT) {
            continue;
        }
        chassis_state.module_states[i] =
            CreateSpirvModuleState(create_info.codeSize, static_cast<const uint32_t*>(create_info.pCode), global_settings,
                                   &chassis_state.stateless_data[i]);
    }
}

void DeviceState::PostCallRecordCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo,
                                                   const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule,
                                                   const RecordObject& record_obj, chassis::CreateShaderModule& chassis_state) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<ShaderModule>(*pShaderModule, chassis_state.module_state));
}

void DeviceState::PostCallRecordCreateShadersEXT(VkDevice device, uint32_t createInfoCount,
                                                 const VkShaderCreateInfoEXT* pCreateInfos, const VkAllocationCallbacks* pAllocator,
                                                 VkShaderEXT* pShaders, const RecordObject& record_obj,
                                                 chassis::ShaderObject& chassis_state) {
    for (uint32_t i = 0; i < createInfoCount; ++i) {
        // If there are multiple shaders being created, and one is bad, will return a non VK_SUCCESS but we need to check if the
        // VkShaderEXT was null or not to actually know if it was created
        const VkShaderEXT shader_handle = pShaders[i];
        if (shader_handle == VK_NULL_HANDLE) {
            continue;
        }
        std::shared_ptr<ShaderObject> shader_object_state =
            std::make_shared<ShaderObject>(*this, pCreateInfos[i], shader_handle, chassis_state.module_states[i]);

        for (uint32_t j = 0; j < createInfoCount; ++j) {
            if (i != j && pShaders[j] != VK_NULL_HANDLE && (pCreateInfos[j].flags & VK_SHADER_CREATE_LINK_STAGE_BIT_EXT) != 0) {
                shader_object_state->linked_shaders.push_back(pShaders[j]);
            }
        }

        if (shader_object_state->descriptor_heap_embedded_samplers_count > 0) {
            descriptor_heap_global_embedded_sampler_count_ += shader_object_state->descriptor_heap_embedded_samplers_count;
        }

        Add(std::move(shader_object_state));
    }
}

void DeviceState::PostCallRecordCopyAccelerationStructureKHR(VkDevice device, VkDeferredOperationKHR deferredOperation,
                                                             const VkCopyAccelerationStructureInfoKHR* pInfo,
                                                             const RecordObject& record_obj) {
    // Might be deferred
    if (record_obj.result < VK_SUCCESS) {
        return;
    }
    auto src_as_state = Get<AccelerationStructureKHR>(pInfo->src);
    auto dst_as_state = Get<AccelerationStructureKHR>(pInfo->dst);
    if (dst_as_state && src_as_state) {
        dst_as_state->SetBuildInfo(src_as_state->GetBuildInfo());
    }
}

void DeviceState::PostCallRecordCmdCopyAccelerationStructureKHR(VkCommandBuffer commandBuffer,
                                                                const VkCopyAccelerationStructureInfoKHR* pInfo,
                                                                const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);

    cb_state->RecordCommand(record_obj.location);
    auto src_as_state = Get<AccelerationStructureKHR>(pInfo->src);
    auto dst_as_state = Get<AccelerationStructureKHR>(pInfo->dst);
    if (dst_as_state && src_as_state) {
        dst_as_state->SetBuildInfo(src_as_state->GetBuildInfo());
        if (!disabled[command_buffer_state]) {
            cb_state->AddChild(dst_as_state);
            cb_state->AddChild(src_as_state);
        }
    }
}

void DeviceState::PostCallRecordCmdCopyAccelerationStructureToMemoryKHR(VkCommandBuffer commandBuffer,
                                                                        const VkCopyAccelerationStructureToMemoryInfoKHR* pInfo,
                                                                        const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    auto src_as_state = Get<AccelerationStructureKHR>(pInfo->src);
    if (!disabled[command_buffer_state]) {
        cb_state->AddChild(src_as_state);
    }
    // Issue https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/6461
    // showed that it is incorrect to try to add buffers obtained through a call to GetBuffersByAddress as children to a command
    // buffer
}

void DeviceState::PostCallRecordCmdCopyMemoryToAccelerationStructureKHR(VkCommandBuffer commandBuffer,
                                                                        const VkCopyMemoryToAccelerationStructureInfoKHR* pInfo,
                                                                        const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    if (!disabled[command_buffer_state]) {
        auto dst_as_state = Get<AccelerationStructureKHR>(pInfo->dst);
        ASSERT_AND_RETURN(dst_as_state);
        cb_state->AddChild(dst_as_state);

        // Issue https://github.com/KhronosGroup/Vulkan-ValidationLayers/issues/6461
        // showed that it is incorrect to try to add buffers obtained through a call to GetBuffersByAddress as children to a
        // command buffer
    }
}

void DeviceState::PostCallRecordCmdCopyMemoryIndirectKHR(VkCommandBuffer commandBuffer,
                                                         const VkCopyMemoryIndirectInfoKHR* pCopyMemoryIndirectInfo,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCopyMemoryIndirect(*pCopyMemoryIndirectInfo, record_obj.location);
    TrackDeviceAddressRange(*cb_state, pCopyMemoryIndirectInfo->copyAddressRange.address,
                            pCopyMemoryIndirectInfo->copyAddressRange.size, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdCopyMemoryToImageIndirectKHR(
    VkCommandBuffer commandBuffer, const VkCopyMemoryToImageIndirectInfoKHR* pCopyMemoryToImageIndirectInfo,
    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCopyMemoryToImageIndirect(*pCopyMemoryToImageIndirectInfo, record_obj.location);
    TrackDeviceAddressRange(*cb_state, pCopyMemoryToImageIndirectInfo->copyAddressRange.address,
                            pCopyMemoryToImageIndirectInfo->copyAddressRange.size, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
}

void DeviceState::PostCallRecordCmdSetCullModeEXT(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode,
                                                  const RecordObject& record_obj) {
    PostCallRecordCmdSetCullMode(commandBuffer, cullMode, record_obj);
}

void DeviceState::PostCallRecordCmdSetCullMode(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode,
                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_CULL_MODE);
    cb_state->dynamic_state_value.cull_mode = cullMode;
}

void DeviceState::PostCallRecordCmdSetFrontFaceEXT(VkCommandBuffer commandBuffer, VkFrontFace frontFace,
                                                   const RecordObject& record_obj) {
    PostCallRecordCmdSetFrontFace(commandBuffer, frontFace, record_obj);
}

void DeviceState::PostCallRecordCmdSetFrontFace(VkCommandBuffer commandBuffer, VkFrontFace frontFace,
                                                const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_FRONT_FACE);
}

void DeviceState::PostCallRecordCmdSetPrimitiveTopologyEXT(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology,
                                                           const RecordObject& record_obj) {
    PostCallRecordCmdSetPrimitiveTopology(commandBuffer, primitiveTopology, record_obj);
}

void DeviceState::PostCallRecordCmdSetPrimitiveTopology(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology,
                                                        const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY);
    cb_state->dynamic_state_value.primitive_topology = primitiveTopology;
}

void DeviceState::PostCallRecordCmdSetViewportWithCountEXT(VkCommandBuffer commandBuffer, uint32_t viewportCount,
                                                           const VkViewport* pViewports, const RecordObject& record_obj) {
    PostCallRecordCmdSetViewportWithCount(commandBuffer, viewportCount, pViewports, record_obj);
}

void DeviceState::PostCallRecordCmdSetViewportWithCount(VkCommandBuffer commandBuffer, uint32_t viewportCount,
                                                        const VkViewport* pViewports, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetViewportWithCount(viewportCount, pViewports);
}

void DeviceState::PostCallRecordCmdSetScissorWithCountEXT(VkCommandBuffer commandBuffer, uint32_t scissorCount,
                                                          const VkRect2D* pScissors, const RecordObject& record_obj) {
    PostCallRecordCmdSetScissorWithCount(commandBuffer, scissorCount, pScissors, record_obj);
}

void DeviceState::PostCallRecordCmdSetScissorWithCount(VkCommandBuffer commandBuffer, uint32_t scissorCount,
                                                       const VkRect2D* pScissors, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetScissorWithCount(scissorCount);
}

void DeviceState::PostCallRecordCmdBindVertexBuffers2EXT(VkCommandBuffer commandBuffer, uint32_t firstBinding,
                                                         uint32_t bindingCount, const VkBuffer* pBuffers,
                                                         const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes,
                                                         const VkDeviceSize* pStrides, const RecordObject& record_obj) {
    PostCallRecordCmdBindVertexBuffers2(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets, pSizes, pStrides,
                                        record_obj);
}

void DeviceState::PostCallRecordCmdBindVertexBuffers2(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount,
                                                      const VkBuffer* pBuffers, const VkDeviceSize* pOffsets,
                                                      const VkDeviceSize* pSizes, const VkDeviceSize* pStrides,
                                                      const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    if (pStrides) {
        cb_state->RecordStateCmd(CB_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE);
        cb_state->stride_set_with_bind_vertex_buffer_3 = false;
    }
    cb_state->bind_vertex_buffer_3_used = false;

    for (uint32_t i = 0; i < bindingCount; ++i) {
        auto buffer_state = Get<vvl::Buffer>(pBuffers[i]);

        const VkDeviceSize* stride_ptr = pStrides ? &pStrides[i] : nullptr;
        const VkDeviceSize effective_size = GetBufferRegionSize(buffer_state, pOffsets[i], pSizes ? pSizes[i] : VK_WHOLE_SIZE);

        cb_state->current_vertex_buffer_binding_info[i + firstBinding].Set(pBuffers[i], effective_size, pOffsets[i], stride_ptr);

        // Add binding for this vertex buffer to this commandbuffer
        if (!disabled[command_buffer_state] && pBuffers[i]) {
            cb_state->AddChild(buffer_state);
        }
    }
}

void DeviceState::PostCallRecordCmdBindVertexBuffers3KHR(VkCommandBuffer commandBuffer, uint32_t firstBinding,
                                                         uint32_t bindingCount, const VkBindVertexBuffer3InfoKHR* pBindingInfos,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->bind_vertex_buffer_3_used = true;

    for (uint32_t i = 0; i < bindingCount; ++i) {
        const VkBindVertexBuffer3InfoKHR& binding_info = pBindingInfos[i];

        const VkDeviceSize* stride_ptr = binding_info.setStride ? &binding_info.addressRange.stride : nullptr;
        cb_state->current_vertex_buffer_binding_info[i + firstBinding].Set(binding_info.addressRange.address,
                                                                           binding_info.addressRange.size, stride_ptr);

        TrackDeviceAddressRange(*cb_state, binding_info.addressRange.address, binding_info.addressRange.size,
                                VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);

        // https://gitlab.khronos.org/vulkan/vulkan/-/issues/3381
        // The stride is "last to set it wins"
        if (binding_info.setStride) {
            cb_state->stride_set_with_bind_vertex_buffer_3 = true;
        }
    }
    if (cb_state->stride_set_with_bind_vertex_buffer_3) {
        cb_state->RecordStateCmd(CB_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE);
    }
}

void DeviceState::PostCallRecordCmdSetDepthTestEnableEXT(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable,
                                                         const RecordObject& record_obj) {
    PostCallRecordCmdSetDepthTestEnable(commandBuffer, depthTestEnable, record_obj);
}

void DeviceState::PostCallRecordCmdSetDepthTestEnable(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable,
                                                      const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetDepthTestEnable(depthTestEnable);
}

void DeviceState::PostCallRecordCmdSetDepthWriteEnableEXT(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable,
                                                          const RecordObject& record_obj) {
    PostCallRecordCmdSetDepthWriteEnable(commandBuffer, depthWriteEnable, record_obj);
}

void DeviceState::PostCallRecordCmdSetDepthWriteEnable(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable,
                                                       const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DEPTH_WRITE_ENABLE);
    cb_state->dynamic_state_value.depth_write_enable = depthWriteEnable;
}

void DeviceState::PostCallRecordCmdSetDepthCompareOpEXT(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp,
                                                        const RecordObject& record_obj) {
    PostCallRecordCmdSetDepthCompareOp(commandBuffer, depthCompareOp, record_obj);
}

void DeviceState::PostCallRecordCmdSetDepthCompareOp(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp,
                                                     const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetDepthCompareOp(depthCompareOp);
}

void DeviceState::PostCallRecordCmdSetDepthBoundsTestEnableEXT(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable,
                                                               const RecordObject& record_obj) {
    PostCallRecordCmdSetDepthBoundsTestEnable(commandBuffer, depthBoundsTestEnable, record_obj);
}

void DeviceState::PostCallRecordCmdSetDepthBoundsTestEnable(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable,
                                                            const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE);
    cb_state->dynamic_state_value.depth_bounds_test_enable = depthBoundsTestEnable;
}

void DeviceState::PostCallRecordCmdSetStencilTestEnableEXT(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable,
                                                           const RecordObject& record_obj) {
    PostCallRecordCmdSetStencilTestEnable(commandBuffer, stencilTestEnable, record_obj);
}

void DeviceState::PostCallRecordCmdSetStencilTestEnable(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable,
                                                        const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_STENCIL_TEST_ENABLE);
    cb_state->dynamic_state_value.stencil_test_enable = stencilTestEnable;
}

void DeviceState::PostCallRecordCmdSetStencilOpEXT(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp,
                                                   VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp,
                                                   const RecordObject& record_obj) {
    PostCallRecordCmdSetStencilOp(commandBuffer, faceMask, failOp, passOp, depthFailOp, compareOp, record_obj);
}

void DeviceState::PostCallRecordCmdSetStencilOp(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp,
                                                VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp,
                                                const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_STENCIL_OP);
    if (faceMask == VK_STENCIL_FACE_FRONT_BIT || faceMask == VK_STENCIL_FACE_FRONT_AND_BACK) {
        cb_state->dynamic_state_value.fail_op_front = failOp;
        cb_state->dynamic_state_value.pass_op_front = passOp;
        cb_state->dynamic_state_value.depth_fail_op_front = depthFailOp;
    }
    if (faceMask == VK_STENCIL_FACE_BACK_BIT || faceMask == VK_STENCIL_FACE_FRONT_AND_BACK) {
        cb_state->dynamic_state_value.fail_op_back = failOp;
        cb_state->dynamic_state_value.pass_op_back = passOp;
        cb_state->dynamic_state_value.depth_fail_op_back = depthFailOp;
    }
}

void DeviceState::PostCallRecordCmdSetDiscardRectangleEXT(VkCommandBuffer commandBuffer, uint32_t firstDiscardRectangle,
                                                          uint32_t discardRectangleCount, const VkRect2D* pDiscardRectangles,
                                                          const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT);
    for (uint32_t i = 0; i < discardRectangleCount; i++) {
        cb_state->dynamic_state_value.discard_rectangles.set(firstDiscardRectangle + i);
    }
}

void DeviceState::PostCallRecordCmdSetDiscardRectangleEnableEXT(VkCommandBuffer commandBuffer, VkBool32 discardRectangleEnable,
                                                                const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT);
    cb_state->dynamic_state_value.discard_rectangle_enable = discardRectangleEnable;
}

void DeviceState::PostCallRecordCmdSetDiscardRectangleModeEXT(VkCommandBuffer commandBuffer,
                                                              VkDiscardRectangleModeEXT discardRectangleMode,
                                                              const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DISCARD_RECTANGLE_MODE_EXT);
}

void DeviceState::PostCallRecordCmdSetSampleLocationsEXT(VkCommandBuffer commandBuffer,
                                                         const VkSampleLocationsInfoEXT* pSampleLocationsInfo,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT);
    cb_state->dynamic_state_value.sample_locations_info = *pSampleLocationsInfo;
}

void DeviceState::PostCallRecordCmdSetCoarseSampleOrderNV(VkCommandBuffer commandBuffer, VkCoarseSampleOrderTypeNV sampleOrderType,
                                                          uint32_t customSampleOrderCount,
                                                          const VkCoarseSampleOrderCustomNV* pCustomSampleOrders,
                                                          const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV);
}

void DeviceState::PostCallRecordCmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer, uint32_t patchControlPoints,
                                                            const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT);
}

void DeviceState::PostCallRecordCmdSetLogicOpEXT(VkCommandBuffer commandBuffer, VkLogicOp logicOp, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_LOGIC_OP_EXT);
}

void DeviceState::PostCallRecordCmdSetRasterizerDiscardEnableEXT(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable,
                                                                 const RecordObject& record_obj) {
    PostCallRecordCmdSetRasterizerDiscardEnable(commandBuffer, rasterizerDiscardEnable, record_obj);
}

void DeviceState::PostCallRecordCmdSetRasterizerDiscardEnable(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable,
                                                              const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE);
    cb_state->dynamic_state_value.rasterizer_discard_enable = (rasterizerDiscardEnable == VK_TRUE);
}

void DeviceState::PostCallRecordCmdSetDepthBiasEnableEXT(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable,
                                                         const RecordObject& record_obj) {
    PostCallRecordCmdSetDepthBiasEnable(commandBuffer, depthBiasEnable, record_obj);
}

void DeviceState::PostCallRecordCmdSetDepthBiasEnable(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable,
                                                      const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DEPTH_BIAS_ENABLE);
    cb_state->dynamic_state_value.depth_bias_enable = depthBiasEnable;
}

void DeviceState::PostCallRecordCmdSetPrimitiveRestartEnableEXT(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable,
                                                                const RecordObject& record_obj) {
    PostCallRecordCmdSetPrimitiveRestartEnable(commandBuffer, primitiveRestartEnable, record_obj);
}

void DeviceState::PostCallRecordCmdSetPrimitiveRestartEnable(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable,
                                                             const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE);
    cb_state->dynamic_state_value.primitive_restart_enable = primitiveRestartEnable;
}

void DeviceState::PostCallRecordCmdSetFragmentShadingRateKHR(VkCommandBuffer commandBuffer, const VkExtent2D* pFragmentSize,
                                                             const VkFragmentShadingRateCombinerOpKHR combinerOps[2],
                                                             const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR);
    cb_state->dynamic_state_value.fragment_size = *pFragmentSize;
}

void DeviceState::PostCallRecordCmdSetRenderingAttachmentLocations(VkCommandBuffer commandBuffer,
                                                                   const VkRenderingAttachmentLocationInfo* pLocationInfo,
                                                                   const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetRenderingAttachmentLocations(pLocationInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdSetRenderingAttachmentLocationsKHR(VkCommandBuffer commandBuffer,
                                                                      const VkRenderingAttachmentLocationInfoKHR* pLocationInfo,
                                                                      const RecordObject& record_obj) {
    PostCallRecordCmdSetRenderingAttachmentLocations(commandBuffer, pLocationInfo, record_obj);
}

void DeviceState::PostCallRecordCmdSetRenderingInputAttachmentIndices(VkCommandBuffer commandBuffer,
                                                                      const VkRenderingInputAttachmentIndexInfo* pLocationInfo,
                                                                      const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetRenderingInputAttachmentIndices(pLocationInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdSetRenderingInputAttachmentIndicesKHR(
    VkCommandBuffer commandBuffer, const VkRenderingInputAttachmentIndexInfoKHR* pLocationInfo, const RecordObject& record_obj) {
    PostCallRecordCmdSetRenderingInputAttachmentIndices(commandBuffer, pLocationInfo, record_obj);
}

void DeviceState::PostCallRecordCmdSetRayTracingPipelineStackSizeKHR(VkCommandBuffer commandBuffer, uint32_t pipelineStackSize,
                                                                     const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCommand(record_obj.location);
    // CB_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR);
    cb_state->dynamic_state_status.rtx_stack_size_cb = true;
    cb_state->dynamic_state_status.rtx_stack_size_pipeline = true;
}

void DeviceState::PostCallRecordCmdSetVertexInputEXT(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount,
                                                     const VkVertexInputBindingDescription2EXT* pVertexBindingDescriptions,
                                                     uint32_t vertexAttributeDescriptionCount,
                                                     const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions,
                                                     const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_VERTEX_INPUT_EXT);
    cb_state->stride_set_with_bind_vertex_buffer_3 = false;

    const auto pipeline_state = cb_state->GetLastBoundGraphics().pipeline_state;
    if (pipeline_state && pipeline_state->IsDynamic(CB_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE)) {
        cb_state->RecordDynamicState(CB_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE);
    }
    auto& vertex_bindings = cb_state->dynamic_state_value.vertex_bindings;

    // When using Dynamic state, anything not set is invalid, so need to reset map
    // "The vertex attribute description for any location not specified in the pVertexAttributeDescriptions array becomes undefined"
    vertex_bindings.clear();

    for (const auto [i, description] : vvl::enumerate(pVertexBindingDescriptions, vertexBindingDescriptionCount)) {
        vertex_bindings.insert_or_assign(description.binding, VertexBindingState(i, &description));

        cb_state->current_vertex_buffer_binding_info[description.binding].stride = description.stride;
    }

    for (const auto [i, description] : vvl::enumerate(pVertexAttributeDescriptions, vertexAttributeDescriptionCount)) {
        if (auto* binding_state = vvl::Find(vertex_bindings, description.binding)) {
            binding_state->locations.insert_or_assign(description.location, VertexAttrState(i, &description));
        }
    }
}

void DeviceState::PostCallRecordCmdSetColorWriteEnableEXT(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
                                                          const VkBool32* pColorWriteEnables, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT);
    cb_state->dynamic_state_value.color_write_enable_attachment_count = attachmentCount;
    for (uint32_t i = 0; i < attachmentCount; ++i) {
        if (pColorWriteEnables[i]) {
            cb_state->dynamic_state_value.color_write_enabled.set(i);
        } else {
            cb_state->dynamic_state_value.color_write_enabled.reset(i);
        }
    }
}

void DeviceState::PostCallRecordCmdSetAttachmentFeedbackLoopEnableEXT(VkCommandBuffer commandBuffer, VkImageAspectFlags aspectMask,
                                                                      const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT);
    cb_state->dynamic_state_value.attachment_feedback_loop_enable = aspectMask;
}

void DeviceState::PostCallRecordCmdSetTessellationDomainOriginEXT(VkCommandBuffer commandBuffer,
                                                                  VkTessellationDomainOrigin domainOrigin,
                                                                  const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_TESSELLATION_DOMAIN_ORIGIN_EXT);
}

void DeviceState::PostCallRecordCmdSetDepthClampEnableEXT(VkCommandBuffer commandBuffer, VkBool32 depthClampEnable,
                                                          const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT);
    cb_state->dynamic_state_value.depth_clamp_enable = depthClampEnable;
}

void DeviceState::PostCallRecordCmdSetDepthClampRangeEXT(VkCommandBuffer commandBuffer, VkDepthClampModeEXT depthClampMode,
                                                         const VkDepthClampRangeEXT* pDepthClampRange,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DEPTH_CLAMP_RANGE_EXT);
}

void DeviceState::PostCallRecordCmdSetPolygonModeEXT(VkCommandBuffer commandBuffer, VkPolygonMode polygonMode,
                                                     const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_POLYGON_MODE_EXT);
    cb_state->dynamic_state_value.polygon_mode = polygonMode;
}

void DeviceState::PostCallRecordCmdSetRasterizationSamplesEXT(VkCommandBuffer commandBuffer,
                                                              VkSampleCountFlagBits rasterizationSamples,
                                                              const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT);
    cb_state->dynamic_state_value.rasterization_samples = rasterizationSamples;
}

void DeviceState::PostCallRecordCmdSetSampleMaskEXT(VkCommandBuffer commandBuffer, VkSampleCountFlagBits samples,
                                                    const VkSampleMask* pSampleMask, const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_SAMPLE_MASK_EXT);
    cb_state->dynamic_state_value.samples_mask_samples = samples;
    // Note from the spec, if the need to record pSampleMask rises:
    // If the maintenance10 feature is enabled, and this (pSampleMask) parameter is set to NULL,
    // it is treated as if the mask has all bits set to 1.
}

void DeviceState::PostCallRecordCmdSetAlphaToCoverageEnableEXT(VkCommandBuffer commandBuffer, VkBool32 alphaToCoverageEnable,
                                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT);
    cb_state->dynamic_state_value.alpha_to_coverage_enable = alphaToCoverageEnable;
}

void DeviceState::PostCallRecordCmdSetAlphaToOneEnableEXT(VkCommandBuffer commandBuffer, VkBool32 alphaToOneEnable,
                                                          const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT);
    cb_state->dynamic_state_value.alpha_to_one_enable = alphaToOneEnable;
}

void DeviceState::PostCallRecordCmdSetLogicOpEnableEXT(VkCommandBuffer commandBuffer, VkBool32 logicOpEnable,
                                                       const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT);
    cb_state->dynamic_state_value.logic_op_enable = logicOpEnable;
}

void DeviceState::PostCallRecordCmdSetColorBlendEnableEXT(VkCommandBuffer commandBuffer, uint32_t firstAttachment,
                                                          uint32_t attachmentCount, const VkBool32* pColorBlendEnables,
                                                          const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT);
    for (uint32_t i = 0; i < attachmentCount; i++) {
        cb_state->dynamic_state_value.color_blend_enable_attachments.set(firstAttachment + i);
        if (pColorBlendEnables[i]) {
            cb_state->dynamic_state_value.color_blend_enabled.set(firstAttachment + i);
        } else {
            cb_state->dynamic_state_value.color_blend_enabled.reset(firstAttachment + i);
        }
    }
}

void DeviceState::PostCallRecordCmdSetColorBlendEquationEXT(VkCommandBuffer commandBuffer, uint32_t firstAttachment,
                                                            uint32_t attachmentCount,
                                                            const VkColorBlendEquationEXT* pColorBlendEquations,
                                                            const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT);
    if (cb_state->dynamic_state_value.color_blend_equations.size() < firstAttachment + attachmentCount) {
        cb_state->dynamic_state_value.color_blend_equations.resize(firstAttachment + attachmentCount);
    }
    for (uint32_t i = 0; i < attachmentCount; i++) {
        cb_state->dynamic_state_value.color_blend_equation_attachments.set(firstAttachment + i);
        cb_state->dynamic_state_value.color_blend_equations[firstAttachment + i] = pColorBlendEquations[i];
    }
}

void DeviceState::PostCallRecordCmdSetColorWriteMaskEXT(VkCommandBuffer commandBuffer, uint32_t firstAttachment,
                                                        uint32_t attachmentCount, const VkColorComponentFlags* pColorWriteMasks,
                                                        const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT);
    if (cb_state->dynamic_state_value.color_write_masks.size() < firstAttachment + attachmentCount) {
        cb_state->dynamic_state_value.color_write_masks.resize(firstAttachment + attachmentCount);
    }
    for (uint32_t i = 0; i < attachmentCount; i++) {
        cb_state->dynamic_state_value.color_write_mask_attachments.set(firstAttachment + i);
        cb_state->dynamic_state_value.color_write_masks[i] = pColorWriteMasks[i];
    }
}

void DeviceState::PostCallRecordCmdSetRasterizationStreamEXT(VkCommandBuffer commandBuffer, uint32_t rasterizationStream,
                                                             const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT);
    cb_state->dynamic_state_value.rasterization_stream = rasterizationStream;
}

void DeviceState::PostCallRecordCmdSetConservativeRasterizationModeEXT(
    VkCommandBuffer commandBuffer, VkConservativeRasterizationModeEXT conservativeRasterizationMode,
    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT);
    cb_state->dynamic_state_value.conservative_rasterization_mode = conservativeRasterizationMode;
}

void DeviceState::PostCallRecordCmdSetExtraPrimitiveOverestimationSizeEXT(VkCommandBuffer commandBuffer,
                                                                          float extraPrimitiveOverestimationSize,
                                                                          const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT);
}

void DeviceState::PostCallRecordCmdSetDepthClipEnableEXT(VkCommandBuffer commandBuffer, VkBool32 depthClipEnable,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DEPTH_CLIP_ENABLE_EXT);
}

void DeviceState::PostCallRecordCmdSetSampleLocationsEnableEXT(VkCommandBuffer commandBuffer, VkBool32 sampleLocationsEnable,
                                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT);
    cb_state->dynamic_state_value.sample_locations_enable = sampleLocationsEnable;
}

void DeviceState::PostCallRecordCmdSetColorBlendAdvancedEXT(VkCommandBuffer commandBuffer, uint32_t firstAttachment,
                                                            uint32_t attachmentCount,
                                                            const VkColorBlendAdvancedEXT* pColorBlendAdvanced,
                                                            const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT);
    for (uint32_t i = 0; i < attachmentCount; i++) {
        cb_state->dynamic_state_value.color_blend_advanced_attachments.set(firstAttachment + i);
    }
}

void DeviceState::PostCallRecordCmdSetProvokingVertexModeEXT(VkCommandBuffer commandBuffer,
                                                             VkProvokingVertexModeEXT provokingVertexMode,
                                                             const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_PROVOKING_VERTEX_MODE_EXT);
}

void DeviceState::PostCallRecordCmdSetLineRasterizationModeEXT(VkCommandBuffer commandBuffer,
                                                               VkLineRasterizationModeEXT lineRasterizationMode,
                                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT);
    cb_state->dynamic_state_value.line_rasterization_mode = lineRasterizationMode;
}

void DeviceState::PostCallRecordCmdSetLineStippleEnableEXT(VkCommandBuffer commandBuffer, VkBool32 stippledLineEnable,
                                                           const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT);
    cb_state->dynamic_state_value.stippled_line_enable = stippledLineEnable;
}

void DeviceState::PostCallRecordCmdSetDepthClipNegativeOneToOneEXT(VkCommandBuffer commandBuffer, VkBool32 negativeOneToOne,
                                                                   const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_DEPTH_CLIP_NEGATIVE_ONE_TO_ONE_EXT);
}

void DeviceState::PostCallRecordCmdSetViewportWScalingEnableNV(VkCommandBuffer commandBuffer, VkBool32 viewportWScalingEnable,
                                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE_NV);
    cb_state->dynamic_state_value.viewport_w_scaling_enable = viewportWScalingEnable;
}

void DeviceState::PostCallRecordCmdSetViewportSwizzleNV(VkCommandBuffer commandBuffer, uint32_t firstViewport,
                                                        uint32_t viewportCount, const VkViewportSwizzleNV* pViewportSwizzles,
                                                        const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV);
    cb_state->dynamic_state_value.viewport_swizzle_count = viewportCount;
}

void DeviceState::PostCallRecordCmdSetCoverageToColorEnableNV(VkCommandBuffer commandBuffer, VkBool32 coverageToColorEnable,
                                                              const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV);
    cb_state->dynamic_state_value.coverage_to_color_enable = coverageToColorEnable;
}

void DeviceState::PostCallRecordCmdSetCoverageToColorLocationNV(VkCommandBuffer commandBuffer, uint32_t coverageToColorLocation,
                                                                const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV);
    cb_state->dynamic_state_value.coverage_to_color_location = coverageToColorLocation;
}

void DeviceState::PostCallRecordCmdSetCoverageModulationModeNV(VkCommandBuffer commandBuffer,
                                                               VkCoverageModulationModeNV coverageModulationMode,
                                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV);
    cb_state->dynamic_state_value.coverage_modulation_mode = coverageModulationMode;
}

void DeviceState::PostCallRecordCmdSetCoverageModulationTableEnableNV(VkCommandBuffer commandBuffer,
                                                                      VkBool32 coverageModulationTableEnable,
                                                                      const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV);
    cb_state->dynamic_state_value.coverage_modulation_table_enable = coverageModulationTableEnable;
}

void DeviceState::PostCallRecordCmdSetCoverageModulationTableNV(VkCommandBuffer commandBuffer,
                                                                uint32_t coverageModulationTableCount,
                                                                const float* pCoverageModulationTable,
                                                                const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_NV);
}

void DeviceState::PostCallRecordCmdSetShadingRateImageEnableNV(VkCommandBuffer commandBuffer, VkBool32 shadingRateImageEnable,
                                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV);
    cb_state->dynamic_state_value.shading_rate_image_enable = shadingRateImageEnable;
}

void DeviceState::PostCallRecordCmdSetRepresentativeFragmentTestEnableNV(VkCommandBuffer commandBuffer,
                                                                         VkBool32 representativeFragmentTestEnable,
                                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_REPRESENTATIVE_FRAGMENT_TEST_ENABLE_NV);
}

void DeviceState::PostCallRecordCmdSetCoverageReductionModeNV(VkCommandBuffer commandBuffer,
                                                              VkCoverageReductionModeNV coverageReductionMode,
                                                              const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordStateCmd(CB_DYNAMIC_STATE_COVERAGE_REDUCTION_MODE_NV);
}

void DeviceState::PostCallRecordCmdControlVideoCodingKHR(VkCommandBuffer commandBuffer,
                                                         const VkVideoCodingControlInfoKHR* pCodingControlInfo,
                                                         const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordControlVideoCoding(*pCodingControlInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdDecodeVideoKHR(VkCommandBuffer commandBuffer, const VkVideoDecodeInfoKHR* pDecodeInfo,
                                                  const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordDecodeVideo(*pDecodeInfo, record_obj.location);
}

void DeviceState::PostCallRecordCmdEncodeVideoKHR(VkCommandBuffer commandBuffer, const VkVideoEncodeInfoKHR* pEncodeInfo,
                                                  const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordEncodeVideo(*pEncodeInfo, record_obj.location);
}

void DeviceState::PostCallRecordGetShaderModuleIdentifierEXT(VkDevice, const VkShaderModule shaderModule,
                                                             VkShaderModuleIdentifierEXT* pIdentifier,
                                                             const RecordObject& record_obj) {
    if (const auto shader_state = Get<ShaderModule>(shaderModule); shader_state) {
        WriteLockGuard guard(shader_identifier_map_lock_);
        shader_identifier_map_.emplace(*pIdentifier, std::move(shader_state));
    }
}

void DeviceState::PostCallRecordGetShaderModuleCreateInfoIdentifierEXT(VkDevice, const VkShaderModuleCreateInfo* pCreateInfo,
                                                                       VkShaderModuleIdentifierEXT* pIdentifier,
                                                                       const RecordObject& record_obj) {
    WriteLockGuard guard(shader_identifier_map_lock_);
    shader_identifier_map_.emplace(*pIdentifier, std::make_shared<ShaderModule>());
}

void DeviceState::PostCallRecordGetBufferDeviceAddress(VkDevice device, const VkBufferDeviceAddressInfo* pInfo,
                                                       const RecordObject& record_obj) {
    if (record_obj.device_address == 0) {
        return;
    }
    if (auto buffer_state = Get<Buffer>(pInfo->buffer)) {
        WriteLockGuard guard(buffer_address_lock_);
        // address is used for GPU-AV and ray tracing buffer validation
        buffer_state->deviceAddress = record_obj.device_address;
        const vvl::range<VkDeviceAddress> address_range = buffer_state->DeviceAddressRange();

        BufferAddressInfillUpdateOps ops{{buffer_state.get()}};
        sparse_container::infill_update_range(buffer_address_map_, address_range, ops);
        buffer_device_address_ranges_version++;
    }
}

void DeviceState::PostCallRecordGetBufferDeviceAddressKHR(VkDevice device, const VkBufferDeviceAddressInfo* pInfo,
                                                          const RecordObject& record_obj) {
    PostCallRecordGetBufferDeviceAddress(device, pInfo, record_obj);
}

void DeviceState::PostCallRecordGetBufferDeviceAddressEXT(VkDevice device, const VkBufferDeviceAddressInfo* pInfo,
                                                          const RecordObject& record_obj) {
    PostCallRecordGetBufferDeviceAddress(device, pInfo, record_obj);
}

std::shared_ptr<Swapchain> DeviceState::CreateSwapchainState(const VkSwapchainCreateInfoKHR* create_info, VkSwapchainKHR handle) {
    return std::make_shared<Swapchain>(*this, create_info, handle);
}

std::shared_ptr<CommandBuffer> DeviceState::CreateCmdBufferState(VkCommandBuffer handle,
                                                                 const VkCommandBufferAllocateInfo* allocate_info,
                                                                 const CommandPool* pool) {
    return std::make_shared<CommandBuffer>(*this, handle, allocate_info, pool);
}

std::shared_ptr<DeviceMemory> DeviceState::CreateDeviceMemoryState(VkDeviceMemory handle, const VkMemoryAllocateInfo* allocate_info,
                                                                   uint64_t fake_address, const VkMemoryType& memory_type,
                                                                   const VkMemoryHeap& memory_heap,
                                                                   VulkanTypedHandle dedicated_binding,
                                                                   uint32_t physical_device_count) {
    return std::make_shared<DeviceMemory>(handle, allocate_info, fake_address, memory_type, memory_heap, dedicated_binding,
                                          physical_device_count);
}

void DeviceState::PostCallRecordCmdSetPrimitiveRestartIndexEXT(VkCommandBuffer commandBuffer, uint32_t primitiveRestartIndex,
                                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordSetPrimitiveRestartIndex(primitiveRestartIndex, record_obj.location);
}

void DeviceState::PostCallRecordCmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer, uint32_t firstBinding,
                                                                   uint32_t bindingCount, const VkBuffer* pBuffers,
                                                                   const VkDeviceSize* pOffsets, const VkDeviceSize* pSizes,
                                                                   const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->transform_feedback_buffers_bound = bindingCount;
}

void DeviceState::PostCallRecordCmdBindTransformFeedbackBuffers2EXT(VkCommandBuffer commandBuffer, uint32_t firstBinding,
                                                                    uint32_t bindingCount,
                                                                    const VkBindTransformFeedbackBuffer2InfoEXT* pBindingInfos,
                                                                    const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->transform_feedback_buffers_bound = bindingCount;
    for (uint32_t i = 0; i < bindingCount; ++i) {
        TrackDeviceAddressRange(*cb_state, pBindingInfos[i].addressRange.address, pBindingInfos[i].addressRange.size,
                                VK_BUFFER_USAGE_2_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
    }
}

void DeviceState::PostCallRecordGetAccelerationStructureDeviceAddressKHR(VkDevice device,
                                                                         const VkAccelerationStructureDeviceAddressInfoKHR* pInfo,
                                                                         const RecordObject& record_obj) {
    if (!pInfo) {
        return;
    }
    if (record_obj.device_address == 0) {
        return;
    }
    if (auto as_state = Get<vvl::AccelerationStructureKHR>(pInfo->accelerationStructure)) {
        as_state->SetAccelerationStructureAddress(record_obj.device_address);
        WriteLockGuard lock(as_with_addresses.array_mutex);
        if (as_with_addresses.array.capacity() <= (as_with_addresses.array.size() + 1)) {
            as_with_addresses.array.reserve(as_with_addresses.array.capacity() * 2);
        }
        as_with_addresses.array.emplace_back(as_state.get());
    }
}

small_vector<const vvl::AccelerationStructureKHR*, 2> DeviceState::GetAccelerationStructuresByAddress(
    VkDeviceAddress address) const {
    small_vector<const vvl::AccelerationStructureKHR*, 2> as_vector;
    if (address == 0) {
        return as_vector;
    }

    ReadLockGuard lock(as_with_addresses.array_mutex);
    auto as_found_it =
        std::find_if(as_with_addresses.array.begin(), as_with_addresses.array.end(),
                     [address](vvl::AccelerationStructureKHR* as) { return as->GetAccelerationStructureAddress() == address; });

    while (as_found_it != as_with_addresses.array.end()) {
        as_vector.emplace_back(*as_found_it);
        as_found_it = std::find_if(as_found_it + 1, as_with_addresses.array.end(), [address](vvl::AccelerationStructureKHR* as) {
            return as->GetAccelerationStructureAddress() == address;
        });
    }
    return as_vector;
}

void DeviceState::PreCallRecordLatencySleepNV(VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepInfoNV* pSleepInfo,
                                              const RecordObject& record_obj) {
    if (auto semaphore_state = Get<Semaphore>(pSleepInfo->signalSemaphore)) {
        auto value = pSleepInfo->value;
        semaphore_state->EnqueueSignal(SubmissionReference{}, value);
    }
}

// TODO: PostRecord is not needed. Test this. WaitSemaphores will retire the signal.
// LatencySleepNV does not perform wait but provides information about semaphore to the driver.
void DeviceState::PostCallRecordLatencySleepNV(VkDevice device, VkSwapchainKHR swapchain, const VkLatencySleepInfoNV* pSleepInfo,
                                               const RecordObject& record_obj) {
    if (auto semaphore_state = Get<Semaphore>(pSleepInfo->signalSemaphore)) {
        semaphore_state->RetireWait(nullptr, pSleepInfo->value, record_obj.location);
    }
}

void DeviceState::PostCallRecordCreateIndirectExecutionSetEXT(VkDevice device,
                                                              const VkIndirectExecutionSetCreateInfoEXT* pCreateInfo,
                                                              const VkAllocationCallbacks* pAllocator,
                                                              VkIndirectExecutionSetEXT* pIndirectExecutionSet,
                                                              const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }

    std::shared_ptr<IndirectExecutionSet> indirect_execution_state =
        std::make_shared<IndirectExecutionSet>(*this, *pIndirectExecutionSet, pCreateInfo);

    if (indirect_execution_state->is_pipeline && pCreateInfo->info.pPipelineInfo) {
        const VkIndirectExecutionSetPipelineInfoEXT& pipeline_info = *pCreateInfo->info.pPipelineInfo;
        indirect_execution_state->initial_pipeline = Get<Pipeline>(pipeline_info.initialPipeline);
        indirect_execution_state->shader_stage_flags = indirect_execution_state->initial_pipeline->active_shaders;
    } else if (indirect_execution_state->is_shader_objects && pCreateInfo->info.pShaderInfo) {
        const VkIndirectExecutionSetShaderInfoEXT& shader_info = *pCreateInfo->info.pShaderInfo;
        for (uint32_t i = 0; i < shader_info.shaderCount; i++) {
            const VkShaderEXT shader_handle = shader_info.pInitialShaders[i];
            const auto shader_object = Get<ShaderObject>(shader_handle);
            ASSERT_AND_CONTINUE(shader_object);
            indirect_execution_state->shader_stage_flags |= shader_object->create_info.stage;
            if (i == 0) {
                indirect_execution_state->initial_shader_object = shader_object;
            }
            if (shader_object->create_info.stage == VK_SHADER_STAGE_FRAGMENT_BIT) {
                indirect_execution_state->initial_fragment_shader_object = shader_object;
            }
        }
    }

    Add(std::move(indirect_execution_state));
}

void DeviceState::PreCallRecordDestroyIndirectExecutionSetEXT(VkDevice device, VkIndirectExecutionSetEXT indirectExecutionSet,
                                                              const VkAllocationCallbacks* pAllocator,
                                                              const RecordObject& record_obj) {
    Destroy<IndirectExecutionSet>(indirectExecutionSet);
}

void DeviceState::PostCallRecordCreateIndirectCommandsLayoutEXT(VkDevice device,
                                                                const VkIndirectCommandsLayoutCreateInfoEXT* pCreateInfo,
                                                                const VkAllocationCallbacks* pAllocator,
                                                                VkIndirectCommandsLayoutEXT* pIndirectCommandsLayout,
                                                                const RecordObject& record_obj) {
    if (record_obj.result != VK_SUCCESS) {
        return;
    }
    Add(std::make_shared<IndirectCommandsLayout>(*this, *pIndirectCommandsLayout, pCreateInfo));
}

void DeviceState::PreCallRecordDestroyIndirectCommandsLayoutEXT(VkDevice device, VkIndirectCommandsLayoutEXT indirectCommandsLayout,
                                                                const VkAllocationCallbacks* pAllocator,
                                                                const RecordObject& record_obj) {
    Destroy<IndirectCommandsLayout>(indirectCommandsLayout);
}

struct CommandBufferReservedAddressInfillUpdateOps {
    using Map = typename DeviceState::DescriptorHeapReservedAddress::RangeMap;
    using Iterator = typename Map::iterator;
    using Value = typename Map::value_type;
    using Mapped = typename Map::mapped_type;
    using Range = typename Map::key_type;

    void infill(Map& map, const Iterator& pos, const Range& infill_range) const {
        map.insert(pos, Value(infill_range, insert_value));
    }

    void update(const Iterator& pos) const {
        auto& current_buffer_list = pos->second;
        assert(!current_buffer_list.empty());
        const auto buffer_found_it = std::find(current_buffer_list.begin(), current_buffer_list.end(), insert_value[0]);
        if (buffer_found_it == current_buffer_list.end()) {
            if (current_buffer_list.capacity() <= (current_buffer_list.size() + 1)) {
                current_buffer_list.reserve(current_buffer_list.capacity() * 2);
            }
            current_buffer_list.emplace_back(insert_value[0]);
        }
    }
    const Mapped& insert_value;
};

struct CommandBufferReservedAddressRemoveOps {
    using Map = DeviceState::DescriptorHeapReservedAddress::RangeMap;
    using Mapped = Map::mapped_type;

    bool operator()(Mapped& cmd_buffer_list) const {
        auto it = std::find(cmd_buffer_list.begin(), cmd_buffer_list.end(), removed_value);
        if (it != cmd_buffer_list.end()) {
            if (cmd_buffer_list.size() == 1) {
                return true;
            } else {
                // Swap with last element and resize to remove it
                size_t idx = std::distance(cmd_buffer_list.begin(), it);
                if (idx != cmd_buffer_list.size() - 1) {
                    std::swap(cmd_buffer_list[idx], cmd_buffer_list.back());
                }
                cmd_buffer_list.resize(cmd_buffer_list.size() - 1);
                return false;
            }
        }
        return false;
    }

    const vvl::CommandBuffer* removed_value;
};

void DeviceState::UpdateCommandBufferHeapReservedAddressMap(vvl::CommandBuffer* cb_state,
                                                            const vvl::range<VkDeviceAddress>& new_range, bool is_sampler) {
    assert(cb_state != nullptr);

    WriteLockGuard guard(descriptor_heap_reserved_address.lock);

    const vvl::range<VkDeviceAddress>& existing_range =
        is_sampler ? cb_state->descriptor_heap.sampler_reserved : cb_state->descriptor_heap.resource_reserved;
    DescriptorHeapReservedAddress::RangeMap& cmd_buffer_map =
        is_sampler ? descriptor_heap_reserved_address.sampler_map : descriptor_heap_reserved_address.resource_map;

    if (existing_range.non_empty()) {
        CommandBufferReservedAddressRemoveOps remove_ops{cb_state};
        cmd_buffer_map.erase_range_or_touch(existing_range, remove_ops);
    }

    if (new_range.non_empty()) {
        CommandBufferReservedAddressInfillUpdateOps update_ops{{cb_state}};
        sparse_container::infill_update_range(cmd_buffer_map, new_range, update_ops);
    }
}

void DeviceState::RemoveCommandBufferHeapReservedAddressMap(vvl::CommandBuffer* cb_state) {
    assert(cb_state != nullptr);

    WriteLockGuard guard(descriptor_heap_reserved_address.lock);

    const vvl::range<VkDeviceAddress>& resource_existing_range = cb_state->descriptor_heap.resource_reserved;
    if (resource_existing_range.non_empty()) {
        CommandBufferReservedAddressRemoveOps remove_ops{cb_state};
        descriptor_heap_reserved_address.resource_map.erase_range_or_touch(resource_existing_range, remove_ops);
    }

    const vvl::range<VkDeviceAddress>& sampler_existing_range = cb_state->descriptor_heap.sampler_reserved;
    if (sampler_existing_range.non_empty()) {
        CommandBufferReservedAddressRemoveOps remove_ops{cb_state};
        descriptor_heap_reserved_address.sampler_map.erase_range_or_touch(sampler_existing_range, remove_ops);
    }
}

void DeviceState::PostCallRecordCmdBindSamplerHeapEXT(VkCommandBuffer commandBuffer, const VkBindHeapInfoEXT* pBindInfo,
                                                      const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->descriptor_heap.sampler_bound = true;

    vvl::range<VkDeviceAddress> reserved = {
        pBindInfo->heapRange.address + pBindInfo->reservedRangeOffset,
        pBindInfo->heapRange.address + pBindInfo->reservedRangeOffset + pBindInfo->reservedRangeSize};

    if (cb_state->descriptor_heap.sampler_reserved != reserved) {
        UpdateCommandBufferHeapReservedAddressMap(cb_state.get(), reserved, true);
        cb_state->descriptor_heap.sampler_reserved = reserved;
    }

    vvl::range<VkDeviceAddress> range = {pBindInfo->heapRange.address, pBindInfo->heapRange.address + pBindInfo->heapRange.size};
    cb_state->descriptor_heap.sampler_range = range;

    cb_state->SetDescriptorMode(DescriptorModeHeap, record_obj.location.function);
    TrackDeviceAddressRange(*cb_state, range, VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT);
}

void DeviceState::PostCallRecordCmdBindResourceHeapEXT(VkCommandBuffer commandBuffer, const VkBindHeapInfoEXT* pBindInfo,
                                                       const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->descriptor_heap.resource_bound = true;

    vvl::range<VkDeviceAddress> reserved = {
        pBindInfo->heapRange.address + pBindInfo->reservedRangeOffset,
        pBindInfo->heapRange.address + pBindInfo->reservedRangeOffset + pBindInfo->reservedRangeSize};

    if (cb_state->descriptor_heap.resource_reserved != reserved) {
        UpdateCommandBufferHeapReservedAddressMap(cb_state.get(), reserved, false);
        cb_state->descriptor_heap.resource_reserved = reserved;
    }

    vvl::range<VkDeviceAddress> range = {pBindInfo->heapRange.address, pBindInfo->heapRange.address + pBindInfo->heapRange.size};
    cb_state->descriptor_heap.resource_range = range;

    cb_state->SetDescriptorMode(DescriptorModeHeap, record_obj.location.function);
    TrackDeviceAddressRange(*cb_state, range, VK_BUFFER_USAGE_2_DESCRIPTOR_HEAP_BIT_EXT);
}

void DeviceState::PostCallRecordCmdPushDataEXT(VkCommandBuffer commandBuffer, const VkPushDataInfoEXT* pPushDataInfo,
                                               const RecordObject& record_obj) {
    auto cb_state = GetWrite<CommandBuffer>(commandBuffer);
    cb_state->RecordCmdPushDataEXT(*pPushDataInfo, record_obj.location);

    cb_state->SetDescriptorMode(DescriptorModeHeap, record_obj.location.function);
}

}  // namespace vvl
