// copyright (c) 2022 the android open source project
//
// 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 "VulkanTestHelper.h"

#include "host-common/emugl_vm_operations.h"
#include "host-common/feature_control.h"
#include "host-common/logging.h"
#include "host-common/vm_operations.h"

namespace gfxstream {
namespace vk {
namespace testing {
namespace {

using ::android::base::BumpPool;

bool validationErrorsFound = false;

// Called back by the Vulkan validation layer in case of a validation error
VKAPI_ATTR VkBool32 VKAPI_CALL validationCallback(
    VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type,
    const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) {
    if (severity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
        ERR("Validation Layer: \"%s\"", pCallbackData->pMessage);
        validationErrorsFound = true;
    }
    return VK_FALSE;
}

}  // namespace

std::mutex VulkanTestHelper::mMutex;

VulkanTestHelper::VulkanTestHelper()
    : mLock(mMutex),
      mVk(vkDispatch(/*forTesting=*/true)),
      mLogger(),
      mMetricsLogger(android::base::CreateMetricsLogger()),
      mHealthMonitor(*mMetricsLogger),
      mVkEmu(createGlobalVkEmulation(mVk)),
      mBp(std::make_unique<BumpPool>()),
      mDecoderContext(VkDecoderContext{.processName = "vulkan_test",
                                       .gfxApiLogger = &mLogger,
                                       .healthMonitor = &mHealthMonitor,
                                       .metricsLogger = mMetricsLogger.get()}),
      mTestDispatch(mVk, mBp.get(), &mDecoderContext) {
    // Enable so that we can have VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
    feature_set_enabled_override(kFeature_GLDirectMem, true);

    // This is used by VkDecoderGlobalState::on_vkCreateInstance()
    QAndroidVmOperations vmOps;
    vmOps.setSkipSnapshotSave = [](bool) {};
    set_emugl_vm_operations(vmOps);

    validationErrorsFound = false;
}

void VulkanTestHelper::destroy() {
    if (mDevice) {
        vk().vkDeviceWaitIdle(mDevice);
        if (mCommandPool) vk().vkDestroyCommandPool(mDevice, mCommandPool, nullptr);
        vk().vkDestroyDevice(mDevice, nullptr);
    }
    if (mInstance) {
        if (mDebugMessenger) {
            vk().vkDestroyDebugUtilsMessengerEXT(mInstance, mDebugMessenger, nullptr);
        }
        vk().vkDestroyInstance(mInstance, nullptr);
    }

    mCommandPool = VK_NULL_HANDLE;
    mDevice = VK_NULL_HANDLE;
    mInstance = VK_NULL_HANDLE;
    mDebugMessenger = VK_NULL_HANDLE;

    VkDecoderGlobalState::reset();
    teardownGlobalVkEmulation();
}

VulkanTestHelper::~VulkanTestHelper() {
    destroy();
    if (mFailOnValidationErrors && validationErrorsFound) {
        FATAL() << "Validation errors found. Aborting.";
    }
}

void VulkanTestHelper::initialize(const InitializationOptions& options) {
    initVkEmulationFeatures(std::make_unique<VkEmulationFeatures>(VkEmulationFeatures{
        .astcLdrEmulationMode = options.astcLdrEmulationMode,
    }));

    // Check that the validation layer is present
    const char* validationLayer = "VK_LAYER_KHRONOS_validation";
    uint32_t layerCount;
    vk().vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
    std::vector<VkLayerProperties> availableLayers(layerCount);
    vk().vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());

    bool layerFound = false;
    for (const auto& layerProperties : availableLayers) {
        if (strcmp(validationLayer, layerProperties.layerName) == 0) {
            layerFound = true;
            break;
        }
    }
    if (!layerFound) FATAL() << "Vulkan Validation Layer not found";

    // Create the instance
    VkApplicationInfo defaultAppInfo = {
        .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
        .pApplicationName = "vulkan_test",
        .pEngineName = "vulkan_test",
        .apiVersion = VK_API_VERSION_1_1,
    };

    VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = {
        .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
        .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
                           VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
                           VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
        .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
                       VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
                       VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
        .pfnUserCallback = validationCallback,
    };

    std::vector<const char*> extensions = {VK_EXT_DEBUG_UTILS_EXTENSION_NAME};
    for (const auto& extName : options.enabledExtensions) {
        extensions.push_back(extName.c_str());
    }

    VkInstanceCreateInfo createInfo = {
        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
        .pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo,
        .pApplicationInfo = options.appInfo ? &options.appInfo.value() : &defaultAppInfo,
        .enabledLayerCount = 1,
        .ppEnabledLayerNames = &validationLayer,
        .enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
        .ppEnabledExtensionNames = extensions.data(),
    };
    VK_CHECK(vk().vkCreateInstance(&createInfo, nullptr, &mInstance));

    // Setup validation layer callbacks
    VK_CHECK(vk().vkCreateDebugUtilsMessengerEXT(mInstance, &debugCreateInfo, nullptr,
                                                 &mDebugMessenger));

    // Pick a physical device
    uint32_t deviceCount = 0;
    vk().vkEnumeratePhysicalDevices(mInstance, &deviceCount, nullptr);
    if (deviceCount == 0) FATAL() << "No Vulkan device found.";
    std::vector<VkPhysicalDevice> devices(deviceCount);
    VK_CHECK(vk().vkEnumeratePhysicalDevices(mInstance, &deviceCount, devices.data()));

    mPhysicalDevice = devices[0];
    assert(mPhysicalDevice != VK_NULL_HANDLE);

