• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 enum class CalledICDGIPA { not_called, vk_icd_gipa, vk_gipa };
35 
36 enum class CalledNegotiateInterface { not_called, vk_icd_negotiate, vk_icd_gipa_first };
37 
38 enum class InterfaceVersionCheck {
39     not_called,
40     loader_version_too_old,
41     loader_version_too_new,
42     icd_version_too_new,
43     version_is_supported
44 };
45 
46 // clang-format off
47 inline std::ostream& operator<<(std::ostream& os, const CalledICDGIPA& result) {
48     switch (result) {
49         case (CalledICDGIPA::not_called): return os << "CalledICDGIPA::not_called";
50         case (CalledICDGIPA::vk_icd_gipa): return os << "CalledICDGIPA::vk_icd_gipa";
51         case (CalledICDGIPA::vk_gipa): return os << "CalledICDGIPA::vk_gipa";
52     }
53     return os << static_cast<uint32_t>(result);
54 }
55 inline std::ostream& operator<<(std::ostream& os, const CalledNegotiateInterface& result) {
56     switch (result) {
57         case (CalledNegotiateInterface::not_called): return os << "CalledNegotiateInterface::not_called";
58         case (CalledNegotiateInterface::vk_icd_negotiate): return os << "CalledNegotiateInterface::vk_icd_negotiate";
59         case (CalledNegotiateInterface::vk_icd_gipa_first): return os << "CalledNegotiateInterface::vk_icd_gipa_first";
60     }
61     return os << static_cast<uint32_t>(result);
62 }
63 inline std::ostream& operator<<(std::ostream& os, const InterfaceVersionCheck& result) {
64     switch (result) {
65         case (InterfaceVersionCheck::not_called): return os << "InterfaceVersionCheck::not_called";
66         case (InterfaceVersionCheck::loader_version_too_old): return os << "InterfaceVersionCheck::loader_version_too_old";
67         case (InterfaceVersionCheck::loader_version_too_new): return os << "InterfaceVersionCheck::loader_version_too_new";
68         case (InterfaceVersionCheck::icd_version_too_new): return os << "InterfaceVersionCheck::icd_version_too_new";
69         case (InterfaceVersionCheck::version_is_supported): return os << "InterfaceVersionCheck::version_is_supported";
70     }
71     return os << static_cast<uint32_t>(result);
72 }
73 // clang-format on
74 
75 // Move only type because it holds a DispatchableHandle<VkPhysicalDevice>
76 struct PhysicalDevice {
PhysicalDevicePhysicalDevice77     PhysicalDevice() {}
PhysicalDevicePhysicalDevice78     PhysicalDevice(std::string name) : deviceName(name) {}
PhysicalDevicePhysicalDevice79     PhysicalDevice(const char* name) : deviceName(name) {}
80 
81     DispatchableHandle<VkPhysicalDevice> vk_physical_device;
82     BUILDER_VALUE(PhysicalDevice, std::string, deviceName, "")
83     BUILDER_VALUE(PhysicalDevice, VkPhysicalDeviceProperties, properties, {})
84     BUILDER_VALUE(PhysicalDevice, VkPhysicalDeviceFeatures, features, {})
85     BUILDER_VALUE(PhysicalDevice, VkPhysicalDeviceMemoryProperties, memory_properties, {})
86     BUILDER_VALUE(PhysicalDevice, VkImageFormatProperties, image_format_properties, {})
87     BUILDER_VALUE(PhysicalDevice, VkExternalMemoryProperties, external_memory_properties, {})
88     BUILDER_VALUE(PhysicalDevice, VkExternalSemaphoreProperties, external_semaphore_properties, {})
89     BUILDER_VALUE(PhysicalDevice, VkExternalFenceProperties, external_fence_properties, {})
90     BUILDER_VALUE(PhysicalDevice, uint32_t, pci_bus, {})
91 
BUILDER_VECTORPhysicalDevice92     BUILDER_VECTOR(PhysicalDevice, MockQueueFamilyProperties, queue_family_properties, queue_family_properties)
93     BUILDER_VECTOR(PhysicalDevice, VkFormatProperties, format_properties, format_properties)
94     BUILDER_VECTOR(PhysicalDevice, VkSparseImageFormatProperties, sparse_image_format_properties, sparse_image_format_properties)
95 
96     BUILDER_VECTOR(PhysicalDevice, Extension, extensions, extension)
97 
98     BUILDER_VALUE(PhysicalDevice, VkSurfaceCapabilitiesKHR, surface_capabilities, {})
99     BUILDER_VECTOR(PhysicalDevice, VkSurfaceFormatKHR, surface_formats, surface_format)
100     BUILDER_VECTOR(PhysicalDevice, VkPresentModeKHR, surface_present_modes, surface_present_mode)
101     BUILDER_VALUE(PhysicalDevice, VkSurfacePresentScalingCapabilitiesEXT, surface_present_scaling_capabilities, {})
102     // No good way to make this a builder value. Each std::vector<VkPresentModeKHR> corresponds to each surface_present_modes
103     // element
104     std::vector<std::vector<VkPresentModeKHR>> surface_present_mode_compatibility{};
105 
BUILDER_VECTORPhysicalDevice106     BUILDER_VECTOR(PhysicalDevice, VkDisplayPropertiesKHR, display_properties, display_properties)
107     BUILDER_VECTOR(PhysicalDevice, VkDisplayPlanePropertiesKHR, display_plane_properties, display_plane_properties)
108     BUILDER_VECTOR(PhysicalDevice, VkDisplayKHR, displays, displays)
109     BUILDER_VECTOR(PhysicalDevice, VkDisplayModePropertiesKHR, display_mode_properties, display_mode_properties)
110     BUILDER_VALUE(PhysicalDevice, VkDisplayModeKHR, display_mode, {})
111     BUILDER_VALUE(PhysicalDevice, VkDisplayPlaneCapabilitiesKHR, display_plane_capabilities, {})
112 
113     BUILDER_VALUE(PhysicalDevice, VkLayeredDriverUnderlyingApiMSFT, layered_driver_underlying_api,
114                   VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT)
115 
116     PhysicalDevice& set_api_version(uint32_t version) {
117         properties.apiVersion = version;
118         return *this;
119     }
120 
finishPhysicalDevice121     PhysicalDevice&& finish() { return std::move(*this); }
122 
123     // Objects created from this physical device
124     std::vector<VkDevice> device_handles;
125     std::vector<DeviceCreateInfo> device_create_infos;
126     std::vector<DispatchableHandle<VkQueue>> queue_handles;
127 
128     // Unknown physical device functions. Add a `VulkanFunction` to this list which will be searched in
129     // vkGetInstanceProcAddr for custom_instance_functions and vk_icdGetPhysicalDeviceProcAddr for custom_physical_device_functions.
130     // To add unknown device functions, add it to the PhysicalDevice directly (in the known_device_functions member)
131     BUILDER_VECTOR(PhysicalDevice, VulkanFunction, custom_physical_device_functions, custom_physical_device_function)
132 
133     // List of function names which are 'known' to the physical device but have test defined implementations
134     // The purpose of this list is so that vkGetDeviceProcAddr returns 'a real function pointer' in tests
135     // without actually implementing any of the logic inside of it.
136     BUILDER_VECTOR(PhysicalDevice, VulkanFunction, known_device_functions, device_function)
137 };
138 
139 struct PhysicalDeviceGroup {
PhysicalDeviceGroupPhysicalDeviceGroup140     PhysicalDeviceGroup() {}
PhysicalDeviceGroupPhysicalDeviceGroup141     PhysicalDeviceGroup(PhysicalDevice const& physical_device) { physical_device_handles.push_back(&physical_device); }
PhysicalDeviceGroupPhysicalDeviceGroup142     PhysicalDeviceGroup(std::vector<PhysicalDevice*> const& physical_devices) {
143         physical_device_handles.insert(physical_device_handles.end(), physical_devices.begin(), physical_devices.end());
144     }
use_physical_devicePhysicalDeviceGroup145     PhysicalDeviceGroup& use_physical_device(PhysicalDevice const& physical_device) {
146         physical_device_handles.push_back(&physical_device);
147         return *this;
148     }
149 
150     std::vector<PhysicalDevice const*> physical_device_handles;
151     VkBool32 subset_allocation = false;
152 };
153 
154 struct TestICD {
155     std::filesystem::path manifest_file_path;
156 
157     BUILDER_VALUE(TestICD, bool, exposes_vk_icdNegotiateLoaderICDInterfaceVersion, true)
158     BUILDER_VALUE(TestICD, bool, exposes_vkEnumerateInstanceExtensionProperties, true)
159     BUILDER_VALUE(TestICD, bool, exposes_vkCreateInstance, true)
160     BUILDER_VALUE(TestICD, bool, exposes_vk_icdGetPhysicalDeviceProcAddr, true)
161 #if defined(WIN32)
162     BUILDER_VALUE(TestICD, bool, exposes_vk_icdEnumerateAdapterPhysicalDevices, true)
163 #endif
164 
165     CalledICDGIPA called_vk_icd_gipa = CalledICDGIPA::not_called;
166     CalledNegotiateInterface called_negotiate_interface = CalledNegotiateInterface::not_called;
167 
168     InterfaceVersionCheck interface_version_check = InterfaceVersionCheck::not_called;
169     BUILDER_VALUE(TestICD, uint32_t, min_icd_interface_version, 0)
170     BUILDER_VALUE(TestICD, uint32_t, max_icd_interface_version, 7)
171     uint32_t icd_interface_version_received = 0;
172 
173     bool called_enumerate_adapter_physical_devices = false;
174 
175     BUILDER_VALUE(TestICD, bool, enable_icd_wsi, false);
176     bool is_using_icd_wsi = false;
177 
178     TestICD& setup_WSI(const char* api_selection = nullptr) {
179         enable_icd_wsi = true;
180         add_instance_extensions({"VK_KHR_surface", get_platform_wsi_extension(api_selection)});
181         min_icd_interface_version = (3U < min_icd_interface_version) ? min_icd_interface_version : 3U;
182         return *this;
183     }
184 
185     BUILDER_VALUE(TestICD, uint32_t, icd_api_version, VK_API_VERSION_1_0)
186     BUILDER_VECTOR(TestICD, LayerDefinition, instance_layers, instance_layer)
187     BUILDER_VECTOR(TestICD, Extension, instance_extensions, instance_extension)
188     std::vector<Extension> enabled_instance_extensions;
189 
190     BUILDER_VECTOR_MOVE_ONLY(TestICD, PhysicalDevice, physical_devices, physical_device);
191 
192     BUILDER_VECTOR(TestICD, PhysicalDeviceGroup, physical_device_groups, physical_device_group);
193 
194     DispatchableHandle<VkInstance> instance_handle;
195     std::vector<DispatchableHandle<VkDevice>> device_handles;
196     std::vector<uint64_t> surface_handles;
197     std::vector<uint64_t> messenger_handles;
198     std::vector<uint64_t> callback_handles;
199     std::vector<uint64_t> swapchain_handles;
200 
201     BUILDER_VALUE(TestICD, bool, can_query_vkEnumerateInstanceVersion, true);
202     BUILDER_VALUE(TestICD, bool, can_query_GetPhysicalDeviceFuncs, true);
203 
204     // Unknown instance functions Add a `VulkanFunction` to this list which will be searched in
205     // vkGetInstanceProcAddr for custom_instance_functions and vk_icdGetPhysicalDeviceProcAddr for
206     // custom_physical_device_functions. To add unknown device functions, add it to the PhysicalDevice directly (in the
207     // known_device_functions member)
208     BUILDER_VECTOR(TestICD, VulkanFunction, custom_instance_functions, custom_instance_function)
209 
210     // Must explicitely state support for the tooling info extension, that way we can control if vkGetInstanceProcAddr returns a
211     // function pointer for vkGetPhysicalDeviceToolPropertiesEXT or vkGetPhysicalDeviceToolProperties (core version)
212     BUILDER_VALUE(TestICD, bool, supports_tooling_info_ext, false);
213     BUILDER_VALUE(TestICD, bool, supports_tooling_info_core, false);
214     // List of tooling properties that this driver 'supports'
215     BUILDER_VECTOR(TestICD, VkPhysicalDeviceToolPropertiesEXT, tooling_properties, tooling_property)
216     std::vector<DispatchableHandle<VkCommandBuffer>> allocated_command_buffers;
217 
218     VkInstanceCreateFlags passed_in_instance_create_flags{};
219 
220     BUILDER_VALUE(TestICD, VkResult, enum_physical_devices_return_code, VK_SUCCESS);
221     BUILDER_VALUE(TestICD, VkResult, enum_adapter_physical_devices_return_code, VK_SUCCESS);
222 
GetPhysDeviceTestICD223     PhysicalDevice& GetPhysDevice(VkPhysicalDevice physicalDevice) {
224         for (auto& phys_dev : physical_devices) {
225             if (phys_dev.vk_physical_device.handle == physicalDevice) return phys_dev;
226         }
227         assert(false && "vkPhysicalDevice not found!");
228         return physical_devices[0];
229     }
230 
GetVkInstanceCreateInfoTestICD231     InstanceCreateInfo GetVkInstanceCreateInfo() {
232         InstanceCreateInfo info;
233         for (auto& layer : instance_layers) info.enabled_layers.push_back(layer.layerName.data());
234         for (auto& ext : instance_extensions) info.enabled_extensions.push_back(ext.extensionName.data());
235         return info;
236     }
237 
238     struct FindDevice {
239         bool found = false;
240         uint32_t phys_dev_index = 0;
241         uint32_t dev_index = 0;
242     };
243 
lookup_deviceTestICD244     FindDevice lookup_device(VkDevice device) {
245         FindDevice fd{};
246         for (uint32_t p = 0; p < physical_devices.size(); p++) {
247             auto const& phys_dev = physical_devices.at(p);
248             for (uint32_t d = 0; d < phys_dev.device_handles.size(); d++) {
249                 if (phys_dev.device_handles.at(d) == device) {
250                     fd.found = true;
251                     fd.phys_dev_index = p;
252                     fd.dev_index = d;
253                     return fd;
254                 }
255             }
256         }
257         return fd;
258     }
259 
260 #if defined(WIN32)
261     BUILDER_VALUE(TestICD, LUID, adapterLUID, {})
262 #endif  // defined(WIN32)
263 };
264 
265 using GetTestICDFunc = TestICD* (*)();
266 #define GET_TEST_ICD_FUNC_STR "get_test_icd_func"
267 
268 using GetNewTestICDFunc = TestICD* (*)();
269 #define RESET_ICD_FUNC_STR "reset_icd_func"
270