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

#include "gpuav/validation_cmd/gpuav_draw.h"
#include <vulkan/vulkan_core.h>

#include "gpuav/core/gpuav.h"
#include "gpuav/core/gpuav_validation_pipeline.h"
#include "gpuav/validation_cmd/gpuav_validation_cmd_common.h"
#include "gpuav/resources/gpuav_vulkan_objects.h"
#include "gpuav/resources/gpuav_state_trackers.h"
#include "gpuav/shaders/gpuav_error_header.h"

#include "state_tracker/pipeline_state.h"
#include "gpuav/shaders/gpuav_error_header.h"
#include "gpuav/shaders/validation_cmd/push_data.h"
#include "generated/gpuav_offline_spirv.h"

namespace gpuav {
namespace valcmd {

using ErrorLoggerFunc = CommandBufferSubState::ErrorLoggerFunc;

struct SharedDrawValidationResources {
    vko::Buffer dummy_buffer;  // Used to fill unused buffer bindings in validation pipelines
    bool valid = false;

    SharedDrawValidationResources(Validator& gpuav) : dummy_buffer(gpuav) {
        VkBufferCreateInfo dummy_buffer_info = vku::InitStructHelper();
        dummy_buffer_info.size = 64;  // whatever
        dummy_buffer_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
        VmaAllocationCreateInfo alloc_info = {};
        alloc_info.usage = VMA_MEMORY_USAGE_AUTO;
        if (gpuav.IsAllDeviceLocalMappable()) {
            alloc_info.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
        }
        const VkResult result = dummy_buffer.Create(&dummy_buffer_info, &alloc_info);
        if (result != VK_SUCCESS) {
            valid = false;
            return;
        }

        valid = true;
    }

    ~SharedDrawValidationResources() { dummy_buffer.Destroy(); }
};

using ValidationCommandFunc = stdext::inplace_function<void(Validator& gpuav, CommandBufferSubState& cb_state), 192>;
struct ValidationCmdCbState {
    std::vector<ValidationCommandFunc> per_render_pass_validation_commands;
};

void FlushValidationCmds(Validator& gpuav, CommandBufferSubState& cb_state) {
    ValidationCmdCbState* val_cmd_cb_state = cb_state.shared_resources_cache.TryGet<ValidationCmdCbState>();
    if (!val_cmd_cb_state) {
        return;
    }

    valpipe::RestorablePipelineState restorable_state(cb_state, VK_PIPELINE_BIND_POINT_COMPUTE);

    for (auto& validation_cmd : val_cmd_cb_state->per_render_pass_validation_commands) {
        validation_cmd(gpuav, cb_state);
    }
    val_cmd_cb_state->per_render_pass_validation_commands.clear();
}

struct FirstInstanceValidationShader {
    static size_t GetSpirvSize() { return validation_cmd_first_instance_comp_size * sizeof(uint32_t); }
    static const uint32_t* GetSpirv() { return validation_cmd_first_instance_comp; }

    glsl::FirstInstancePushData push_constants{};
    valpipe::BoundStorageBuffer draw_buffer_binding = {glsl::kPreDrawBinding_IndirectBuffer};
    valpipe::BoundStorageBuffer count_buffer_binding = {glsl::kPreDrawBinding_CountBuffer};

    static std::vector<VkDescriptorSetLayoutBinding> GetDescriptorSetLayoutBindings() {
        return {{glsl::kPreDrawBinding_IndirectBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr},
                {glsl::kPreDrawBinding_CountBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}};
    }

