/* Copyright (c) 2024-2026 The Khronos Group Inc.
 * Copyright (c) 2024-2026 Valve Corporation
 * Copyright (c) 2024-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 "sync/sync_reporting.h"
#include "sync/sync_validation.h"
#include "error_message/error_strings.h"
#include "utils/math_utils.h"

namespace syncval {

constexpr VkAccessFlags2 kAllAccesses = VK_ACCESS_2_MEMORY_READ_BIT | VK_ACCESS_2_MEMORY_WRITE_BIT;

static const char *string_SyncHazard(SyncHazard hazard) {
    switch (hazard) {
        case SyncHazard::NONE:
            return "NONE";
        case SyncHazard::READ_AFTER_WRITE:
            return "READ_AFTER_WRITE";
        case SyncHazard::WRITE_AFTER_READ:
            return "WRITE_AFTER_READ";
        case SyncHazard::WRITE_AFTER_WRITE:
            return "WRITE_AFTER_WRITE";
        case SyncHazard::READ_RACING_WRITE:
            return "READ_RACING_WRITE";
        case SyncHazard::WRITE_RACING_WRITE:
            return "WRITE_RACING_WRITE";
        case SyncHazard::WRITE_RACING_READ:
            return "WRITE_RACING_READ";
        case SyncHazard::READ_AFTER_PRESENT:
            return "READ_AFTER_PRESENT";
        case SyncHazard::WRITE_AFTER_PRESENT:
            return "WRITE_AFTER_PRESENT";
        case SyncHazard::PRESENT_AFTER_WRITE:
            return "PRESENT_AFTER_WRITE";
        case SyncHazard::PRESENT_AFTER_READ:
            return "PRESENT_AFTER_READ";
        default:
            assert(0);
            return "INVALID HAZARD";
    }
}

static bool IsHazardVsRead(SyncHazard hazard) {
    switch (hazard) {
        case SyncHazard::WRITE_AFTER_READ:
        case SyncHazard::WRITE_RACING_READ:
        case SyncHazard::PRESENT_AFTER_READ:
            return true;
        default:
            return false;
    }
}

static auto SortKeyValues(const std::vector<ReportProperties::NameValue> &name_values) {
    const std::vector<std::string> std_properties = {
        kPropertyMessageType,   kPropertyHazardType, kPropertyAccess,       kPropertyPriorAccess, kPropertyReadBarriers,
        kPropertyWriteBarriers, kPropertyCommand,    kPropertyPriorCommand, kPropertyDebugRegion, kPropertyPriorDebugRegion};
    const uint32_t other_properties_order = uint32_t(std_properties.size());
    const uint32_t debug_properties_order = other_properties_order + 1;

    auto get_sort_order = [&](const std::string &key) -> uint32_t {
        // at first put standard properties
        auto std_it = std::find(std_properties.begin(), std_properties.end(), key);
        if (std_it != std_properties.end()) {
            const uint32_t std_order = uint32_t(&*std_it - std_properties.data());
            return std_order;
        }
        // debug properties are at the end
        const char *debug_properties[] = {kPropertySeqNo, kPropertyResetNo, kPropertyBatchTag};
        if (IsValueIn(key, debug_properties)) {
            return debug_properties_order;
        }
        return other_properties_order;
    };
    auto sorted = name_values;
    std::stable_sort(sorted.begin(), sorted.end(), [&get_sort_order](const auto &a, const auto &b) {
        const uint32_t a_order = get_sort_order(a.name);
        const uint32_t b_order = get_sort_order(b.name);
        // Sort ordering groups
        if (a_order != b_order) {
            return a_order < b_order;
        }
        // Do not rearrange elements within a group. By returning false we indicate neither element
        // in the group is less than the other one. Stable sort will keep the original order.
        return false;
    });
    return sorted;
}

static std::string FormatAccessProperty(const SyncAccessInfo &access) {
    constexpr std::array special_accesses = {SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_ACQUIRE_READ_SYNCVAL,
                                             SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_PRESENTED_SYNCVAL, SYNC_IMAGE_LAYOUT_TRANSITION,
                                             SYNC_QUEUE_FAMILY_OWNERSHIP_TRANSFER};
    if (IsValueIn(access.access_index, special_accesses)) {
        // Print internal name for accesses that don't have corresponding Vulkan constants
        return access.name;
    }
    std::ostringstream ss;
    ss << string_VkPipelineStageFlagBits2(access.stage_mask);
    ss << "(";
    ss << string_VkAccessFlagBits2(access.access_mask);
    ss << ")";
    return ss.str();
}

static void GetAccessProperties(const HazardResult &hazard_result, const SyncValidator &device, VkQueueFlags allowed_queue_flags,
                                ReportProperties &properties) {
    const HazardResult::HazardState &hazard = hazard_result.State();
    const SyncAccessInfo &access_info = GetAccessInfo(hazard.access_index);
    const SyncAccessInfo &prior_access_info = GetAccessInfo(hazard.prior_access_index);

    if (!hazard.recorded_access.get()) {
        properties.Add(kPropertyAccess, FormatAccessProperty(access_info));
    }
    properties.Add(kPropertyPriorAccess, FormatAccessProperty(prior_access_info));

    if (IsHazardVsRead(hazard.hazard)) {
        const VkPipelineStageFlags2 barriers = hazard.access_state->GetReadBarriers(hazard.prior_access_index);
        const std::string barriers_str = string_VkPipelineStageFlags2(barriers);
        properties.Add(kPropertyReadBarriers, barriers ? barriers_str : "0");
    } else {
        const SyncAccessFlags barriers = hazard.access_state->GetWriteBarriers();
        const std::string property_barriers_str = FormatSyncAccesses(barriers, device, allowed_queue_flags, true);
        properties.Add(kPropertyWriteBarriers, property_barriers_str);
    }
}

static void GetPriorUsageProperties(const ResourceUsageInfo &prior_usage_info, ReportProperties &properties) {
    properties.Add(kPropertyPriorCommand, vvl::String(prior_usage_info.command));

    if (!prior_usage_info.debug_region_name.empty()) {
        properties.Add(kPropertyPriorDebugRegion, prior_usage_info.debug_region_name);
    }

    // These commands are not recorded/submitted, so the rest of the properties are not applicable.
    // TODO: we can track command seq number.
    if (IsValueIn(prior_usage_info.command,
                  {vvl::Func::vkQueuePresentKHR, vvl::Func::vkAcquireNextImageKHR, vvl::Func::vkAcquireNextImage2KHR})) {
        return;
    }
    properties.Add(kPropertySeqNo, prior_usage_info.command_seq);
    properties.Add(kPropertyResetNo, prior_usage_info.command_buffer_reset_count);
    if (prior_usage_info.queue) {
        properties.Add(kPropertyBatchTag, prior_usage_info.batch_base_tag);
        properties.Add(kPropertySubmitIndex, prior_usage_info.submit_index);
        properties.Add(kPropertyBatchIndex, prior_usage_info.batch_index);
    }
}

static VkPipelineStageFlags2 GetAllowedStages(VkQueueFlags queue_flags, VkPipelineStageFlagBits2 disabled_stages) {
    VkPipelineStageFlags2 allowed_stages = 0;
    for (const auto &[queue_flag, stages] : syncAllCommandStagesByQueueFlags()) {
        if (queue_flag & queue_flags) {
            allowed_stages |= (stages & ~disabled_stages);
        }
    }
    return allowed_stages;
}

static SyncAccessFlags FilterSyncAccessesByAllowedVkStages(const SyncAccessFlags &accesses, VkPipelineStageFlags2 allowed_stages,
                                                           VkAccessFlags2 disabled_accesses) {
    SyncAccessFlags filtered_accesses = accesses;
    const auto &access_infos = GetSyncAccessInfos();
    for (size_t i = 0; i < access_infos.size(); i++) {
        const SyncAccessInfo &access_info = access_infos[i];
        const bool is_stage_allowed = (access_info.stage_mask & allowed_stages) != 0;
        const bool is_access_allowed = (access_info.access_mask & disabled_accesses) == 0;
        if (!is_stage_allowed || !is_access_allowed) {
            filtered_accesses.reset(i);
        }
    }
    return filtered_accesses;
}

static SyncAccessFlags FilterSyncAccessesByAllowedVkAccesses(const SyncAccessFlags &accesses, VkAccessFlags2 allowed_vk_accesses) {
    SyncAccessFlags filtered_accesses = accesses;
    const auto &access_infos = GetSyncAccessInfos();
    for (size_t i = 0; i < access_infos.size(); i++) {
        const SyncAccessInfo &access_info = access_infos[i];
        if (filtered_accesses[i]) {
            const bool is_access_allowed = (access_info.access_mask & allowed_vk_accesses) != 0;
            if (!is_access_allowed) {
                filtered_accesses.reset(i);
            }
        }
    }
    return filtered_accesses;
}

// If mask contains ALL of expand_bits, then clear these bits and add a meta_mask
static void ReplaceExpandBitsWithMetaMask(VkFlags64 &mask, VkFlags64 expand_bits, VkFlags64 meta_mask) {
    if (expand_bits && (mask & expand_bits) == expand_bits) {
        mask &= ~expand_bits;
        mask |= meta_mask;
    }
}

static std::vector<std::pair<VkPipelineStageFlags2, VkAccessFlags2>> ConvertSyncAccessesToCompactVkForm(
    const SyncAccessFlags &sync_accesses, const SyncValidator &device, VkQueueFlags allowed_queue_flags) {
    if (sync_accesses.none()) {
        return {};
    }

    const VkPipelineStageFlags2 disabled_stages = sync_utils::DisabledPipelineStages(device.enabled_features, device.extensions);
    const VkPipelineStageFlags2 all_transfer_expand_bits = kAllTransferExpandBits & ~disabled_stages;

    const VkAccessFlags2 disabled_accesses = sync_utils::DisabledAccesses(device.extensions);
    const VkAccessFlags2 all_shader_read_bits = kShaderReadExpandBits & ~disabled_accesses;

    // Build stage -> accesses mapping. OR-merge accesses that happen on the same stage.
    // Also handle ALL_COMMANDS accesses.
    vvl::unordered_map<VkPipelineStageFlagBits2, VkAccessFlags2> stage_to_accesses;
    {
        const VkPipelineStageFlags2 allowed_stages = GetAllowedStages(allowed_queue_flags, disabled_stages);
        const SyncAccessFlags filtered_accesses =
            FilterSyncAccessesByAllowedVkStages(sync_accesses, allowed_stages, disabled_accesses);

        const SyncAccessFlags all_reads =
            FilterSyncAccessesByAllowedVkStages(syncAccessReadMask, allowed_stages, disabled_accesses);
        const SyncAccessFlags all_shader_reads = FilterSyncAccessesByAllowedVkAccesses(all_reads, kShaderReadExpandBits);

        const SyncAccessFlags all_writes =
            FilterSyncAccessesByAllowedVkStages(syncAccessWriteMask, allowed_stages, disabled_accesses);
        const SyncAccessFlags all_shader_writes = FilterSyncAccessesByAllowedVkAccesses(all_writes, kShaderWriteExpandBits);

        if (filtered_accesses == all_reads) {
            stage_to_accesses[VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT] = VK_ACCESS_2_MEMORY_READ_BIT;
        } else if (filtered_accesses == all_shader_reads) {
            stage_to_accesses[VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT] = VK_ACCESS_2_SHADER_READ_BIT;
        } else if (filtered_accesses == all_shader_writes) {
            stage_to_accesses[VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT] = VK_ACCESS_2_SHADER_WRITE_BIT;
        } else {
            for (size_t i = 0; i < filtered_accesses.size(); i++) {
                if (filtered_accesses[i]) {
                    const SyncAccessInfo &info = GetSyncAccessInfos()[i];
                    stage_to_accesses[info.stage_mask] |= info.access_mask;
                }
            }
        }
    }

    // Build accesses -> stages mapping. OR-merge stages that share the same accesses
    vvl::unordered_map<VkAccessFlags2, VkPipelineStageFlags2> accesses_to_stages;
    for (const auto [stage, accesses] : stage_to_accesses) {
        accesses_to_stages[accesses] |= stage;
    }

    // Replace sequences of stages/accesses with more compact equivalent meta values where possible
    std::vector<std::pair<VkPipelineStageFlags2, VkAccessFlags2>> result;
    VkPipelineStageFlags2 stages_with_all_supported_accesses = 0;
    VkAccessFlags2 all_accesses = 0;  // accesses for the above stages

    for (const auto &entry : accesses_to_stages) {
        VkAccessFlags2 accesses = entry.first;
        VkPipelineStageFlags2 stages = entry.second;

        VkAccessFlags2 all_accesses_supported_by_stages = sync_utils::CompatibleAccessMask(stages);
        {
            // Remove meta stages.
            // TODO: revisit CompatibleAccessMask helper. SyncVal works with expanded representation.
            // Meta stages are needed for core checks in this case, update function so serve both purposes well.
            all_accesses_supported_by_stages &= ~VK_ACCESS_2_SHADER_READ_BIT;
            all_accesses_supported_by_stages &= ~VK_ACCESS_2_SHADER_WRITE_BIT;
            // Remove unsupported accesses, otherwise the access mask won't be detected as the one that covers ALL accesses
            // TODO: ideally this should be integrated into utilities logic (need to revisit all use cases)
            if (!IsExtEnabled(device.extensions.vk_ext_blend_operation_advanced)) {
                all_accesses_supported_by_stages &= ~VK_ACCESS_2_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT;
            }
        }

        // Check if ALL supported accesses for the given stage are used.
        // This is an opportunity to use a compact message form.
        if (accesses == all_accesses_supported_by_stages) {
            stages_with_all_supported_accesses |= stages;
            all_accesses |= all_accesses_supported_by_stages;
            continue;
        }

        ReplaceExpandBitsWithMetaMask(stages, all_transfer_expand_bits, VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT);

        const VkAccessFlags2 all_shader_reads_supported_by_stages = all_shader_read_bits & all_accesses_supported_by_stages;
        ReplaceExpandBitsWithMetaMask(accesses, all_shader_reads_supported_by_stages, VK_ACCESS_2_SHADER_READ_BIT);
        result.emplace_back(stages, accesses);
    }
    if (stages_with_all_supported_accesses) {
        if (IsSingleBitSet(stages_with_all_supported_accesses) && GetBitSetCount(all_accesses) <= 2) {
            // For simple configurations (1 stage and at most 2 accesses) don't use ALL accesses shortcut
            result.emplace_back(stages_with_all_supported_accesses, all_accesses);
        } else {
            ReplaceExpandBitsWithMetaMask(stages_with_all_supported_accesses, all_transfer_expand_bits,
                                          VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT);
            result.emplace_back(stages_with_all_supported_accesses, kAllAccesses);
        }
    }
    return result;
}

// Given that access is hazardous, we check if at least stage or access part of it is covered
// by the synchronization. If applied synchronization covers at least stage or access component
// then we can provide more precise message by focusing on the other component.
static std::pair<bool, bool> GetPartialProtectedInfo(const SyncAccessInfo &access, const SyncAccessFlags &write_barriers,
                                                     const CommandExecutionContext &context) {
    const auto protected_stage_access_pairs =
        ConvertSyncAccessesToCompactVkForm(write_barriers, context.GetSyncState(), context.GetQueueFlags());
    bool is_stage_protected = false;
    bool is_access_protected = false;
    for (const auto &protected_stage_access : protected_stage_access_pairs) {
        if (protected_stage_access.first & access.stage_mask) {
            is_stage_protected = true;
        }
        if (protected_stage_access.second & access.access_mask) {
            is_access_protected = true;
        }
    }
    return std::make_pair(is_stage_protected, is_access_protected);
}

static void ReportLayoutTransitionSynchronizationInsight(std::ostringstream &ss, bool needs_execution_dependency,
                                                         VkPipelineStageFlags2 read_barriers = 0) {
    // TODO: analyse exact form of API is used (render pass layout transition, image barrier layout transition) and
    // print instructions for specific situation. Now we describe all possibilities.
    const std::string barrier_src_stage = string_VkPipelineStageFlags2(read_barriers);
    if (needs_execution_dependency) {
        ss << "\nVulkan insight: If the layout transition is done via an image barrier, consider including " << barrier_src_stage
           << " in srcStageMask. If the transition occurs as part of the render pass begin operation, consider specifying an "
              "external subpass dependency (VK_SUBPASS_EXTERNAL) with srcStageMask that includes "
           << barrier_src_stage << ", or perform the transition in a separate image barrier before the render pass begins.";
    } else {
        ss << "\nVulkan insight: If the layout transition is done via an image barrier, ensure srcStageMask and srcAccessMask "
              "synchronize with the accesses mentioned above. If the transition occurs as part of the render pass begin operation, "
              "consider specifying an external subpass dependency (VK_SUBPASS_EXTERNAL) with srcStageMask and srcAccessMask that "
              "synchronize with those accesses, or perform the transition in a separate image barrier before the render pass "
              "begins.";
    }
}

static void ReportAcquireImageSynchronizationInsight(std::ostringstream &ss) {
    ss << "\nVulkan insight: If a submit command waits on a semaphore signaled by AcquireNextImage command at specific pipeline "
          "stages, this error can occur if the layout transition barrier does not create an execution dependency with those stages "
          "(for example, by including them in the barrier's srcStageMask).";
}

void ReportProperties::Add(std::string_view property_name, std::string_view value) {
    name_values.emplace_back(NameValue{std::string(property_name), std::string(value)});
}

void ReportProperties::Add(std::string_view property_name, uint64_t value) {
    name_values.emplace_back(NameValue{std::string(property_name), std::to_string(value)});
}

std::string ReportProperties::FormatExtraPropertiesSection() const {
    if (name_values.empty()) {
        return {};
    }
    const auto sorted = SortKeyValues(name_values);
    std::ostringstream ss;
    ss << "[Extra properties]\n";
    bool first = true;
    for (const NameValue &property : sorted) {
        if (!first) {
            ss << "\n";
        }
        first = false;
        ss << property.name << " = " << property.value;
    }
    return ss.str();
}

ReportProperties GetErrorMessageProperties(const HazardResult &hazard, const CommandExecutionContext &context, vvl::Func command,
                                           const char *message_type, const AdditionalMessageInfo &additional_info) {
    ReportProperties properties;
    properties.Add(kPropertyMessageType, message_type);
    properties.Add(kPropertyHazardType, string_SyncHazard(hazard.Hazard()));
    properties.Add(kPropertyCommand, vvl::String(command));

    GetAccessProperties(hazard, context.GetSyncState(), context.GetQueueFlags(), properties);

    if (hazard.Tag() != kInvalidTag) {
        ResourceUsageInfo prior_usage_info = context.GetResourceUsageInfo(hazard.TagEx());
        GetPriorUsageProperties(prior_usage_info, properties);
    }
    for (const auto &property : additional_info.properties.name_values) {
        properties.Add(property.name, property.value);
    }
    return properties;
}

std::string FormatErrorMessage(const HazardResult &hazard, const CommandExecutionContext &context, vvl::Func command,
                               const std::string &resouce_description, const AdditionalMessageInfo &additional_info) {
    const SyncHazard hazard_type = hazard.Hazard();
    const SyncHazardInfo hazard_info = GetSyncHazardInfo(hazard_type);

    const SyncAccessInfo &access = GetAccessInfo(hazard.State().access_index);
    const SyncAccessInfo &prior_access = GetAccessInfo(hazard.State().prior_access_index);

    const SyncAccessFlags write_barriers = hazard.State().access_state->GetWriteBarriers();
    VkPipelineStageFlags2 read_barriers = hazard.State().access_state->GetReadBarriers(hazard.State().prior_access_index);

    // TODO: BOTTOM_OF_PIPE part will go away when syncval switches internally to use NONE/ALL for everything.
    // Remove this block then.
    if (read_barriers & VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT) {
        read_barriers &= ~VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
    }

    const bool missing_synchronization = (hazard_info.IsPriorWrite() && write_barriers.none()) ||
                                         (hazard_info.IsPriorRead() && read_barriers == VK_PIPELINE_STAGE_2_NONE);

    std::ostringstream ss;

    // Brief description of what happened
    ss << string_SyncHazard(hazard_type) << " hazard detected";
    if (!additional_info.hazard_overview.empty()) {
        ss << ": " << additional_info.hazard_overview;
    }
    ss << ". ";
    ss << (additional_info.access_initiator.empty() ? vvl::String(command) : additional_info.access_initiator);
    ss << " ";
    if (!additional_info.access_action.empty()) {
        ss << additional_info.access_action;
    } else {
        ss << (hazard_info.IsWrite() ? "writes to" : "reads");
    }
    ss << " " << resouce_description << ", which was previously ";
    if (prior_access.access_index == SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_ACQUIRE_READ_SYNCVAL) {
        ss << "accessed by ";
    } else if (hazard_info.IsPriorWrite()) {
        if (prior_access.access_index == SYNC_IMAGE_LAYOUT_TRANSITION) {
            ss << "written during an image layout transition initiated by ";
        } else {
            ss << "written by ";
        }
    } else {
        ss << "read by ";
    }
    if (hazard.Tag() == kInvalidTag) {
        // Invalid tag for prior access means the same command performed ILT before loadOp access
        ss << "the same command";
    } else {
        const ResourceUsageInfo prior_usage_info = context.GetResourceUsageInfo(hazard.TagEx());
        if (prior_usage_info.command == command) {
            ss << "another ";
        }
        ss << vvl::String(prior_usage_info.command);
        if (!prior_usage_info.debug_region_name.empty()) {
            ss << "[" << prior_usage_info.debug_region_name << "]";
        }
        if (prior_usage_info.command == command) {
            ss << " command";
        }
    }
    if (!additional_info.brief_description_end_text.empty()) {
        ss << " " << additional_info.brief_description_end_text;
    }
    ss << ". ";

    // Additional information before synchronization section.
    if (!additional_info.pre_synchronization_text.empty()) {
        ss << additional_info.pre_synchronization_text;
    }

    // Synchronization information
    ss << "\n";
    if (missing_synchronization) {
        const char *access_type = hazard_info.IsWrite() ? "write" : "read";
        const char *prior_access_type = hazard_info.IsPriorWrite() ? "write" : "read";

        auto get_special_access_name = [](SyncAccessIndex access) -> const char * {
            if (access == SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_ACQUIRE_READ_SYNCVAL) {
                return "swapchain image acquire operation";
            } else if (access == SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_PRESENTED_SYNCVAL) {
                return "swapchain present operation";
            } else if (access == SYNC_IMAGE_LAYOUT_TRANSITION) {
                return "layout transition";
            } else if (access == SYNC_QUEUE_FAMILY_OWNERSHIP_TRANSFER) {
                return "ownership transfer";
            }
            return nullptr;
        };

        ss << "No sufficient synchronization is present to ensure that a ";
        if (const char *special_access_name = get_special_access_name(access.access_index)) {
            ss << special_access_name;
        } else {
            assert(access.access_mask != VK_ACCESS_2_NONE);
            assert(access.stage_mask != VK_PIPELINE_STAGE_2_NONE);
            ss << access_type << " (" << string_VkAccessFlagBits2(access.access_mask) << ") at ";
            ss << string_VkPipelineStageFlagBits2(access.stage_mask);
        }

        ss << " does not conflict with a prior ";
        if (const char *special_access_name = get_special_access_name(prior_access.access_index)) {
            ss << special_access_name;
        } else {
            assert(prior_access.access_mask != VK_ACCESS_2_NONE);
            assert(prior_access.stage_mask != VK_PIPELINE_STAGE_2_NONE);
            ss << prior_access_type;
            if (prior_access.access_mask != access.access_mask) {
                ss << " (" << string_VkAccessFlags2(prior_access.access_mask) << ")";
            } else {
                ss << " of the same type";
            }
            ss << " at ";
            if (prior_access.stage_mask == access.stage_mask) {
                ss << "the same stage";
            } else {
                ss << string_VkPipelineStageFlagBits2(prior_access.stage_mask);
            }
        }
        ss << ".";
    } else if (hazard_info.IsPriorWrite()) {  // RAW/WAW hazards
        ss << "The current synchronization allows ";
        ss << FormatSyncAccesses(write_barriers, context.GetSyncState(), context.GetQueueFlags(), false);
        auto [is_stage_protected, is_access_protected] = GetPartialProtectedInfo(access, write_barriers, context);
        if (is_access_protected) {
            ss << ", but to prevent this hazard, it must allow these accesses at ";
            ss << string_VkPipelineStageFlagBits2(access.stage_mask) << ".";
        } else if (access.access_mask != VK_ACCESS_2_NONE) {
            ss << ", but to prevent this hazard, it must allow ";
            ss << string_VkAccessFlagBits2(access.access_mask) << " accesses at ";
            ss << string_VkPipelineStageFlagBits2(access.stage_mask) << ".";
        } else {
            ss << ", but layout transition does synchronize with these accesses.";
            ReportLayoutTransitionSynchronizationInsight(ss, false);
        }
    } else {  // WAR hazard
        ss << "The current synchronization defines the destination stage mask as ";
        ss << string_VkPipelineStageFlags2(read_barriers);
        if (access.access_mask != VK_ACCESS_2_NONE) {
            ss << ", but to prevent this hazard, it must include ";
            ss << string_VkPipelineStageFlagBits2(access.stage_mask) << ".";
        } else {
            ss << ", but layout transition does not synchronize with these stages.";
            if (prior_access.access_index == SYNC_PRESENT_ENGINE_SYNCVAL_PRESENT_ACQUIRE_READ_SYNCVAL) {
                ReportAcquireImageSynchronizationInsight(ss);
            }
            ReportLayoutTransitionSynchronizationInsight(ss, true, read_barriers);
        }
    }

    // Give a hint for WAR hazard
    if (IsValueIn(hazard_type, {WRITE_AFTER_READ, WRITE_RACING_READ, PRESENT_AFTER_READ})) {
        ss << "\nVulkan insight: An execution dependency is sufficient to prevent this hazard.";
    }

    if (!additional_info.message_end_text.empty()) {
        ss << additional_info.message_end_text;
    }
    return ss.str();
}

std::string FormatSyncAccesses(const SyncAccessFlags &sync_accesses, const SyncValidator &device, VkQueueFlags allowed_queue_flags,
                               bool format_as_extra_property) {
    const auto report_accesses = ConvertSyncAccessesToCompactVkForm(sync_accesses, device, allowed_queue_flags);
    if (report_accesses.empty()) {
        return "0";
    }
    std::ostringstream out;
    bool first = true;
    for (const auto &[stages, accesses] : report_accesses) {
        if (!first) {
            out << (format_as_extra_property ? ":" : ", ");
        }
        if (format_as_extra_property) {
            if (accesses == kAllAccesses) {
                out << string_VkPipelineStageFlags2(stages) << "(ALL_ACCESSES)";
            } else {
                out << string_VkPipelineStageFlags2(stages) << "(" << string_VkAccessFlags2(accesses) << ")";
            }
        } else {
            if (accesses == kAllAccesses) {
                out << "all accesses at " << string_VkPipelineStageFlags2(stages);
            } else {
                out << string_VkAccessFlags2(accesses) << " accesses at " << string_VkPipelineStageFlags2(stages);
            }
        }
        first = false;
    }
    return out.str();
}

void FormatVideoPictureResouce(const Logger &logger, const VkVideoPictureResourceInfoKHR &video_picture, std::ostringstream &ss) {
    ss << "{";
    ss << logger.FormatHandle(video_picture.imageViewBinding);
    ss << ", codedOffset (" << string_VkOffset2D(video_picture.codedOffset) << ")";
    ss << ", codedExtent (" << string_VkExtent2D(video_picture.codedExtent) << ")";
    ss << ", baseArrayLayer = " << video_picture.baseArrayLayer;
    ss << "}";
}

void FormatVideoQuantizationMap(const Logger &logger, const VkVideoEncodeQuantizationMapInfoKHR &quantization_map,
                                std::ostringstream &ss) {
    ss << "{";
    ss << logger.FormatHandle(quantization_map.quantizationMap);
    ss << ", quantizationMapExtent (" << string_VkExtent2D(quantization_map.quantizationMapExtent) << ")";
    ss << "}";
}

static ResourceUsageInfo GetResourceUsageInfoFromRecord(ResourceUsageTagEx tag_ex, const ResourceUsageRecord &record,
                                                        const DebugNameProvider *debug_name_provider) {
    ResourceUsageInfo info;
    if (record.alt_usage) {
        info.command = record.alt_usage.GetCommand();
    } else {
        info.command = record.command;
        info.command_seq = record.seq_num;
        info.command_buffer_reset_count = record.reset_count;

        // Associated resource
        if (tag_ex.handle_index != vvl::kNoIndex32) {
            auto &cb_context = SubState(*record.cb_state);
            const auto &handle_records = cb_context.access_context.GetHandleRecords();

            // Command buffer can be in inconsistent state due to unhandled core validation error (core validation is disabled).
            // In this case the goal is not to crash, no guarantees that reported information (handle index) makes sense.
            const bool valid_handle_index = tag_ex.handle_index < handle_records.size();
            if (valid_handle_index) {
                info.resource_handle = handle_records[tag_ex.handle_index].TypedHandle();
                // TODO: also extract optional index or get rid of index
            }
        }
        // Debug region name. Empty name means that we are not inside any debug region.
        if (debug_name_provider) {
            info.debug_region_name = debug_name_provider->GetDebugRegionName(record);
        }
    }
    info.cb = record.cb_state;
    return info;
}

ResourceUsageInfo CommandBufferAccessContext::GetResourceUsageInfo(ResourceUsageTagEx tag_ex) const {
    const ResourceUsageRecord &record = (*access_log_)[tag_ex.tag];
    const auto debug_name_provider = (record.label_command_index == vvl::kNoIndex32) ? nullptr : this;
    return GetResourceUsageInfoFromRecord(tag_ex, record, debug_name_provider);
}

ResourceUsageInfo QueueBatchContext::GetResourceUsageInfo(ResourceUsageTagEx tag_ex) const {
    BatchAccessLog::AccessRecord access = batch_log_.GetAccessRecord(tag_ex.tag);
    if (!access.IsValid()) {
        return {};
    }
    const ResourceUsageRecord &record = *access.record;
    ResourceUsageInfo info = GetResourceUsageInfoFromRecord(tag_ex, record, access.debug_name_provider);

    const BatchAccessLog::BatchRecord &batch = *access.batch;
    if (batch.queue) {
        info.queue = batch.queue->GetQueueState();
        info.submit_index = batch.submit_index;
        info.batch_index = batch.batch_index;
        info.batch_base_tag = batch.base_tag;
    }
    return info;
}

}  // namespace syncval