    // Create the logical device
    float queuePriority = 1.0f;
    VkDeviceQueueCreateInfo queueCreateInfo = {
        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
        .queueFamilyIndex = getQueueFamilyIndex(VK_QUEUE_GRAPHICS_BIT),
        .queueCount = 1,
        .pQueuePriorities = &queuePriority,
    };

    VkDeviceCreateInfo deviceCreateInfo = {
        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
        .queueCreateInfoCount = 1,
        .pQueueCreateInfos = &queueCreateInfo,
        .enabledLayerCount = 1,
        .ppEnabledLayerNames = &validationLayer,
        .pEnabledFeatures = &options.deviceFeatures,
    };
    VK_CHECK(vk().vkCreateDevice(mPhysicalDevice, &deviceCreateInfo, nullptr, &mDevice));

    // Get a graphics queue
    vk().vkGetDeviceQueue(mDevice, queueCreateInfo.queueFamilyIndex, 0, &mGraphicsQueue);
    assert(mGraphicsQueue != VK_NULL_HANDLE);

    // Create command pool
    VkCommandPoolCreateInfo poolInfo{
        .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
        .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
        .queueFamilyIndex = queueCreateInfo.queueFamilyIndex,
    };
    VK_CHECK(vk().vkCreateCommandPool(mDevice, &poolInfo, nullptr, &mCommandPool));
}

bool VulkanTestHelper::hasValidationErrors() const { return validationErrorsFound; }

VkCommandBuffer VulkanTestHelper::beginCommandBuffer() {
    VkCommandBufferAllocateInfo allocInfo = {
        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
        .commandPool = unbox_VkCommandPool(mCommandPool),
        .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
        .commandBufferCount = 1,
    };
    VkCommandBuffer commandBuffer;
    vk().vkAllocateCommandBuffers(mDevice, &allocInfo, &commandBuffer);

    VkCommandBufferBeginInfo beginInfo = {
        .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
        .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
    };
    vk().vkBeginCommandBuffer(commandBuffer, &beginInfo);
    return commandBuffer;
}

void VulkanTestHelper::submitCommandBuffer(VkCommandBuffer commandBuffer) {
    vk().vkEndCommandBuffer(commandBuffer);
    auto cmdBuf = unbox_VkCommandBuffer(commandBuffer);

    VkSubmitInfo submitInfo = {
        .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
        .commandBufferCount = 1,
        .pCommandBuffers = &cmdBuf,
    };
    vk().vkQueueSubmit(mGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
    vk().vkQueueWaitIdle(mGraphicsQueue);
    vk().vkFreeCommandBuffers(mDevice, mCommandPool, 1, &cmdBuf);
}

uint32_t VulkanTestHelper::getQueueFamilyIndex(VkQueueFlagBits queueFlags) {
    uint32_t queueFamilyCount = 0;
    vk().vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueFamilyCount, nullptr);

    std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
    vk().vkGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueFamilyCount,
                                                  queueFamilies.data());
    for (uint32_t i = 0; i < static_cast<uint32_t>(queueFamilies.size()); i++) {
        if (queueFamilies[i].queueFlags & queueFlags) {
            return i;
        }
    }

    FATAL() << "No queue family found matching the requested flags";
}

uint32_t VulkanTestHelper::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties) {
    VkPhysicalDeviceMemoryProperties memProperties;
    vk().vkGetPhysicalDeviceMemoryProperties(mPhysicalDevice, &memProperties);

    for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
        if ((typeFilter & (1 << i)) &&
            (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
            return i;
        }
    }
    FATAL() << "failed to find suitable memory type!";
}

void VulkanTestHelper::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
                                    VkMemoryPropertyFlags properties, VkBuffer& buffer,
                                    VkDeviceMemory& bufferMemory) {
    VkBufferCreateInfo bufferInfo = {
        .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
        .size = size,
        .usage = usage,
        .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
    };
    VK_CHECK(vk().vkCreateBuffer(mDevice, &bufferInfo, nullptr, &buffer));

    VkMemoryRequirements memRequirements;
    vk().vkGetBufferMemoryRequirements(mDevice, buffer, &memRequirements);

    VkMemoryAllocateInfo allocInfo = {
        .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
        .allocationSize = memRequirements.size,
        .memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties),
    };
    VK_CHECK(vk().vkAllocateMemory(mDevice, &allocInfo, nullptr, &bufferMemory));

    vk().vkBindBufferMemory(mDevice, buffer, bufferMemory, 0);
}

void VulkanTestHelper::transitionImageLayout(VkCommandBuffer cmdBuf, VkImage image,
                                             VkImageLayout oldLayout, VkImageLayout newLayout) {
    VkImageMemoryBarrier barrier = {
        .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
        .oldLayout = oldLayout,
        .newLayout = newLayout,
        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
        .image = unbox_VkImage(image),
        .subresourceRange =
            {
                .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
                .baseMipLevel = 0,
                .levelCount = 1,
                .baseArrayLayer = 0,
                .layerCount = 1,
            },
    };

    switch (oldLayout) {
        case VK_IMAGE_LAYOUT_UNDEFINED:
            barrier.srcAccessMask = 0;
            break;
        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
            barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
            break;
        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
            barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
            break;
        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
            barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
            break;
        default:
            FATAL() << "Unsupported layout transition!";
    }

    switch (newLayout) {
        case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
            barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
            break;
        case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
            barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
            break;
        case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
            if (barrier.srcAccessMask == 0) {
                barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
            }
            barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
            break;
        default:
            FATAL() << "Unsupported layout transition!";
    }
    vk().vkCmdPipelineBarrier(cmdBuf, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                              VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, 1,
                              &barrier);
}

}  // namespace testing
}  // namespace vk
}  // namespace gfxstream