    std::vector<VkWriteDescriptorSet> GetDescriptorWrites() const {
        std::vector<VkWriteDescriptorSet> desc_writes(2);

        desc_writes[0] = vku::InitStructHelper();
        desc_writes[0].dstBinding = draw_buffer_binding.binding;
        desc_writes[0].dstArrayElement = 0;
        desc_writes[0].descriptorCount = 1;
        desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
        desc_writes[0].pBufferInfo = &draw_buffer_binding.info;

        desc_writes[1] = vku::InitStructHelper();
        desc_writes[1].dstBinding = count_buffer_binding.binding;
        desc_writes[1].dstArrayElement = 0;
        desc_writes[1].descriptorCount = 1;
        desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
        desc_writes[1].pBufferInfo = &count_buffer_binding.info;

        return desc_writes;
    }
};

void FirstInstance(Validator& gpuav, CommandBufferSubState& cb_state, const Location& loc, const LastBound& last_bound,
                   VkBuffer api_buffer, VkDeviceSize api_offset, uint32_t api_stride, vvl::Struct api_struct_name,
                   uint32_t first_instance_member_pos, uint32_t api_draw_count, VkBuffer api_count_buffer,
                   VkDeviceSize api_count_buffer_offset, const FirstInstanceValidationVuidSelector& vuid_selector) {
    if (!gpuav.gpuav_settings.validate_indirect_draws_buffers) {
        return;
    }

    const char* vuid = vuid_selector(gpuav, last_bound);
    if (!vuid) {
        return;  // No reason to validate, there is no possible VUID to report
    }

    ValidationCommandFunc validation_cmd = [api_buffer, api_offset, api_stride, first_instance_member_pos, api_draw_count,
                                            api_count_buffer, api_count_buffer_offset, draw_i = cb_state.draw_index,
                                            error_logger_i = cb_state.GetErrorLoggerIndex(),
                                            loc](Validator& gpuav, CommandBufferSubState& cb_state) {
        SharedDrawValidationResources& shared_draw_validation_resources =
            gpuav.shared_resources_cache.GetOrCreate<SharedDrawValidationResources>(gpuav);
        if (!shared_draw_validation_resources.valid) {
            gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to create SharedDrawValidationResources.");
            return;
        }
        ValidationCommandsGpuavState& val_cmd_gpuav_state =
            gpuav.shared_resources_cache.GetOrCreate<ValidationCommandsGpuavState>(gpuav, loc);
        valpipe::ComputePipeline<FirstInstanceValidationShader>& validation_pipeline =
            gpuav.shared_resources_cache.GetOrCreate<valpipe::ComputePipeline<FirstInstanceValidationShader>>(
                gpuav, loc, val_cmd_gpuav_state.error_logging_desc_set_layout_);
        if (!validation_pipeline.valid) {
            gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to create FirstInstanceValidationShader.");
            return;
        }

        auto draw_buffer_state = gpuav.Get<vvl::Buffer>(api_buffer);
        if (!draw_buffer_state) {
            gpuav.InternalError(LogObjectList(cb_state.VkHandle(), api_buffer), loc, "buffer must be a valid VkBuffer handle");
            return;
        }

        // Setup shader resources
        // ---
        {
            FirstInstanceValidationShader shader_resources;
            shader_resources.push_constants.api_stride_dwords = api_stride / sizeof(uint32_t);
            shader_resources.push_constants.api_draw_count = api_draw_count;
            shader_resources.push_constants.first_instance_member_pos = first_instance_member_pos;

            shader_resources.draw_buffer_binding.info = {api_buffer, 0, VK_WHOLE_SIZE};
            shader_resources.push_constants.api_offset_dwords = (uint32_t)api_offset / sizeof(uint32_t);
            if (api_count_buffer) {
                shader_resources.push_constants.flags |= glsl::kFirstInstanceFlags_DrawCountFromBuffer;
                shader_resources.count_buffer_binding.info = {api_count_buffer, 0, sizeof(uint32_t)};
                shader_resources.push_constants.api_count_buffer_offset_dwords =
                    uint32_t(api_count_buffer_offset / sizeof(uint32_t));

            } else {
                shader_resources.count_buffer_binding.info = {shared_draw_validation_resources.dummy_buffer.VkHandle(), 0,
                                                              VK_WHOLE_SIZE};
            }

            if (!BindShaderResources(validation_pipeline, gpuav, cb_state, draw_i, error_logger_i, shader_resources)) {
                gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to GetManagedDescriptorSet in BindShaderResources");
                return;
            }
        }

        // Setup validation pipeline
        // ---
        {
            DispatchCmdBindPipeline(cb_state.VkHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, validation_pipeline.pipeline);

            uint32_t max_held_draw_cmds = 0;
            if (draw_buffer_state->GetSize() > api_offset) {
                // If drawCount is less than or equal to one, stride is ignored
                if (api_draw_count > 1) {
                    max_held_draw_cmds = static_cast<uint32_t>((draw_buffer_state->GetSize() - api_offset) / api_stride);
                } else {
                    max_held_draw_cmds = 1;
                }
            }
            // It is assumed that the number of draws to validate is fairly low.
            // Otherwise might reconsider having a warp dimension of (1, 1, 1)
            // Maybe another reason to add telemetry?
            const uint32_t work_group_count = std::min(api_draw_count, max_held_draw_cmds);

            if (work_group_count == 0) {
                return;
            }

            DispatchCmdDispatch(cb_state.VkHandle(), work_group_count, 1, 1);

            // synchronize draw buffer validation (read) against subsequent writes
            std::array<VkBufferMemoryBarrier, 2> buffer_memory_barriers = {};
            uint32_t buffer_memory_barriers_count = 1;
            buffer_memory_barriers[0] = vku::InitStructHelper();
            buffer_memory_barriers[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
            buffer_memory_barriers[0].dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
            buffer_memory_barriers[0].buffer = api_buffer;
            buffer_memory_barriers[0].offset = api_offset;
            buffer_memory_barriers[0].size = work_group_count * sizeof(uint32_t);

            if (api_count_buffer) {
                buffer_memory_barriers[1] = vku::InitStructHelper();
                buffer_memory_barriers[1].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
                buffer_memory_barriers[1].dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
                buffer_memory_barriers[1].buffer = api_count_buffer;
                buffer_memory_barriers[1].offset = api_count_buffer_offset;
                buffer_memory_barriers[1].size = sizeof(uint32_t);
                ++buffer_memory_barriers_count;
            }

            DispatchCmdPipelineBarrier(cb_state.VkHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
                                       VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, buffer_memory_barriers_count,
                                       buffer_memory_barriers.data(), 0, nullptr);
        }
    };

    ValidationCmdCbState& val_cmd_cb_state = cb_state.shared_resources_cache.GetOrCreate<ValidationCmdCbState>();
    val_cmd_cb_state.per_render_pass_validation_commands.emplace_back(std::move(validation_cmd));

    // Register error logger. Happens per command GPU-AV intercepts
    // ---
    ErrorLoggerFunc error_logger = [&gpuav, vuid, api_struct_name](const uint32_t* error_record,
                                                                   const Location& loc_with_debug_region,
                                                                   const LogObjectList& objlist) {
        bool skip = false;
        using namespace glsl;

        if (GetErrorGroup(error_record) != kErrorGroup_GpuPreDraw) {
            return skip;
        }

        assert(GetSubError(error_record) == kErrorSubCode_PreDraw_FirstInstance);

        const uint32_t index = error_record[kValCmd_ErrorPayloadDword_0];
        const uint32_t invalid_first_instance = error_record[kValCmd_ErrorPayloadDword_1];

        skip |= gpuav.LogError(vuid, objlist, loc_with_debug_region,
                               "The firstInstance member of the %s structure at "
                               "index %" PRIu32 " is %" PRIu32 ".",
                               vvl::String(api_struct_name), index, invalid_first_instance);

        return skip;
    };

    cb_state.AddCommandErrorLogger(loc, &last_bound, std::move(error_logger));
}

struct FirstInstanceVUIDs {
    const char* vuid_09461{};
    const char* vuid_09462{};
    const char* vuid_00501_00554{};
};

static FirstInstanceValidationVuidSelector GetFirstInstanceValidationVuidSelector(const FirstInstanceVUIDs& first_instance_vuids) {
    FirstInstanceValidationVuidSelector vuid_selector = [first_instance_vuids](Validator& gpuav, const LastBound& last_bound) {
        if (!gpuav.phys_dev_props_core14.supportsNonZeroFirstInstance) {
            if (last_bound.IsDynamic(CB_DYNAMIC_STATE_VERTEX_INPUT_EXT)) {
                for (const auto& [binding, binding_state] : last_bound.cb_state.dynamic_state_value.vertex_bindings) {
                    if (binding_state.desc.divisor != 1) {
                        return first_instance_vuids.vuid_09462;
                    }
                }
            } else if (last_bound.pipeline_state && last_bound.pipeline_state->GraphicsCreateInfo().pVertexInputState) {
                if (auto divisor_state_ci = vku::FindStructInPNextChain<VkPipelineVertexInputDivisorStateCreateInfo>(
                        last_bound.pipeline_state->GraphicsCreateInfo().pVertexInputState->pNext)) {
                    for (const VkVertexInputBindingDivisorDescription& divisor :
                         vvl::make_span(divisor_state_ci->pVertexBindingDivisors, divisor_state_ci->vertexBindingDivisorCount)) {
                        if (divisor.divisor != 1u) {
                            return first_instance_vuids.vuid_09461;
                        }
                    }
                }
            }
        }

        if (!gpuav.enabled_features.drawIndirectFirstInstance) {
            return first_instance_vuids.vuid_00501_00554;
        }

        // Return null to show |firstInstance| could be anything and it will still be valid
        return (const char*)nullptr;
    };

    return vuid_selector;
}

template <>
void FirstInstance<VkDrawIndirectCommand>(Validator& gpuav, CommandBufferSubState& cb_state, const Location& loc,
                                          const LastBound& last_bound, VkBuffer buffer, VkDeviceSize offset, uint32_t draw_count,
                                          VkBuffer count_buffer, VkDeviceSize count_buffer_offset) {
    FirstInstanceVUIDs vuids;
    vuids.vuid_09461 = "VUID-VkDrawIndirectCommand-pNext-09461";
    vuids.vuid_09462 = "VUID-VkDrawIndirectCommand-None-09462";
    vuids.vuid_00501_00554 = "VUID-VkDrawIndirectCommand-firstInstance-00501";

    FirstInstanceValidationVuidSelector vuid_selector = GetFirstInstanceValidationVuidSelector(vuids);
    FirstInstance(gpuav, cb_state, loc, last_bound, buffer, offset, sizeof(VkDrawIndirectCommand),
                  vvl::Struct::VkDrawIndirectCommand, 3, draw_count, count_buffer, count_buffer_offset, vuid_selector);
}

template <>
void FirstInstance<VkDrawIndexedIndirectCommand>(Validator& gpuav, CommandBufferSubState& cb_state, const Location& loc,
                                                 const LastBound& last_bound, VkBuffer buffer, VkDeviceSize offset,
                                                 uint32_t draw_count, VkBuffer count_buffer, VkDeviceSize count_buffer_offset) {
    FirstInstanceVUIDs vuids;
    vuids.vuid_09461 = "VUID-VkDrawIndexedIndirectCommand-pNext-09461";
    vuids.vuid_09462 = "VUID-VkDrawIndexedIndirectCommand-None-09462";
    vuids.vuid_00501_00554 = "VUID-VkDrawIndexedIndirectCommand-firstInstance-00554";

    FirstInstanceValidationVuidSelector vuid_selector = GetFirstInstanceValidationVuidSelector(vuids);
    FirstInstance(gpuav, cb_state, loc, last_bound, buffer, offset, sizeof(VkDrawIndexedIndirectCommand),
                  vvl::Struct::VkDrawIndexedIndirectCommand, 4, draw_count, count_buffer, count_buffer_offset, vuid_selector);
}

struct CountBufferValidationShader {
    static size_t GetSpirvSize() { return validation_cmd_count_buffer_comp_size * sizeof(uint32_t); }
    static const uint32_t* GetSpirv() { return validation_cmd_count_buffer_comp; }

    glsl::CountBufferPushData push_constants{};
    valpipe::BoundStorageBuffer count_buffer_binding = {glsl::kPreDrawBinding_CountBuffer};

    static std::vector<VkDescriptorSetLayoutBinding> GetDescriptorSetLayoutBindings() {
        return {{glsl::kPreDrawBinding_CountBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}};
    }

    std::vector<VkWriteDescriptorSet> GetDescriptorWrites() const {
        std::vector<VkWriteDescriptorSet> desc_writes(1);

        desc_writes[0] = vku::InitStructHelper();
        desc_writes[0].dstBinding = count_buffer_binding.binding;
        desc_writes[0].dstArrayElement = 0;
        desc_writes[0].descriptorCount = 1;
        desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
        desc_writes[0].pBufferInfo = &count_buffer_binding.info;

        return desc_writes;
    }
};

void CountBuffer(Validator& gpuav, CommandBufferSubState& cb_state, const Location& loc, const LastBound& last_bound,
                 VkBuffer api_buffer, VkDeviceSize api_offset, uint32_t api_struct_size_byte, vvl::Struct api_struct_name,
                 uint32_t api_stride, VkBuffer api_count_buffer, VkDeviceSize api_count_buffer_offset, const char* vuid) {
    if (!gpuav.gpuav_settings.validate_indirect_draws_buffers) {
        return;
    }

    auto draw_buffer_state = gpuav.Get<vvl::Buffer>(api_buffer);
    if (!draw_buffer_state) {
        gpuav.InternalError(LogObjectList(cb_state.VkHandle(), api_buffer), loc, "buffer must be a valid VkBuffer handle");
        return;
    }

    ValidationCommandFunc validation_cmd = [draw_buffer_size = draw_buffer_state->GetSize(), api_offset,
                                            api_struct_size_byte, api_stride, api_count_buffer, api_count_buffer_offset,
                                            draw_i = cb_state.draw_index, error_logger_i = cb_state.GetErrorLoggerIndex(),
                                            loc](Validator& gpuav, CommandBufferSubState& cb_state) {
        SharedDrawValidationResources& shared_draw_validation_resources =
            gpuav.shared_resources_cache.GetOrCreate<SharedDrawValidationResources>(gpuav);
        if (!shared_draw_validation_resources.valid) {
            gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to create SharedDrawValidationResources.");
            return;
        }
        ValidationCommandsGpuavState& val_cmd_gpuav_state =
            gpuav.shared_resources_cache.GetOrCreate<ValidationCommandsGpuavState>(gpuav, loc);
        valpipe::ComputePipeline<CountBufferValidationShader>& validation_pipeline =
            gpuav.shared_resources_cache.GetOrCreate<valpipe::ComputePipeline<CountBufferValidationShader>>(
                gpuav, loc, val_cmd_gpuav_state.error_logging_desc_set_layout_);
        if (!validation_pipeline.valid) {
            gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to create CountBufferValidationShader.");
            return;
        }

        // Setup shader resources
        // ---
        {
            CountBufferValidationShader shader_resources;
            shader_resources.push_constants.api_stride = api_stride;
            shader_resources.push_constants.api_offset = api_offset;
            shader_resources.push_constants.draw_buffer_size = draw_buffer_size;
            shader_resources.push_constants.api_struct_size_byte = api_struct_size_byte;
            shader_resources.push_constants.device_limit_max_draw_indirect_count = gpuav.phys_dev_props.limits.maxDrawIndirectCount;

            shader_resources.count_buffer_binding.info = {api_count_buffer, 0, sizeof(uint32_t)};
            shader_resources.push_constants.api_count_buffer_offset_dwords = uint32_t(api_count_buffer_offset / sizeof(uint32_t));

            if (!BindShaderResources(validation_pipeline, gpuav, cb_state, draw_i, error_logger_i, shader_resources)) {
                gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to GetManagedDescriptorSet in BindShaderResources");
                return;
            }
        }

        // Setup validation pipeline
        // ---
        {
            DispatchCmdBindPipeline(cb_state.VkHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, validation_pipeline.pipeline);
            DispatchCmdDispatch(cb_state.VkHandle(), 1, 1, 1);
            // synchronize draw buffer validation (read) against subsequent writes
            VkBufferMemoryBarrier count_buffer_memory_barrier = vku::InitStructHelper();
            count_buffer_memory_barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
            count_buffer_memory_barrier.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
            count_buffer_memory_barrier.buffer = api_count_buffer;
            count_buffer_memory_barrier.offset = api_count_buffer_offset;
            count_buffer_memory_barrier.size = sizeof(uint32_t);

            DispatchCmdPipelineBarrier(cb_state.VkHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
                                       VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 1, &count_buffer_memory_barrier, 0,
                                       nullptr);
        }
    };

    ValidationCmdCbState& val_cmd_cb_state = cb_state.shared_resources_cache.GetOrCreate<ValidationCmdCbState>();
    val_cmd_cb_state.per_render_pass_validation_commands.emplace_back(std::move(validation_cmd));

    // Register error logger
    // ---
    ErrorLoggerFunc error_logger = [&gpuav, api_buffer, draw_buffer_size = draw_buffer_state->GetSize(), api_offset,
                                    api_struct_size_byte, api_stride, api_struct_name,
                                    vuid](const uint32_t* error_record, const Location& loc_with_debug_region,
                                          const LogObjectList& objlist) {
        bool skip = false;
        using namespace glsl;

        const uint32_t error_sub_code = GetSubError(error_record);
        switch (error_sub_code) {
            case kErrorSubCode_PreDraw_DrawBufferSize: {
                const uint32_t count = error_record[kValCmd_ErrorPayloadDword_0];

                const VkDeviceSize draw_size = (api_stride * (count - 1) + api_offset + api_struct_size_byte);

                // Discussed that if drawCount is largeer than the buffer, it is still capped by the maxDrawCount on the CPU (which
                // we would have checked is in the buffer range). We decided that we still want to give a warning, but the nothing
                // is invalid here. https://gitlab.khronos.org/vulkan/vulkan/-/issues/3991
                skip |= gpuav.LogWarning("WARNING-GPU-AV-drawCount", objlist, loc_with_debug_region,
                                         "Indirect draw count of %" PRIu32 " would exceed size (%" PRIu64
                                         ") of buffer (%s). "
                                         "stride = %" PRIu32 " offset = %" PRIu64
                                         " (stride * (drawCount - 1) + offset + sizeof(%s)) = %" PRIu64 ".",
                                         count, draw_buffer_size, gpuav.FormatHandle(api_buffer).c_str(), api_stride, api_offset,
                                         vvl::String(api_struct_name), draw_size);
                break;
            }
            case kErrorSubCode_PreDraw_DrawCountLimit: {
                const uint32_t count = error_record[kValCmd_ErrorPayloadDword_0];
                skip |= gpuav.LogError(vuid, objlist, loc_with_debug_region,
                                       "Indirect draw count of %" PRIu32 " would exceed maxDrawIndirectCount limit of %" PRIu32 ".",
                                       count, gpuav.phys_dev_props.limits.maxDrawIndirectCount);
                break;
            }
            default:
                assert(false);
                return skip;
        }

        return skip;
    };

    cb_state.AddCommandErrorLogger(loc, &last_bound, std::move(error_logger));
}

struct MeshValidationShader {
    static size_t GetSpirvSize() { return validation_cmd_draw_mesh_indirect_comp_size * sizeof(uint32_t); }
    static const uint32_t* GetSpirv() { return validation_cmd_draw_mesh_indirect_comp; }

    glsl::DrawMeshPushData push_constants{};
    valpipe::BoundStorageBuffer draw_buffer_binding = {glsl::kPreDrawBinding_IndirectBuffer};
    valpipe::BoundStorageBuffer count_buffer_binding = {glsl::kPreDrawBinding_CountBuffer};

    static std::vector<VkDescriptorSetLayoutBinding> GetDescriptorSetLayoutBindings() {
        return {{glsl::kPreDrawBinding_IndirectBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr},
                {glsl::kPreDrawBinding_CountBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}};
    }

    std::vector<VkWriteDescriptorSet> GetDescriptorWrites() const {
        std::vector<VkWriteDescriptorSet> desc_writes(2);

        desc_writes[0] = vku::InitStructHelper();
        desc_writes[0].dstBinding = draw_buffer_binding.binding;
        desc_writes[0].dstArrayElement = 0;
        desc_writes[0].descriptorCount = 1;
        desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
        desc_writes[0].pBufferInfo = &draw_buffer_binding.info;

        desc_writes[1] = vku::InitStructHelper();
        desc_writes[1].dstBinding = count_buffer_binding.binding;
        desc_writes[1].dstArrayElement = 0;
        desc_writes[1].descriptorCount = 1;
        desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
        desc_writes[1].pBufferInfo = &count_buffer_binding.info;

        return desc_writes;
    }
};

void DrawMeshIndirect(Validator& gpuav, CommandBufferSubState& cb_state, const Location& loc, const LastBound& last_bound,
                      VkBuffer api_buffer, VkDeviceSize api_offset, uint32_t api_stride, VkBuffer api_count_buffer,
                      VkDeviceSize api_count_buffer_offset, uint32_t api_draw_count) {
    if (!gpuav.gpuav_settings.validate_indirect_draws_buffers) {
        return;
    }

    auto draw_buffer_state = gpuav.Get<vvl::Buffer>(api_buffer);
    if (!draw_buffer_state) {
        gpuav.InternalError(LogObjectList(cb_state.VkHandle(), api_buffer), loc, "buffer must be a valid VkBuffer handle");
        return;
    }

    const VkShaderStageFlags stages = last_bound.GetAllActiveBoundStages();
    const bool is_task_shader = (stages & VK_SHADER_STAGE_TASK_BIT_EXT) == VK_SHADER_STAGE_TASK_BIT_EXT;

    ValidationCommandFunc validation_cmd = [api_buffer, draw_buffer_full_size = draw_buffer_state->GetSize(), api_offset,
                                            api_stride, api_count_buffer, api_count_buffer_offset, api_draw_count, is_task_shader,
                                            draw_i = cb_state.draw_index, error_logger_i = cb_state.GetErrorLoggerIndex(),
                                            loc](Validator& gpuav, CommandBufferSubState& cb_state) {
        SharedDrawValidationResources& shared_draw_validation_resources =
            gpuav.shared_resources_cache.GetOrCreate<SharedDrawValidationResources>(gpuav);
        if (!shared_draw_validation_resources.valid) {
            gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to create SharedDrawValidationResources.");
            return;
        }
        ValidationCommandsGpuavState& val_cmd_gpuav_state =
            gpuav.shared_resources_cache.GetOrCreate<ValidationCommandsGpuavState>(gpuav, loc);
        valpipe::ComputePipeline<MeshValidationShader>& validation_pipeline =
            gpuav.shared_resources_cache.GetOrCreate<valpipe::ComputePipeline<MeshValidationShader>>(
                gpuav, loc, val_cmd_gpuav_state.error_logging_desc_set_layout_);
        if (!validation_pipeline.valid) {
            gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to create MeshValidationShader.");
            return;
        }

        // Setup shader resources
        // ---
        {
            MeshValidationShader shader_resources;
            shader_resources.push_constants.api_stride_dwords = api_stride / sizeof(uint32_t);
            shader_resources.push_constants.api_draw_count = api_draw_count;
            const auto& properties = gpuav.phys_dev_ext_props.mesh_shader_props_ext;
            if (is_task_shader) {
                shader_resources.push_constants.max_workgroup_count_x = properties.maxTaskWorkGroupCount[0];
                shader_resources.push_constants.max_workgroup_count_y = properties.maxTaskWorkGroupCount[1];
                shader_resources.push_constants.max_workgroup_count_z = properties.maxTaskWorkGroupCount[2];
                shader_resources.push_constants.max_workgroup_total_count = properties.maxTaskWorkGroupTotalCount;
            } else {
                shader_resources.push_constants.max_workgroup_count_x = properties.maxMeshWorkGroupCount[0];
                shader_resources.push_constants.max_workgroup_count_y = properties.maxMeshWorkGroupCount[1];
                shader_resources.push_constants.max_workgroup_count_z = properties.maxMeshWorkGroupCount[2];
                shader_resources.push_constants.max_workgroup_total_count = properties.maxMeshWorkGroupTotalCount;
            }

            shader_resources.draw_buffer_binding.info = {api_buffer, 0, VK_WHOLE_SIZE};
            shader_resources.push_constants.api_offset_dwords = uint32_t(api_offset / sizeof(uint32_t));
            if (api_count_buffer != VK_NULL_HANDLE) {
                shader_resources.push_constants.flags |= glsl::kDrawMeshFlags_DrawCountFromBuffer;
                shader_resources.count_buffer_binding.info = {api_count_buffer, 0, sizeof(uint32_t)};
                shader_resources.push_constants.api_count_buffer_offset_dwords =
                    uint32_t(api_count_buffer_offset / sizeof(uint32_t));
            } else {
                shader_resources.count_buffer_binding.info = {shared_draw_validation_resources.dummy_buffer.VkHandle(), 0,
                                                              VK_WHOLE_SIZE};
            }

            if (!BindShaderResources(validation_pipeline, gpuav, cb_state, draw_i, error_logger_i, shader_resources)) {
                return;
            }
        }

        // Setup validation pipeline
        // ---
        {
            DispatchCmdBindPipeline(cb_state.VkHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, validation_pipeline.pipeline);

            uint32_t max_held_draw_cmds = 0;
            if (draw_buffer_full_size > api_offset) {
                // If drawCount is less than or equal to one, stride is ignored
                if (api_draw_count > 1) {
                    max_held_draw_cmds = static_cast<uint32_t>((draw_buffer_full_size - api_offset) / api_stride);
                } else {
                    max_held_draw_cmds = 1;
                }
            }
            const uint32_t work_group_count = std::min(api_draw_count, max_held_draw_cmds);
            DispatchCmdDispatch(cb_state.VkHandle(), work_group_count, 1, 1);

            // synchronize draw buffer validation (read) against subsequent writes
            std::array<VkBufferMemoryBarrier, 2> buffer_memory_barriers = {};
            uint32_t buffer_memory_barriers_count = 1;
            buffer_memory_barriers[0] = vku::InitStructHelper();
            buffer_memory_barriers[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
            buffer_memory_barriers[0].dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
            buffer_memory_barriers[0].buffer = api_buffer;
            buffer_memory_barriers[0].offset = api_offset;
            buffer_memory_barriers[0].size = work_group_count * sizeof(uint32_t);

            if (api_count_buffer) {
                buffer_memory_barriers[1] = vku::InitStructHelper();
                buffer_memory_barriers[1].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
                buffer_memory_barriers[1].dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
                buffer_memory_barriers[1].buffer = api_count_buffer;
                buffer_memory_barriers[1].offset = api_count_buffer_offset;
                buffer_memory_barriers[1].size = sizeof(uint32_t);
                ++buffer_memory_barriers_count;
            }

            DispatchCmdPipelineBarrier(cb_state.VkHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
                                       VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, buffer_memory_barriers_count,
                                       buffer_memory_barriers.data(), 0, nullptr);
        }
    };

    ValidationCmdCbState& val_cmd_cb_state = cb_state.shared_resources_cache.GetOrCreate<ValidationCmdCbState>();
    val_cmd_cb_state.per_render_pass_validation_commands.emplace_back(std::move(validation_cmd));

    // Register error logger
    // ---
    ErrorLoggerFunc error_logger = [&gpuav, is_task_shader](const uint32_t* error_record, const Location& loc_with_debug_region,
                                                            const LogObjectList& objlist) {
        bool skip = false;
        using namespace glsl;

        const uint32_t draw_i = error_record[kValCmd_ErrorPayloadDword_1];
        const char* group_count_name = is_task_shader ? "maxTaskWorkGroupCount" : "maxMeshWorkGroupCount";
        const char* group_count_total_name = is_task_shader ? "maxTaskWorkGroupTotalCount" : "maxMeshWorkGroupTotalCount";

        const uint32_t error_sub_code = GetSubError(error_record);
        switch (error_sub_code) {
            case kErrorSubCode_PreDraw_GroupCountX: {
                const char* vuid = is_task_shader ? "VUID-VkDrawMeshTasksIndirectCommandEXT-TaskEXT-07322"
                                                  : "VUID-VkDrawMeshTasksIndirectCommandEXT-TaskEXT-07326";
                const uint32_t group_count_x = error_record[kValCmd_ErrorPayloadDword_0];
                const uint32_t limit = is_task_shader ? gpuav.phys_dev_ext_props.mesh_shader_props_ext.maxTaskWorkGroupCount[0]
                                                      : gpuav.phys_dev_ext_props.mesh_shader_props_ext.maxMeshWorkGroupCount[0];
                skip |= gpuav.LogError(vuid, objlist, loc_with_debug_region,
                                       "In draw %" PRIu32 ", VkDrawMeshTasksIndirectCommandEXT::groupCountX is %" PRIu32
                                       " which is greater than VkPhysicalDeviceMeshShaderPropertiesEXT::%s[0]"
                                       " (%" PRIu32 ").",
                                       draw_i, group_count_x, group_count_name, limit);
                break;
            }

            case kErrorSubCode_PreDraw_GroupCountY: {
                const char* vuid = is_task_shader ? "VUID-VkDrawMeshTasksIndirectCommandEXT-TaskEXT-07323"
                                                  : "VUID-VkDrawMeshTasksIndirectCommandEXT-TaskEXT-07327";
                const uint32_t group_count_y = error_record[kValCmd_ErrorPayloadDword_0];
                const uint32_t limit = is_task_shader ? gpuav.phys_dev_ext_props.mesh_shader_props_ext.maxTaskWorkGroupCount[1]
                                                      : gpuav.phys_dev_ext_props.mesh_shader_props_ext.maxMeshWorkGroupCount[1];
                skip |= gpuav.LogError(vuid, objlist, loc_with_debug_region,
                                       "In draw %" PRIu32 ", VkDrawMeshTasksIndirectCommandEXT::groupCountY is %" PRIu32
                                       " which is greater than VkPhysicalDeviceMeshShaderPropertiesEXT::%s[1]"
                                       " (%" PRIu32 ").",
                                       draw_i, group_count_y, group_count_name, limit);
                break;
            }

            case kErrorSubCode_PreDraw_GroupCountZ: {
                const char* vuid = is_task_shader ? "VUID-VkDrawMeshTasksIndirectCommandEXT-TaskEXT-07324"
                                                  : "VUID-VkDrawMeshTasksIndirectCommandEXT-TaskEXT-07328";
                const uint32_t group_count_z = error_record[kValCmd_ErrorPayloadDword_0];
                const uint32_t limit = is_task_shader ? gpuav.phys_dev_ext_props.mesh_shader_props_ext.maxTaskWorkGroupCount[2]
                                                      : gpuav.phys_dev_ext_props.mesh_shader_props_ext.maxMeshWorkGroupCount[2];
                skip |= gpuav.LogError(vuid, objlist, loc_with_debug_region,
                                       "In draw %" PRIu32 ", VkDrawMeshTasksIndirectCommandEXT::groupCountZ is %" PRIu32
                                       " which is greater than VkPhysicalDeviceMeshShaderPropertiesEXT::%s[2]"
                                       " (%" PRIu32 ").",
                                       draw_i, group_count_z, group_count_name, limit);
                break;
            }

            case kErrorSubCode_PreDraw_GroupCountTotal: {
                const char* vuid = is_task_shader ? "VUID-VkDrawMeshTasksIndirectCommandEXT-TaskEXT-07325"
                                                  : "VUID-VkDrawMeshTasksIndirectCommandEXT-TaskEXT-07329";
                const uint32_t group_count_total = error_record[kValCmd_ErrorPayloadDword_0];
                const uint32_t limit = is_task_shader ? gpuav.phys_dev_ext_props.mesh_shader_props_ext.maxTaskWorkGroupTotalCount
                                                      : gpuav.phys_dev_ext_props.mesh_shader_props_ext.maxMeshWorkGroupTotalCount;
                skip |= gpuav.LogError(vuid, objlist, loc_with_debug_region,
                                       "In draw %" PRIu32 ", size of VkDrawMeshTasksIndirectCommandEXT is %" PRIu32
                                       " which is greater than VkPhysicalDeviceMeshShaderPropertiesEXT::%s"
                                       " (%" PRIu32 ").",
                                       draw_i, group_count_total, group_count_total_name, limit);
                break;
            }

            default:
                assert(false);
                return skip;
        }

        return skip;
    };

    cb_state.AddCommandErrorLogger(loc, &last_bound, std::move(error_logger));
}

struct DrawIndexedIndirectIndexBufferShader {
    static size_t GetSpirvSize() { return validation_cmd_draw_indexed_indirect_index_buffer_comp_size * sizeof(uint32_t); }
    static const uint32_t* GetSpirv() { return validation_cmd_draw_indexed_indirect_index_buffer_comp; }

    glsl::DrawIndexedIndirectIndexBufferPushData push_constants{};
    valpipe::BoundStorageBuffer draw_buffer_binding = {glsl::kPreDrawBinding_IndirectBuffer};
    valpipe::BoundStorageBuffer count_buffer_binding = {glsl::kPreDrawBinding_CountBuffer};

    static std::vector<VkDescriptorSetLayoutBinding> GetDescriptorSetLayoutBindings() {
        return {{glsl::kPreDrawBinding_IndirectBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr},
                {glsl::kPreDrawBinding_CountBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr},
                {glsl::kPreDrawBinding_IndexBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr}};
    }

    std::vector<VkWriteDescriptorSet> GetDescriptorWrites() const {
        std::vector<VkWriteDescriptorSet> desc_writes(2);

        desc_writes[0] = vku::InitStructHelper();
        desc_writes[0].dstBinding = draw_buffer_binding.binding;
        desc_writes[0].dstArrayElement = 0;
        desc_writes[0].descriptorCount = 1;
        desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
        desc_writes[0].pBufferInfo = &draw_buffer_binding.info;

        desc_writes[1] = vku::InitStructHelper();
        desc_writes[1].dstBinding = count_buffer_binding.binding;
        desc_writes[1].dstArrayElement = 0;
        desc_writes[1].descriptorCount = 1;
        desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
        desc_writes[1].pBufferInfo = &count_buffer_binding.info;

        return desc_writes;
    }
};

struct SetupDrawCountDispatchIndirectShader {
    static size_t GetSpirvSize() { return validation_cmd_setup_draw_indexed_indirect_index_buffer_comp_size * sizeof(uint32_t); }
    static const uint32_t* GetSpirv() { return validation_cmd_setup_draw_indexed_indirect_index_buffer_comp; }

    glsl::DrawIndexedIndirectIndexBufferPushData push_constants{};
    valpipe::BoundStorageBuffer count_buffer_binding = {glsl::kPreDrawBinding_CountBuffer};
    valpipe::BoundStorageBuffer dispatch_indirect_buffer_binding = {glsl::kPreDrawBinding_DispatchIndirectBuffer};

    static std::vector<VkDescriptorSetLayoutBinding> GetDescriptorSetLayoutBindings() {
        std::vector<VkDescriptorSetLayoutBinding> bindings = {
            {glsl::kPreDrawBinding_CountBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr},
            {glsl::kPreDrawBinding_DispatchIndirectBuffer, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
             nullptr},
        };

        return bindings;
    }

    std::vector<VkWriteDescriptorSet> GetDescriptorWrites() const {
        std::vector<VkWriteDescriptorSet> desc_writes(2);

        desc_writes[0] = vku::InitStructHelper();
        desc_writes[0].dstBinding = count_buffer_binding.binding;
        desc_writes[0].dstArrayElement = 0;
        desc_writes[0].descriptorCount = 1;
        desc_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
        desc_writes[0].pBufferInfo = &count_buffer_binding.info;

        desc_writes[1] = vku::InitStructHelper();
        desc_writes[1].dstBinding = dispatch_indirect_buffer_binding.binding;
        desc_writes[1].dstArrayElement = 0;
        desc_writes[1].descriptorCount = 1;
        desc_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
        desc_writes[1].pBufferInfo = &dispatch_indirect_buffer_binding.info;

        return desc_writes;
    }
};

// Use "api_" prefix to make it clear which buffer/offset/etc we are talking about
// "api" helps to distinguish it is input from the user at the API level
void DrawIndexedIndirectIndexBuffer(Validator& gpuav, CommandBufferSubState& cb_state, const Location& loc,
                                    const LastBound& last_bound, VkBuffer api_buffer, VkDeviceSize api_offset, uint32_t api_stride,
                                    uint32_t api_draw_count, VkBuffer api_count_buffer, VkDeviceSize api_count_buffer_offset,
                                    const char* vuid) {
    if (!gpuav.gpuav_settings.validate_index_buffers) {
        return;
    }

    if (gpuav.modified_features.robustBufferAccess2) {
        return;
    }

    if (gpuav.enabled_features.pipelineRobustness && last_bound.pipeline_state) {
        const auto robustness_ci =
            vku::FindStructInPNextChain<VkPipelineRobustnessCreateInfo>(last_bound.pipeline_state->GraphicsCreateInfo().pNext);
        if (robustness_ci && robustness_ci->vertexInputs) {
            return;
        }
    }

    if (!cb_state.base.IsPrimary()) {
        // TODO Unhandled for now. Potential issues with accessing the right vertex buffers
        // in secondary command buffers
        return;
    }

    if (!cb_state.base.index_buffer_binding.HasNonNullBuffer()) {
        return;
    }

    ValidationCommandFunc validation_cmd = [index_buffer_binding = cb_state.base.index_buffer_binding, api_buffer, api_offset,
                                            api_stride, api_draw_count, api_count_buffer, api_count_buffer_offset,
                                            draw_i = cb_state.draw_index, error_logger_i = cb_state.GetErrorLoggerIndex(),
                                            loc](Validator& gpuav, CommandBufferSubState& cb_state) {
        SharedDrawValidationResources& shared_draw_validation_resources =
            gpuav.shared_resources_cache.GetOrCreate<SharedDrawValidationResources>(gpuav);
        if (!shared_draw_validation_resources.valid) {
            gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to create SharedDrawValidationResources.");
            return;
        }
        valpipe::ComputePipeline<SetupDrawCountDispatchIndirectShader>& setup_validation_dispatch_pipeline =
            gpuav.shared_resources_cache.GetOrCreate<valpipe::ComputePipeline<SetupDrawCountDispatchIndirectShader>>(gpuav, loc);
        if (!setup_validation_dispatch_pipeline.valid) {
            gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to create SetupDrawCountDispatchIndirectShader.");
            return;
        }
        ValidationCommandsGpuavState& val_cmd_gpuav_state =
            gpuav.shared_resources_cache.GetOrCreate<ValidationCommandsGpuavState>(gpuav, loc);
        valpipe::ComputePipeline<DrawIndexedIndirectIndexBufferShader>& validation_pipeline =
            gpuav.shared_resources_cache.GetOrCreate<valpipe::ComputePipeline<DrawIndexedIndirectIndexBufferShader>>(
                gpuav, loc, val_cmd_gpuav_state.error_logging_desc_set_layout_);
        if (!validation_pipeline.valid) {
            gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to create DrawIndexedIndirectIndexBufferShader.");
            return;
        }

        const uint32_t index_byte_size = IndexTypeByteSize(index_buffer_binding.index_type);
        const uint32_t max_indices_in_buffer = static_cast<uint32_t>(index_buffer_binding.size / index_byte_size);

        vko::BufferRange validation_dispatch_params_buffer_range =
            cb_state.gpu_resources_manager.GetDeviceLocalIndirectBufferRange(3 * sizeof(uint32_t));

        glsl::DrawIndexedIndirectIndexBufferPushData push_constants{};
        if (api_count_buffer != VK_NULL_HANDLE) {
            push_constants.flags |= glsl::kIndexedIndirectDrawFlags_DrawCountFromBuffer;
            push_constants.api_count_buffer_offset_dwords = uint32_t(api_count_buffer_offset / sizeof(uint32_t));
        }
        push_constants.api_stride_dwords = api_stride / sizeof(uint32_t);
        push_constants.bound_index_buffer_indices_count = max_indices_in_buffer;
        push_constants.api_draw_count = api_draw_count;
        push_constants.api_offset_dwords = uint32_t(api_offset / sizeof(uint32_t));

        // Draw count being stored in a GPU buffer,
        // setup a compute pipeline to determine the size of the validation indirect dispatch
        {
            SetupDrawCountDispatchIndirectShader setup_validation_shader_resources;
            setup_validation_shader_resources.push_constants = push_constants;
            if (api_count_buffer != VK_NULL_HANDLE) {
                setup_validation_shader_resources.count_buffer_binding.info = {api_count_buffer, 0, sizeof(uint32_t)};
            } else {
                setup_validation_shader_resources.count_buffer_binding.info = {
                    shared_draw_validation_resources.dummy_buffer.VkHandle(), 0, VK_WHOLE_SIZE};
            }

            setup_validation_shader_resources.dispatch_indirect_buffer_binding.info =
                validation_dispatch_params_buffer_range.GetDescriptorBufferInfo();

            if (!setup_validation_dispatch_pipeline.BindShaderResources(gpuav, cb_state, setup_validation_shader_resources)) {
                gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to GetManagedDescriptorSet in BindShaderResources");
                return;
            }

            DispatchCmdBindPipeline(cb_state.VkHandle(), VK_PIPELINE_BIND_POINT_COMPUTE,
                                    setup_validation_dispatch_pipeline.pipeline);

            // Sync indirect buffer writes - the same command buffer could be executed concurrently
            // for all we know
            {
                VkBufferMemoryBarrier barrier_write_after_read = vku::InitStructHelper();
                barrier_write_after_read.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
                barrier_write_after_read.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
                barrier_write_after_read.buffer = validation_dispatch_params_buffer_range.buffer;
                barrier_write_after_read.offset = validation_dispatch_params_buffer_range.offset;
                barrier_write_after_read.size = validation_dispatch_params_buffer_range.size;

                DispatchCmdPipelineBarrier(cb_state.VkHandle(), VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,
                                           VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, 1, &barrier_write_after_read, 0,
                                           nullptr);
            }

            DispatchCmdDispatch(cb_state.VkHandle(), 1, 1, 1);

            // Sync indirect buffer reads
            {
                VkBufferMemoryBarrier barrier_read_after_write = vku::InitStructHelper();
                barrier_read_after_write.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
                barrier_read_after_write.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
                barrier_read_after_write.buffer = validation_dispatch_params_buffer_range.buffer;
                barrier_read_after_write.offset = validation_dispatch_params_buffer_range.offset;
                barrier_read_after_write.size = validation_dispatch_params_buffer_range.size;

                DispatchCmdPipelineBarrier(cb_state.VkHandle(), VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
                                           VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0, 0, nullptr, 1, &barrier_read_after_write, 0,
                                           nullptr);
            }
        }

        // Setup validation pipeline
        {
            DrawIndexedIndirectIndexBufferShader validation_shader_resources;
            validation_shader_resources.push_constants = push_constants;
            if (api_count_buffer != VK_NULL_HANDLE) {
                validation_shader_resources.count_buffer_binding.info = {api_count_buffer, 0, sizeof(uint32_t)};
            } else {
                validation_shader_resources.count_buffer_binding.info = {shared_draw_validation_resources.dummy_buffer.VkHandle(),
                                                                         0, VK_WHOLE_SIZE};
            }
            validation_shader_resources.draw_buffer_binding.info = {api_buffer, 0, VK_WHOLE_SIZE};

            if (!BindShaderResources(validation_pipeline, gpuav, cb_state, draw_i, error_logger_i, validation_shader_resources)) {
                gpuav.InternalError(cb_state.VkHandle(), loc, "Failed to GetManagedDescriptorSet in BindShaderResources");
                return;
            }

            DispatchCmdBindPipeline(cb_state.VkHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, validation_pipeline.pipeline);

            // One draw will check all VkDrawIndexedIndirectCommand
            DispatchCmdDispatchIndirect(cb_state.VkHandle(), validation_dispatch_params_buffer_range.buffer,
                                        validation_dispatch_params_buffer_range.offset);
            // synchronize draw buffer validation (read) against subsequent writes
            std::array<VkBufferMemoryBarrier, 2> buffer_memory_barriers = {};
            uint32_t buffer_memory_barriers_count = 1;
            buffer_memory_barriers[0] = vku::InitStructHelper();
            buffer_memory_barriers[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
            buffer_memory_barriers[0].dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
            buffer_memory_barriers[0].buffer = api_buffer;
            buffer_memory_barriers[0].offset = api_offset;
            buffer_memory_barriers[0].size = VK_WHOLE_SIZE;

            if (api_count_buffer) {
                buffer_memory_barriers[1] = vku::InitStructHelper();
                buffer_memory_barriers[1].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
                buffer_memory_barriers[1].dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
                buffer_memory_barriers[1].buffer = api_count_buffer;
                buffer_memory_barriers[1].offset = api_count_buffer_offset;
                buffer_memory_barriers[1].size = sizeof(uint32_t);
                ++buffer_memory_barriers_count;
            }

            DispatchCmdPipelineBarrier(cb_state.VkHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
                                       VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, nullptr, buffer_memory_barriers_count,
                                       buffer_memory_barriers.data(), 0, nullptr);
        }
    };

    ValidationCmdCbState& val_cmd_cb_state = cb_state.shared_resources_cache.GetOrCreate<ValidationCmdCbState>();
    val_cmd_cb_state.per_render_pass_validation_commands.emplace_back(std::move(validation_cmd));

    ErrorLoggerFunc error_logger = [&gpuav, vuid, api_buffer, api_offset, api_stride,
                                    index_buffer_binding = cb_state.base.index_buffer_binding](
                                       const uint32_t* error_record, const Location& loc_with_debug_region,
                                       const LogObjectList& objlist) {
        bool skip = false;
        using namespace glsl;

        const uint32_t error_sub_code = GetSubError(error_record);
        switch (error_sub_code) {
            case kErrorSubCode_OobIndexBuffer: {
                const uint32_t draw_i = error_record[kValCmd_ErrorPayloadDword_0];
                const uint32_t first_index = error_record[kValCmd_ErrorPayloadDword_1];
                const uint32_t index_count = error_record[kValCmd_ErrorPayloadDword_2];
                const uint32_t highest_accessed_index = first_index + index_count;

                std::stringstream indirect_buffer_info;
                indirect_buffer_info << "VkDrawIndexedIndirectCommand buffer:\n";
                if (loc_with_debug_region.function == vvl::Func::vkCmdDrawIndexedIndirect2KHR) {
                    auto draw_buffer_state = gpuav.Get<vvl::Buffer>(api_buffer);
                    if (!draw_buffer_state) {
                        gpuav.InternalError(api_buffer, loc_with_debug_region,
                                            "Could not retrieve buffer state during error logging - most likely a GPU-AV bug.");
                        return skip;
                    }

                    indirect_buffer_info << "- Offset address: 0x" << std::hex << draw_buffer_state->deviceAddress + api_offset
                                         << '\n';
                } else {
                    indirect_buffer_info << "- Buffer: " << gpuav.FormatHandle(api_buffer) << '\n';
                    indirect_buffer_info << "- Buffer offset: " << api_offset << '\n';
                }
                indirect_buffer_info << "- Stride: " << api_stride << '\n';

                skip |= gpuav.LogError(vuid, objlist, loc_with_debug_region,
                                       "Index %" PRIu32
                                       " is not within the bound index buffer. Computed from VkDrawIndexedIndirectCommand[%" PRIu32
                                       "] (.firstIndex = %" PRIu32 ", .indexCount = %" PRIu32
                                       ")\n"

                                       "%s\n"

                                       "%s\n",

                                       // OOB index info
                                       highest_accessed_index, draw_i, first_index, index_count,

                                       // Draw parameters buffer
                                       indirect_buffer_info.str().c_str(),

                                       // Index buffer binding info
                                       index_buffer_binding.String(*gpuav.device_state).c_str());
                break;
            }

            default:
                assert(false);
                return skip;
        }

        return skip;
    };

    cb_state.AddCommandErrorLogger(loc, &last_bound, std::move(error_logger));
}

}  // namespace valcmd
}  // namespace gpuav
