/*
*
* Vulkan hardware capability viewer
*
* Device information class
*
* Copyright (C) 2016-2025 by Sascha Willems (www.saschawillems.de)
*
* This code is free software, you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 3 as published by the Free Software Foundation.
*
* Please review the following information to ensure the GNU Lesser
* General Public License version 3 requirements will be met:
* http://opensource.org/licenses/lgpl-3.0.html
*
* The code is distributed WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE.  See the GNU LGPL 3.0 for more details.
*
*/

#ifndef VULKANDEVICEINFO_H
#define VULKANDEVICEINFO_H

#include <vector>
#include <assert.h>
#include <string>
#include <unordered_map>
#include <map>
#include <list>
#include <iostream>
#include <fstream>
#include <utility>

#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QFile>
#include <QDebug>

#include "vulkan/vulkan.h"
#include "vulkanResources.h"
#include "vulkanDeviceInfoExtensions.h"
#include "vulkanContext.h"

#ifdef __ANDROID__
#include <sys/system_properties.h>
#endif

#include "vulkanAndroid.h"
#if !defined(DISABLE_PROFILES)
#include "vulkan_profiles.hpp"
#endif

struct OSInfo
{
    std::string name;
    std::string version;
    std::string architecture;
    int32_t type{ -1 };
};

struct VulkanQueueFamilyInfo
{
    VkQueueFamilyProperties properties;
    VkBool32 supportsPresent;
};

struct VulkanProfileInfo
{
    std::string profileName;
    uint32_t specVersion;
    bool supported = false;
};

struct VulkanLayerInfo
{
    VkLayerProperties properties;
    std::vector<VkExtensionProperties> extensions;
};

struct VulkanFormatInfo
{
    VkFormat format;
    VkFormatProperties properties;
    bool supported;
};

struct VulkanSurfaceInfo
{
    bool validSurface = false;
    VkSurfaceCapabilitiesKHR capabilities;
    std::vector<VkPresentModeKHR> presentModes;
    std::vector<VkSurfaceFormatKHR> formats;
    std::string surfaceExtension;
    void get(VkPhysicalDevice device, VkSurfaceKHR surface);
};

class VulkanDeviceInfo: public VulkanDeviceInfoExtensions
{
private:
    std::vector<VulkanLayerInfo> layers;
    bool vulkanVersionSupported(uint32_t major, uint32_t minor);
    bool extensionSupported(const char* extensionName);
#if defined(__ANDROID__)
    std::string getSystemProperty(const char* propname);
#endif
public:
    uint32_t id;
    QVariantMap properties;
    QVariantMap sparseProperties;
    QVariantMap limits;
    QVariantMap features;
    std::map<std::string, std::string> platformdetails;
    VkDevice dev = VK_NULL_HANDLE;
    VkPhysicalDeviceProperties props;
    VkPhysicalDeviceMemoryProperties memoryProperties;
    VkPhysicalDeviceFeatures deviceFeatures;
    QVariantMap core11Features;
    QVariantMap core12Features;
    QVariantMap core13Features;
    QVariantMap core14Features;
    bool hasSubgroupProperties = false;
    bool hasFeaturModifyingTool = false;
    QVariantMap subgroupProperties;
    QVariantMap core11Properties;
    QVariantMap core12Properties;
    QVariantMap core13Properties;
    QVariantMap core14Properties;
    std::vector<VulkanQueueFamilyInfo> queueFamilies;
    std::vector<VulkanFormatInfo> formats;
    VulkanSurfaceInfo surfaceInfo;
    std::vector<VulkanProfileInfo> profiles;
    OSInfo os;
    QString appVersion;
    QString reportVersion;
    std::vector<VulkanLayerInfo> getLayers();
    std::string getDriverVersion();
    void readExtensions();
    void readLayers();
    void readSupportedFormats();
    void readQueueFamilies();
    void readPhysicalProperties();
    void readPhysicalFeatures();
    void readPhysicalLimits();
    void readPhysicalMemoryProperties();
    void readSurfaceInfo();
    void readPlatformDetails();
    void readProfiles();
    QJsonObject toJson(QString submitter, QString comment);
};

#endif // VULKANDEVICEINFO_H
