1 /* 2 * Copyright (c) 2021-2023 The Khronos Group Inc. 3 * Copyright (c) 2021-2023 Valve Corporation 4 * Copyright (c) 2021-2023 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and/or associated documentation files (the "Materials"), to 8 * deal in the Materials without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Materials, and to permit persons to whom the Materials are 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice(s) and this permission notice shall be included in 14 * all copies or substantial portions of the Materials. 15 * 16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 23 * USE OR OTHER DEALINGS IN THE MATERIALS. 24 * 25 * Author: Charles Giessen <charles@lunarg.com> 26 */ 27 28 #pragma once 29 30 #include "test_util.h" 31 32 #include "layer/layer_util.h" 33 34 #include "physical_device.h" 35 36 enum class CalledICDGIPA { not_called, vk_icd_gipa, vk_gipa }; 37 38 enum class CalledNegotiateInterface { not_called, vk_icd_negotiate, vk_icd_gipa_first }; 39 40 enum class InterfaceVersionCheck { 41 not_called, 42 loader_version_too_old, 43 loader_version_too_new, 44 icd_version_too_new, 45 version_is_supported 46 }; 47 48 // clang-format off 49 inline std::ostream& operator<<(std::ostream& os, const CalledICDGIPA& result) { 50 switch (result) { 51 case (CalledICDGIPA::not_called): return os << "CalledICDGIPA::not_called"; 52 case (CalledICDGIPA::vk_icd_gipa): return os << "CalledICDGIPA::vk_icd_gipa"; 53 case (CalledICDGIPA::vk_gipa): return os << "CalledICDGIPA::vk_gipa"; 54 } 55 return os << static_cast<uint32_t>(result); 56 } 57 inline std::ostream& operator<<(std::ostream& os, const CalledNegotiateInterface& result) { 58 switch (result) { 59 case (CalledNegotiateInterface::not_called): return os << "CalledNegotiateInterface::not_called"; 60 case (CalledNegotiateInterface::vk_icd_negotiate): return os << "CalledNegotiateInterface::vk_icd_negotiate"; 61 case (CalledNegotiateInterface::vk_icd_gipa_first): return os << "CalledNegotiateInterface::vk_icd_gipa_first"; 62 } 63 return os << static_cast<uint32_t>(result); 64 } 65 inline std::ostream& operator<<(std::ostream& os, const InterfaceVersionCheck& result) { 66 switch (result) { 67 case (InterfaceVersionCheck::not_called): return os << "InterfaceVersionCheck::not_called"; 68 case (InterfaceVersionCheck::loader_version_too_old): return os << "InterfaceVersionCheck::loader_version_too_old"; 69 case (InterfaceVersionCheck::loader_version_too_new): return os << "InterfaceVersionCheck::loader_version_too_new"; 70 case (InterfaceVersionCheck::icd_version_too_new): return os << "InterfaceVersionCheck::icd_version_too_new"; 71 case (InterfaceVersionCheck::version_is_supported): return os << "InterfaceVersionCheck::version_is_supported"; 72 } 73 return os << static_cast<uint32_t>(result); 74 } 75 // clang-format on 76 77 struct TestICD { 78 fs::path manifest_file_path; 79 80 BUILDER_VALUE(TestICD, bool, exposes_vk_icdNegotiateLoaderICDInterfaceVersion, true) 81 BUILDER_VALUE(TestICD, bool, exposes_vkEnumerateInstanceExtensionProperties, true) 82 BUILDER_VALUE(TestICD, bool, exposes_vkCreateInstance, true) 83 BUILDER_VALUE(TestICD, bool, exposes_vk_icdGetPhysicalDeviceProcAddr, true) 84 #if defined(WIN32) 85 BUILDER_VALUE(TestICD, bool, exposes_vk_icdEnumerateAdapterPhysicalDevices, true) 86 #endif 87 88 CalledICDGIPA called_vk_icd_gipa = CalledICDGIPA::not_called; 89 CalledNegotiateInterface called_negotiate_interface = CalledNegotiateInterface::not_called; 90 91 InterfaceVersionCheck interface_version_check = InterfaceVersionCheck::not_called; 92 BUILDER_VALUE(TestICD, uint32_t, min_icd_interface_version, 0) 93 BUILDER_VALUE(TestICD, uint32_t, max_icd_interface_version, 7) 94 uint32_t icd_interface_version_received = 0; 95 96 bool called_enumerate_adapter_physical_devices = false; 97 98 BUILDER_VALUE(TestICD, bool, enable_icd_wsi, false); 99 bool is_using_icd_wsi = false; 100 101 TestICD& setup_WSI(const char* api_selection = nullptr) { 102 enable_icd_wsi = true; 103 add_instance_extensions({"VK_KHR_surface", get_platform_wsi_extension(api_selection)}); 104 min_icd_interface_version = (3U < min_icd_interface_version) ? min_icd_interface_version : 3U; 105 return *this; 106 } 107 108 BUILDER_VALUE(TestICD, uint32_t, icd_api_version, VK_API_VERSION_1_0) 109 BUILDER_VECTOR(TestICD, LayerDefinition, instance_layers, instance_layer) 110 BUILDER_VECTOR(TestICD, Extension, instance_extensions, instance_extension) 111 BUILDER_VECTOR(TestICD, Extension, enabled_instance_extensions, enabled_instance_extension) 112 113 BUILDER_VECTOR_MOVE_ONLY(TestICD, PhysicalDevice, physical_devices, physical_device); 114 115 BUILDER_VECTOR(TestICD, PhysicalDeviceGroup, physical_device_groups, physical_device_group); 116 117 DispatchableHandle<VkInstance> instance_handle; 118 std::vector<DispatchableHandle<VkDevice>> device_handles; 119 std::vector<uint64_t> surface_handles; 120 std::vector<uint64_t> messenger_handles; 121 std::vector<uint64_t> swapchain_handles; 122 123 BUILDER_VALUE(TestICD, bool, can_query_vkEnumerateInstanceVersion, true); 124 BUILDER_VALUE(TestICD, bool, can_query_GetPhysicalDeviceFuncs, true); 125 126 // Unknown instance functions Add a `VulkanFunction` to this list which will be searched in 127 // vkGetInstanceProcAddr for custom_instance_functions and vk_icdGetPhysicalDeviceProcAddr for 128 // custom_physical_device_functions. To add unknown device functions, add it to the PhysicalDevice directly (in the 129 // known_device_functions member) 130 BUILDER_VECTOR(TestICD, VulkanFunction, custom_instance_functions, custom_instance_function) 131 132 // Must explicitely state support for the tooling info extension, that way we can control if vkGetInstanceProcAddr returns a 133 // function pointer for vkGetPhysicalDeviceToolPropertiesEXT or vkGetPhysicalDeviceToolProperties (core version) 134 BUILDER_VALUE(TestICD, bool, supports_tooling_info_ext, false); 135 BUILDER_VALUE(TestICD, bool, supports_tooling_info_core, false); 136 // List of tooling properties that this driver 'supports' 137 BUILDER_VECTOR(TestICD, VkPhysicalDeviceToolPropertiesEXT, tooling_properties, tooling_property) 138 std::vector<DispatchableHandle<VkCommandBuffer>> allocated_command_buffers; 139 140 VkInstanceCreateFlags passed_in_instance_create_flags{}; 141 GetPhysDeviceTestICD142 PhysicalDevice& GetPhysDevice(VkPhysicalDevice physicalDevice) { 143 for (auto& phys_dev : physical_devices) { 144 if (phys_dev.vk_physical_device.handle == physicalDevice) return phys_dev; 145 } 146 assert(false && "vkPhysicalDevice not found!"); 147 return physical_devices[0]; 148 } 149 GetVkInstanceCreateInfoTestICD150 InstanceCreateInfo GetVkInstanceCreateInfo() { 151 InstanceCreateInfo info; 152 for (auto& layer : instance_layers) info.enabled_layers.push_back(layer.layerName.data()); 153 for (auto& ext : instance_extensions) info.enabled_extensions.push_back(ext.extensionName.data()); 154 return info; 155 } 156 157 struct FindDevice { 158 bool found = false; 159 uint32_t phys_dev_index = 0; 160 uint32_t dev_index = 0; 161 }; 162 lookup_deviceTestICD163 FindDevice lookup_device(VkDevice device) { 164 FindDevice fd{}; 165 for (uint32_t p = 0; p < physical_devices.size(); p++) { 166 auto const& phys_dev = physical_devices.at(p); 167 for (uint32_t d = 0; d < phys_dev.device_handles.size(); d++) { 168 if (phys_dev.device_handles.at(d) == device) { 169 fd.found = true; 170 fd.phys_dev_index = p; 171 fd.dev_index = d; 172 return fd; 173 } 174 } 175 } 176 return fd; 177 } 178 179 #if defined(WIN32) 180 BUILDER_VALUE(TestICD, LUID, adapterLUID, {}) 181 #endif // defined(WIN32) 182 }; 183 184 using GetTestICDFunc = TestICD* (*)(); 185 #define GET_TEST_ICD_FUNC_STR "get_test_icd_func" 186 187 using GetNewTestICDFunc = TestICD* (*)(); 188 #define RESET_ICD_FUNC_STR "reset_icd_func" 189