/*
 * Copyright (c) 2023-2026 Valve Corporation
 * Copyright (c) 2023-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
 *
 */

#include "../framework/layer_validation_tests.h"
#include "../framework/shader_helper.h"

class PositiveDeviceQueue : public VkLayerTest {};

TEST_F(PositiveDeviceQueue, NoQueues) {
    SetTargetApiVersion(VK_API_VERSION_1_1);
    AddRequiredExtensions(VK_KHR_MAINTENANCE_9_EXTENSION_NAME);
    AddRequiredFeature(vkt::Feature::maintenance9);
    RETURN_IF_SKIP(InitFramework());

    VkDeviceCreateInfo device_ci = vku::InitStructHelper();
    device_ci.pNext = requested_features_.GetEnabledFeatures2();
    device_ci.enabledExtensionCount = static_cast<uint32_t>(m_device_extension_names.size());
    device_ci.ppEnabledExtensionNames = m_device_extension_names.data();

    vkt::Device device(gpu_, device_ci);

    VkShaderObj cs(device, kMinimalShaderGlsl, VK_SHADER_STAGE_COMPUTE_BIT);

    std::vector<VkDescriptorSetLayoutBinding> bindings(0);
    const vkt::DescriptorSetLayout pipeline_dsl(device, bindings);
    const vkt::PipelineLayout pipeline_layout(device, {&pipeline_dsl});

    VkComputePipelineCreateInfo compute_create_info = vku::InitStructHelper();
    compute_create_info.stage = cs.GetStageCreateInfo();
    compute_create_info.layout = pipeline_layout;

    VkPipeline pipeline;
    vk::CreateComputePipelines(device, VK_NULL_HANDLE, 1, &compute_create_info, nullptr, &pipeline);
    vk::DestroyPipeline(device, pipeline, nullptr);
}

TEST_F(PositiveDeviceQueue, QueueFamilyIndexDifferentCreateFlags) {
    SetTargetApiVersion(VK_API_VERSION_1_1);
    AddRequiredExtensions(VK_KHR_INTERNALLY_SYNCHRONIZED_QUEUES_EXTENSION_NAME);
    AddRequiredFeature(vkt::Feature::internallySynchronizedQueues);
    RETURN_IF_SKIP(InitFramework());

    bool found_queue = false;
    VkQueueFamilyProperties queue_properties;
    uint32_t queue_family_index = 0u;
    uint32_t queue_family_count = 0u;
    vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_family_count, nullptr);
    std::vector<VkQueueFamilyProperties> queue_families(queue_family_count);
    vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_family_count, queue_families.data());

    for (size_t i = 0; i < queue_families.size(); i++) {
        if (queue_families[i].queueCount > 1) {
            found_queue = true;
            queue_family_index = i;
            queue_properties = queue_families[i];
            break;
        }
    }

    if (found_queue == false) {
        GTEST_SKIP() << "test requires queue family with 2 queues, not available";
    }

    float queue_priority = 1.0f;
    VkDeviceQueueCreateInfo device_queue_ci[2];
    device_queue_ci[0] = vku::InitStructHelper();
    device_queue_ci[0].flags = 0u;
    device_queue_ci[0].queueFamilyIndex = queue_family_index;
    device_queue_ci[0].queueCount = 1u;
    device_queue_ci[0].pQueuePriorities = &queue_priority;
    device_queue_ci[1] = vku::InitStructHelper();
    device_queue_ci[1].flags = VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR;
    device_queue_ci[1].queueFamilyIndex = queue_family_index;
    device_queue_ci[1].queueCount = 1u;
    device_queue_ci[1].pQueuePriorities = &queue_priority;

    VkDevice test_device = VK_NULL_HANDLE;
    VkDeviceCreateInfo device_ci = vku::InitStructHelper();
    device_ci.pNext = requested_features_.GetEnabledFeatures2();
    device_ci.queueCreateInfoCount = 2u;
    device_ci.pQueueCreateInfos = device_queue_ci;
    device_ci.enabledExtensionCount = static_cast<uint32_t>(m_device_extension_names.size());
    device_ci.ppEnabledExtensionNames = m_device_extension_names.data();
    vk::CreateDevice(Gpu(), &device_ci, nullptr, &test_device);
    vk::DestroyDevice(test_device, nullptr);
}

TEST_F(PositiveDeviceQueue, MultipleQueuePerfHint) {
    TEST_DESCRIPTION("Test vkQueueSetPerfHintQCOM on all supported queues.");
    SetTargetApiVersion(VK_API_VERSION_1_3);
    AddRequiredExtensions(VK_QCOM_QUEUE_PERF_HINT_EXTENSION_NAME);
    AddRequiredFeature(vkt::Feature::queuePerfHint);
    RETURN_IF_SKIP(InitFramework());

    VkPhysicalDeviceQueuePerfHintPropertiesQCOM perf_hint_props = vku::InitStructHelper();
    GetPhysicalDeviceProperties2(perf_hint_props);
    const VkQueueFlags supported_queues = perf_hint_props.supportedQueues;

    uint32_t queue_family_count = 0;
    vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_family_count, nullptr);
    std::vector<VkQueueFamilyProperties> queue_family_props(queue_family_count);
    vk::GetPhysicalDeviceQueueFamilyProperties(Gpu(), &queue_family_count, queue_family_props.data());

    std::vector<uint32_t> supported_queue_ids{};
    for (uint32_t index = 0; index < queue_family_count; ++index) {
        if ((queue_family_props[index].queueFlags & supported_queues) != 0) {
            supported_queue_ids.push_back(index);
        }
    }
    if (supported_queue_ids.empty()) {
        GTEST_SKIP() << "Failed to find the queue family that supports queue perf-hint property, skipping test.";
    }

    RETURN_IF_SKIP(InitState());

    constexpr std::array<VkPerfHintTypeQCOM, 3> hint_types{
        VK_PERF_HINT_TYPE_FREQUENCY_SCALED_QCOM,
        VK_PERF_HINT_TYPE_DEFAULT_QCOM,
        VK_PERF_HINT_TYPE_FREQUENCY_MIN_QCOM,
    };

    uint32_t index = 0;
    for (const uint32_t family_id : supported_queue_ids) {
        VkQueue queue = VK_NULL_HANDLE;
        vk::GetDeviceQueue(device(), family_id, 0, &queue);

        VkPerfHintInfoQCOM perf_hint_info = vku::InitStructHelper();
        perf_hint_info.type = hint_types[index];
        perf_hint_info.scale = 0;

        if (hint_types[index] == VK_PERF_HINT_TYPE_FREQUENCY_SCALED_QCOM) {
            perf_hint_info.scale = 65;
        }

        vk::QueueSetPerfHintQCOM(queue, &perf_hint_info);

        ++index;
        index = index % hint_types.size();
    }
}
