15db71995Sopenharmony_ci/*
25db71995Sopenharmony_ci * Copyright (c) 2021-2023 The Khronos Group Inc.
35db71995Sopenharmony_ci * Copyright (c) 2021-2023 Valve Corporation
45db71995Sopenharmony_ci * Copyright (c) 2021-2023 LunarG, Inc.
55db71995Sopenharmony_ci *
65db71995Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
75db71995Sopenharmony_ci * of this software and/or associated documentation files (the "Materials"), to
85db71995Sopenharmony_ci * deal in the Materials without restriction, including without limitation the
95db71995Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
105db71995Sopenharmony_ci * sell copies of the Materials, and to permit persons to whom the Materials are
115db71995Sopenharmony_ci * furnished to do so, subject to the following conditions:
125db71995Sopenharmony_ci *
135db71995Sopenharmony_ci * The above copyright notice(s) and this permission notice shall be included in
145db71995Sopenharmony_ci * all copies or substantial portions of the Materials.
155db71995Sopenharmony_ci *
165db71995Sopenharmony_ci * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
175db71995Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
185db71995Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
195db71995Sopenharmony_ci *
205db71995Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
215db71995Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
225db71995Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
235db71995Sopenharmony_ci * USE OR OTHER DEALINGS IN THE MATERIALS.
245db71995Sopenharmony_ci *
255db71995Sopenharmony_ci * Author: Charles Giessen <charles@lunarg.com>
265db71995Sopenharmony_ci */
275db71995Sopenharmony_ci
285db71995Sopenharmony_ci#pragma once
295db71995Sopenharmony_ci
305db71995Sopenharmony_ci#include "test_util.h"
315db71995Sopenharmony_ci
325db71995Sopenharmony_ci#include "layer/layer_util.h"
335db71995Sopenharmony_ci
345db71995Sopenharmony_ci#include "physical_device.h"
355db71995Sopenharmony_ci
365db71995Sopenharmony_cienum class CalledICDGIPA { not_called, vk_icd_gipa, vk_gipa };
375db71995Sopenharmony_ci
385db71995Sopenharmony_cienum class CalledNegotiateInterface { not_called, vk_icd_negotiate, vk_icd_gipa_first };
395db71995Sopenharmony_ci
405db71995Sopenharmony_cienum class InterfaceVersionCheck {
415db71995Sopenharmony_ci    not_called,
425db71995Sopenharmony_ci    loader_version_too_old,
435db71995Sopenharmony_ci    loader_version_too_new,
445db71995Sopenharmony_ci    icd_version_too_new,
455db71995Sopenharmony_ci    version_is_supported
465db71995Sopenharmony_ci};
475db71995Sopenharmony_ci
485db71995Sopenharmony_ci// clang-format off
495db71995Sopenharmony_ciinline std::ostream& operator<<(std::ostream& os, const CalledICDGIPA& result) {
505db71995Sopenharmony_ci    switch (result) {
515db71995Sopenharmony_ci        case (CalledICDGIPA::not_called): return os << "CalledICDGIPA::not_called";
525db71995Sopenharmony_ci        case (CalledICDGIPA::vk_icd_gipa): return os << "CalledICDGIPA::vk_icd_gipa";
535db71995Sopenharmony_ci        case (CalledICDGIPA::vk_gipa): return os << "CalledICDGIPA::vk_gipa";
545db71995Sopenharmony_ci    }
555db71995Sopenharmony_ci    return os << static_cast<uint32_t>(result);
565db71995Sopenharmony_ci}
575db71995Sopenharmony_ciinline std::ostream& operator<<(std::ostream& os, const CalledNegotiateInterface& result) {
585db71995Sopenharmony_ci    switch (result) {
595db71995Sopenharmony_ci        case (CalledNegotiateInterface::not_called): return os << "CalledNegotiateInterface::not_called";
605db71995Sopenharmony_ci        case (CalledNegotiateInterface::vk_icd_negotiate): return os << "CalledNegotiateInterface::vk_icd_negotiate";
615db71995Sopenharmony_ci        case (CalledNegotiateInterface::vk_icd_gipa_first): return os << "CalledNegotiateInterface::vk_icd_gipa_first";
625db71995Sopenharmony_ci    }
635db71995Sopenharmony_ci    return os << static_cast<uint32_t>(result);
645db71995Sopenharmony_ci}
655db71995Sopenharmony_ciinline std::ostream& operator<<(std::ostream& os, const InterfaceVersionCheck& result) {
665db71995Sopenharmony_ci    switch (result) {
675db71995Sopenharmony_ci        case (InterfaceVersionCheck::not_called): return os << "InterfaceVersionCheck::not_called";
685db71995Sopenharmony_ci        case (InterfaceVersionCheck::loader_version_too_old): return os << "InterfaceVersionCheck::loader_version_too_old";
695db71995Sopenharmony_ci        case (InterfaceVersionCheck::loader_version_too_new): return os << "InterfaceVersionCheck::loader_version_too_new";
705db71995Sopenharmony_ci        case (InterfaceVersionCheck::icd_version_too_new): return os << "InterfaceVersionCheck::icd_version_too_new";
715db71995Sopenharmony_ci        case (InterfaceVersionCheck::version_is_supported): return os << "InterfaceVersionCheck::version_is_supported";
725db71995Sopenharmony_ci    }
735db71995Sopenharmony_ci    return os << static_cast<uint32_t>(result);
745db71995Sopenharmony_ci}
755db71995Sopenharmony_ci// clang-format on
765db71995Sopenharmony_ci
775db71995Sopenharmony_cistruct TestICD {
785db71995Sopenharmony_ci    fs::path manifest_file_path;
795db71995Sopenharmony_ci
805db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, exposes_vk_icdNegotiateLoaderICDInterfaceVersion, true)
815db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, exposes_vkEnumerateInstanceExtensionProperties, true)
825db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, exposes_vkCreateInstance, true)
835db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, exposes_vk_icdGetPhysicalDeviceProcAddr, true)
845db71995Sopenharmony_ci#if defined(WIN32)
855db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, exposes_vk_icdEnumerateAdapterPhysicalDevices, true)
865db71995Sopenharmony_ci#endif
875db71995Sopenharmony_ci
885db71995Sopenharmony_ci    CalledICDGIPA called_vk_icd_gipa = CalledICDGIPA::not_called;
895db71995Sopenharmony_ci    CalledNegotiateInterface called_negotiate_interface = CalledNegotiateInterface::not_called;
905db71995Sopenharmony_ci
915db71995Sopenharmony_ci    InterfaceVersionCheck interface_version_check = InterfaceVersionCheck::not_called;
925db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, uint32_t, min_icd_interface_version, 0)
935db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, uint32_t, max_icd_interface_version, 7)
945db71995Sopenharmony_ci    uint32_t icd_interface_version_received = 0;
955db71995Sopenharmony_ci
965db71995Sopenharmony_ci    bool called_enumerate_adapter_physical_devices = false;
975db71995Sopenharmony_ci
985db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, enable_icd_wsi, false);
995db71995Sopenharmony_ci    bool is_using_icd_wsi = false;
1005db71995Sopenharmony_ci
1015db71995Sopenharmony_ci    TestICD& setup_WSI(const char* api_selection = nullptr) {
1025db71995Sopenharmony_ci        enable_icd_wsi = true;
1035db71995Sopenharmony_ci        add_instance_extensions({"VK_KHR_surface", get_platform_wsi_extension(api_selection)});
1045db71995Sopenharmony_ci        min_icd_interface_version = (3U < min_icd_interface_version) ? min_icd_interface_version : 3U;
1055db71995Sopenharmony_ci        return *this;
1065db71995Sopenharmony_ci    }
1075db71995Sopenharmony_ci
1085db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, uint32_t, icd_api_version, VK_API_VERSION_1_0)
1095db71995Sopenharmony_ci    BUILDER_VECTOR(TestICD, LayerDefinition, instance_layers, instance_layer)
1105db71995Sopenharmony_ci    BUILDER_VECTOR(TestICD, Extension, instance_extensions, instance_extension)
1115db71995Sopenharmony_ci    BUILDER_VECTOR(TestICD, Extension, enabled_instance_extensions, enabled_instance_extension)
1125db71995Sopenharmony_ci
1135db71995Sopenharmony_ci    BUILDER_VECTOR_MOVE_ONLY(TestICD, PhysicalDevice, physical_devices, physical_device);
1145db71995Sopenharmony_ci
1155db71995Sopenharmony_ci    BUILDER_VECTOR(TestICD, PhysicalDeviceGroup, physical_device_groups, physical_device_group);
1165db71995Sopenharmony_ci
1175db71995Sopenharmony_ci    DispatchableHandle<VkInstance> instance_handle;
1185db71995Sopenharmony_ci    std::vector<DispatchableHandle<VkDevice>> device_handles;
1195db71995Sopenharmony_ci    std::vector<uint64_t> surface_handles;
1205db71995Sopenharmony_ci    std::vector<uint64_t> messenger_handles;
1215db71995Sopenharmony_ci    std::vector<uint64_t> swapchain_handles;
1225db71995Sopenharmony_ci
1235db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, can_query_vkEnumerateInstanceVersion, true);
1245db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, can_query_GetPhysicalDeviceFuncs, true);
1255db71995Sopenharmony_ci
1265db71995Sopenharmony_ci    // Unknown instance functions Add a `VulkanFunction` to this list which will be searched in
1275db71995Sopenharmony_ci    // vkGetInstanceProcAddr for custom_instance_functions and vk_icdGetPhysicalDeviceProcAddr for
1285db71995Sopenharmony_ci    // custom_physical_device_functions. To add unknown device functions, add it to the PhysicalDevice directly (in the
1295db71995Sopenharmony_ci    // known_device_functions member)
1305db71995Sopenharmony_ci    BUILDER_VECTOR(TestICD, VulkanFunction, custom_instance_functions, custom_instance_function)
1315db71995Sopenharmony_ci
1325db71995Sopenharmony_ci    // Must explicitely state support for the tooling info extension, that way we can control if vkGetInstanceProcAddr returns a
1335db71995Sopenharmony_ci    // function pointer for vkGetPhysicalDeviceToolPropertiesEXT or vkGetPhysicalDeviceToolProperties (core version)
1345db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, supports_tooling_info_ext, false);
1355db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, bool, supports_tooling_info_core, false);
1365db71995Sopenharmony_ci    // List of tooling properties that this driver 'supports'
1375db71995Sopenharmony_ci    BUILDER_VECTOR(TestICD, VkPhysicalDeviceToolPropertiesEXT, tooling_properties, tooling_property)
1385db71995Sopenharmony_ci    std::vector<DispatchableHandle<VkCommandBuffer>> allocated_command_buffers;
1395db71995Sopenharmony_ci
1405db71995Sopenharmony_ci    VkInstanceCreateFlags passed_in_instance_create_flags{};
1415db71995Sopenharmony_ci
1425db71995Sopenharmony_ci    PhysicalDevice& GetPhysDevice(VkPhysicalDevice physicalDevice) {
1435db71995Sopenharmony_ci        for (auto& phys_dev : physical_devices) {
1445db71995Sopenharmony_ci            if (phys_dev.vk_physical_device.handle == physicalDevice) return phys_dev;
1455db71995Sopenharmony_ci        }
1465db71995Sopenharmony_ci        assert(false && "vkPhysicalDevice not found!");
1475db71995Sopenharmony_ci        return physical_devices[0];
1485db71995Sopenharmony_ci    }
1495db71995Sopenharmony_ci
1505db71995Sopenharmony_ci    InstanceCreateInfo GetVkInstanceCreateInfo() {
1515db71995Sopenharmony_ci        InstanceCreateInfo info;
1525db71995Sopenharmony_ci        for (auto& layer : instance_layers) info.enabled_layers.push_back(layer.layerName.data());
1535db71995Sopenharmony_ci        for (auto& ext : instance_extensions) info.enabled_extensions.push_back(ext.extensionName.data());
1545db71995Sopenharmony_ci        return info;
1555db71995Sopenharmony_ci    }
1565db71995Sopenharmony_ci
1575db71995Sopenharmony_ci    struct FindDevice {
1585db71995Sopenharmony_ci        bool found = false;
1595db71995Sopenharmony_ci        uint32_t phys_dev_index = 0;
1605db71995Sopenharmony_ci        uint32_t dev_index = 0;
1615db71995Sopenharmony_ci    };
1625db71995Sopenharmony_ci
1635db71995Sopenharmony_ci    FindDevice lookup_device(VkDevice device) {
1645db71995Sopenharmony_ci        FindDevice fd{};
1655db71995Sopenharmony_ci        for (uint32_t p = 0; p < physical_devices.size(); p++) {
1665db71995Sopenharmony_ci            auto const& phys_dev = physical_devices.at(p);
1675db71995Sopenharmony_ci            for (uint32_t d = 0; d < phys_dev.device_handles.size(); d++) {
1685db71995Sopenharmony_ci                if (phys_dev.device_handles.at(d) == device) {
1695db71995Sopenharmony_ci                    fd.found = true;
1705db71995Sopenharmony_ci                    fd.phys_dev_index = p;
1715db71995Sopenharmony_ci                    fd.dev_index = d;
1725db71995Sopenharmony_ci                    return fd;
1735db71995Sopenharmony_ci                }
1745db71995Sopenharmony_ci            }
1755db71995Sopenharmony_ci        }
1765db71995Sopenharmony_ci        return fd;
1775db71995Sopenharmony_ci    }
1785db71995Sopenharmony_ci
1795db71995Sopenharmony_ci#if defined(WIN32)
1805db71995Sopenharmony_ci    BUILDER_VALUE(TestICD, LUID, adapterLUID, {})
1815db71995Sopenharmony_ci#endif  // defined(WIN32)
1825db71995Sopenharmony_ci};
1835db71995Sopenharmony_ci
1845db71995Sopenharmony_ciusing GetTestICDFunc = TestICD* (*)();
1855db71995Sopenharmony_ci#define GET_TEST_ICD_FUNC_STR "get_test_icd_func"
1865db71995Sopenharmony_ci
1875db71995Sopenharmony_ciusing GetNewTestICDFunc = TestICD* (*)();
1885db71995Sopenharmony_ci#define RESET_ICD_FUNC_STR "reset_icd_func"
189