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#include "test_environment.h"
29
30TEST(ICDInterfaceVersion2Plus, vk_icdNegotiateLoaderICDInterfaceVersion) {
31    FrameworkEnvironment env{};
32    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
33
34    for (uint32_t i = 0; i <= 6; i++) {
35        for (uint32_t j = i; j <= 6; j++) {
36            driver.set_min_icd_interface_version(i).set_max_icd_interface_version(j);
37            InstWrapper inst{env.vulkan_functions};
38            inst.CheckCreate();
39        }
40    }
41}
42
43TEST(ICDInterfaceVersion2Plus, version_3) {
44    FrameworkEnvironment env{};
45    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
46    {
47        driver.set_min_icd_interface_version(2).set_enable_icd_wsi(true);
48        InstWrapper inst{env.vulkan_functions};
49        inst.CheckCreate();
50
51        ASSERT_FALSE(driver.is_using_icd_wsi);
52    }
53    {
54        driver.set_min_icd_interface_version(3).set_enable_icd_wsi(false);
55        InstWrapper inst{env.vulkan_functions};
56        inst.CheckCreate();
57
58        ASSERT_FALSE(driver.is_using_icd_wsi);
59    }
60    {
61        driver.set_min_icd_interface_version(3).set_enable_icd_wsi(true);
62        InstWrapper inst{env.vulkan_functions};
63        inst.CheckCreate();
64
65        ASSERT_TRUE(driver.is_using_icd_wsi);
66    }
67}
68
69TEST(ICDInterfaceVersion2Plus, version_4) {
70    FrameworkEnvironment env{};
71    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
72    InstWrapper inst{env.vulkan_functions};
73    inst.CheckCreate();
74}
75
76TEST(ICDInterfaceVersion2Plus, l4_icd4) {
77    // TODO:
78    // ICD must fail with VK_ERROR_INCOMPATIBLE_DRIVER for all vkCreateInstance calls with apiVersion set to > Vulkan 1.0
79    // because both the loader and ICD support interface version <= 4. Otherwise, the ICD should behave as normal.
80}
81TEST(ICDInterfaceVersion2Plus, l4_icd5) {
82    // TODO:
83    // ICD must fail with VK_ERROR_INCOMPATIBLE_DRIVER for all vkCreateInstance calls with apiVersion set to > Vulkan 1.0
84    // because the loader is still at interface version <= 4. Otherwise, the ICD should behave as normal.
85}
86TEST(ICDInterfaceVersion2Plus, l5_icd4) {
87    // TODO:
88    // Loader will fail with VK_ERROR_INCOMPATIBLE_DRIVER if it can't handle the apiVersion. ICD may pass for all apiVersions,
89    // but since its interface is <= 4, it is best if it assumes it needs to do the work of rejecting anything > Vulkan 1.0 and
90    // fail with VK_ERROR_INCOMPATIBLE_DRIVER. Otherwise, the ICD should behave as normal.
91}
92TEST(ICDInterfaceVersion2Plus, l5_icd5) {
93    // TODO:
94    // Loader will fail with VK_ERROR_INCOMPATIBLE_DRIVER if it can't handle the apiVersion, and ICDs should fail with
95    // VK_ERROR_INCOMPATIBLE_DRIVER only if they can not support the specified apiVersion. Otherwise, the ICD should behave as
96    // normal.
97}
98
99#if defined(WIN32)
100// This test makes sure that EnumerateAdapterPhysicalDevices on drivers found in the Khronos/Vulkan/Drivers registry
101TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, version_6_in_drivers_registry) {
102    FrameworkEnvironment env{};
103    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES));
104    driver.physical_devices.emplace_back("physical_device_1");
105    driver.physical_devices.emplace_back("physical_device_0");
106    uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
107    uint32_t returned_physical_count = static_cast<uint32_t>(driver.physical_devices.size());
108    std::vector<VkPhysicalDevice> physical_device_handles = std::vector<VkPhysicalDevice>(physical_count);
109
110    driver.min_icd_interface_version = 5;
111
112    auto& known_driver = known_driver_list.at(2);  // which drive this test pretends to be
113    DXGI_ADAPTER_DESC1 desc1{};
114    desc1.AdapterLuid = _LUID{10, 1000};
115    desc1.VendorId = known_driver.vendor_id;
116    env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
117    driver.set_adapterLUID(desc1.AdapterLuid);
118
119    InstWrapper inst{env.vulkan_functions};
120    inst.CheckCreate();
121
122    ASSERT_EQ(VK_SUCCESS,
123              env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
124    ASSERT_EQ(physical_count, returned_physical_count);
125    ASSERT_TRUE(driver.called_enumerate_adapter_physical_devices);
126}
127// Make the version_6 driver found through the D3DKMT driver discovery mechanism of the loader
128TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, version_6) {
129    FrameworkEnvironment env{};
130    env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_3}.set_discovery_type(ManifestDiscoveryType::null_dir));
131    // Version 6 provides a mechanism to allow the loader to sort physical devices.
132    // The loader will only attempt to sort physical devices on an ICD if version 6 of the interface is supported.
133    // This version provides the vk_icdEnumerateAdapterPhysicalDevices function.
134    auto& driver = env.get_test_icd(0);
135    driver.physical_devices.emplace_back("physical_device_1");
136    driver.physical_devices.emplace_back("physical_device_0");
137    uint32_t physical_count = 2;
138    uint32_t returned_physical_count = physical_count;
139    std::vector<VkPhysicalDevice> physical_device_handles{physical_count};
140
141    driver.min_icd_interface_version = 6;
142
143    auto& known_driver = known_driver_list.at(2);  // which drive this test pretends to be
144    DXGI_ADAPTER_DESC1 desc1{};
145    desc1.AdapterLuid = _LUID{10, 1000};
146    desc1.VendorId = known_driver.vendor_id;
147    env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
148    driver.set_adapterLUID(desc1.AdapterLuid);
149
150    env.platform_shim->add_d3dkmt_adapter(
151        D3DKMT_Adapter{0, desc1.AdapterLuid}.add_driver_manifest_path(env.get_icd_manifest_path(0)));
152
153    InstWrapper inst{env.vulkan_functions};
154    inst.CheckCreate();
155
156    ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
157    ASSERT_EQ(physical_count, returned_physical_count);
158    ASSERT_EQ(VK_SUCCESS,
159              env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
160    ASSERT_EQ(physical_count, returned_physical_count);
161    ASSERT_TRUE(driver.called_enumerate_adapter_physical_devices);
162
163    // Make sure that the loader doesn't write past the the end of the pointer
164    auto temp_ptr = std::unique_ptr<int>(new int());
165    for (auto& phys_dev : physical_device_handles) {
166        phys_dev = reinterpret_cast<VkPhysicalDevice>(temp_ptr.get());
167    }
168
169    ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
170    returned_physical_count = 0;
171    ASSERT_EQ(VK_INCOMPLETE,
172              env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
173    ASSERT_EQ(0U, returned_physical_count);
174    for (auto& phys_dev : physical_device_handles) {
175        ASSERT_EQ(phys_dev, reinterpret_cast<VkPhysicalDevice>(temp_ptr.get()));
176    }
177}
178
179// Declare drivers using the D3DKMT driver interface and make sure the loader can find them - but don't export
180// EnumerateAdapterPhysicalDevices
181TEST(ICDInterfaceVersion2, EnumAdapters2) {
182    FrameworkEnvironment env{};
183    auto& driver =
184        env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA}.set_discovery_type(ManifestDiscoveryType::null_dir));
185    InstWrapper inst{env.vulkan_functions};
186    driver.physical_devices.emplace_back("physical_device_1");
187    driver.physical_devices.emplace_back("physical_device_0");
188    uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
189    uint32_t returned_physical_count = static_cast<uint32_t>(driver.physical_devices.size());
190    std::vector<VkPhysicalDevice> physical_device_handles = std::vector<VkPhysicalDevice>(physical_count);
191    driver.adapterLUID = _LUID{10, 1000};
192    env.platform_shim->add_d3dkmt_adapter(D3DKMT_Adapter{0, _LUID{10, 1000}}.add_driver_manifest_path(env.get_icd_manifest_path()));
193
194    inst.CheckCreate();
195
196    ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
197    ASSERT_EQ(physical_count, returned_physical_count);
198    ASSERT_EQ(VK_SUCCESS,
199              env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
200    ASSERT_EQ(physical_count, returned_physical_count);
201    ASSERT_FALSE(driver.called_enumerate_adapter_physical_devices);
202}
203
204// Make sure that physical devices are found through EnumerateAdapterPhysicalDevices
205// Verify that the handles are correct by calling vkGetPhysicalDeviceProperties with them
206TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, VerifyPhysDevResults) {
207    FrameworkEnvironment env{};
208    auto& driver =
209        env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES, VK_API_VERSION_1_1}
210                        .set_discovery_type(ManifestDiscoveryType::null_dir))
211            .set_min_icd_interface_version(6)
212            .set_icd_api_version(VK_API_VERSION_1_1);
213    const std::vector<std::string> physical_device_names = {"physical_device_4", "physical_device_3", "physical_device_2",
214                                                            "physical_device_1", "physical_device_0"};
215    for (const auto& dev_name : physical_device_names) driver.physical_devices.push_back(dev_name);
216
217    auto& known_driver = known_driver_list.at(2);  // which drive this test pretends to be
218    DXGI_ADAPTER_DESC1 desc1{};
219    desc1.VendorId = known_driver.vendor_id;
220    desc1.AdapterLuid = _LUID{10, 1000};
221    env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
222    driver.set_adapterLUID(desc1.AdapterLuid);
223
224    env.platform_shim->add_d3dkmt_adapter(D3DKMT_Adapter{0, _LUID{10, 1000}}.add_driver_manifest_path(env.get_icd_manifest_path()));
225
226    InstWrapper inst{env.vulkan_functions};
227    inst.CheckCreate();
228
229    const size_t phys_dev_count = physical_device_names.size();
230
231    // The test ICD should completely swap the order of devices.
232    // Since we can't compare VkPhysicalDevice handles because they will be different per VkInstance, we will
233    // compare the property names returned, which should still be equal.
234
235    std::vector<VkPhysicalDevice> adapter_pds{phys_dev_count};
236    uint32_t count = static_cast<uint32_t>(adapter_pds.size());
237    ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &count, adapter_pds.data()));
238    ASSERT_EQ(phys_dev_count, count);
239
240    for (uint32_t dev = 0; dev < phys_dev_count; ++dev) {
241        VkPhysicalDeviceProperties props;
242        env.vulkan_functions.vkGetPhysicalDeviceProperties(adapter_pds[dev], &props);
243        std::string dev_name = props.deviceName;
244        // index in reverse
245        ASSERT_EQ(dev_name, physical_device_names[physical_device_names.size() - 1 - dev]);
246    }
247}
248
249// Make sure physical device groups enumerated through EnumerateAdapterPhysicalDevices are properly found
250TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, VerifyGroupResults) {
251    FrameworkEnvironment env{};
252    auto& driver =
253        env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES, VK_API_VERSION_1_1}
254                        .set_discovery_type(ManifestDiscoveryType::null_dir))
255            .set_min_icd_interface_version(6)
256            .set_icd_api_version(VK_API_VERSION_1_1);
257    const std::vector<std::string> physical_device_names = {"physical_device_4", "physical_device_3", "physical_device_2",
258                                                            "physical_device_1", "physical_device_0"};
259    for (const auto& dev_name : physical_device_names) {
260        driver.physical_devices.push_back(dev_name);
261    }
262
263    driver.physical_device_groups.emplace_back(driver.physical_devices[0]).use_physical_device(driver.physical_devices[1]);
264    driver.physical_device_groups.emplace_back(driver.physical_devices[2]);
265    driver.physical_device_groups.emplace_back(driver.physical_devices[3]).use_physical_device(driver.physical_devices[4]);
266
267    auto& known_driver = known_driver_list.at(2);  // which driver this test pretends to be
268    DXGI_ADAPTER_DESC1 desc1{};
269    desc1.VendorId = known_driver.vendor_id;
270    desc1.AdapterLuid = _LUID{10, 1000};
271    env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
272    driver.set_adapterLUID(desc1.AdapterLuid);
273
274    env.platform_shim->add_d3dkmt_adapter(D3DKMT_Adapter{0, _LUID{10, 1000}}.add_driver_manifest_path(env.get_icd_manifest_path()));
275
276    InstWrapper inst{env.vulkan_functions};
277    inst.CheckCreate();
278
279    // The test ICD should completely swap the order of devices.
280    // Since we can't compare VkPhysicalDevice handles because they will be different per VkInstance, we will
281    // compare the property names returned, which should still be equal.
282    // And, since this is device groups, the groups themselves should also be in reverse order with the devices
283    // inside each group in revers order.
284
285    const uint32_t actual_group_count = 3;
286    uint32_t count = actual_group_count;
287    std::array<VkPhysicalDeviceGroupProperties, actual_group_count> groups{};
288    for (uint32_t group = 0; group < actual_group_count; ++group) {
289        groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
290    }
291    ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &count, groups.data()));
292    ASSERT_EQ(actual_group_count, count);
293
294    size_t cur_device_name_index = physical_device_names.size() - 1;  // start at last index and reverse through it
295    for (uint32_t group = 0; group < actual_group_count; ++group) {
296        for (uint32_t dev = 0; dev < groups[group].physicalDeviceCount; ++dev) {
297            VkPhysicalDeviceProperties props;
298            env.vulkan_functions.vkGetPhysicalDeviceProperties(groups[group].physicalDevices[dev], &props);
299            std::string dev_name = props.deviceName;
300            ASSERT_EQ(dev_name, physical_device_names[cur_device_name_index]);
301            cur_device_name_index--;
302        }
303    }
304}
305
306#endif  // defined(WIN32)
307TEST(ICDInterfaceVersion7, SingleDriver) {
308    FrameworkEnvironment env{};
309    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7_WITH_ADDITIONAL_EXPORTS)).add_physical_device({});
310    InstWrapper inst{env.vulkan_functions};
311    inst.CheckCreate();
312    DeviceWrapper dev{inst};
313    dev.CheckCreate(inst.GetPhysDev());
314    ASSERT_EQ(driver.interface_version_check, InterfaceVersionCheck::version_is_supported);
315}
316
317TEST(ICDInterfaceVersion7, SingleDriverWithoutExportedFunctions) {
318    FrameworkEnvironment env{};
319    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7)).add_physical_device({});
320    InstWrapper inst{env.vulkan_functions};
321    inst.CheckCreate();
322    DeviceWrapper dev{inst};
323    dev.CheckCreate(inst.GetPhysDev());
324    ASSERT_EQ(driver.interface_version_check, InterfaceVersionCheck::version_is_supported);
325}
326
327TEST(MultipleICDConfig, Basic) {
328    FrameworkEnvironment env{};
329    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
330    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
331    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
332
333    env.get_test_icd(0).physical_devices.emplace_back("physical_device_0");
334    env.get_test_icd(1).physical_devices.emplace_back("physical_device_1");
335    env.get_test_icd(2).physical_devices.emplace_back("physical_device_2");
336
337    env.get_test_icd(0).physical_devices.at(0).properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
338    env.get_test_icd(1).physical_devices.at(0).properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
339    env.get_test_icd(2).physical_devices.at(0).properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_CPU;
340
341    copy_string_to_char_array("dev0", env.get_test_icd(0).physical_devices.at(0).properties.deviceName, VK_MAX_EXTENSION_NAME_SIZE);
342    copy_string_to_char_array("dev1", env.get_test_icd(1).physical_devices.at(0).properties.deviceName, VK_MAX_EXTENSION_NAME_SIZE);
343    copy_string_to_char_array("dev2", env.get_test_icd(2).physical_devices.at(0).properties.deviceName, VK_MAX_EXTENSION_NAME_SIZE);
344
345    InstWrapper inst{env.vulkan_functions};
346    inst.CheckCreate();
347
348    std::array<VkPhysicalDevice, 3> phys_devs_array;
349    uint32_t phys_dev_count = 3;
350    ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
351    ASSERT_EQ(phys_dev_count, 3U);
352    ASSERT_EQ(env.get_test_icd(0).physical_devices.at(0).properties.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
353    ASSERT_EQ(env.get_test_icd(1).physical_devices.at(0).properties.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
354    ASSERT_EQ(env.get_test_icd(2).physical_devices.at(0).properties.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
355}
356
357TEST(MultipleDriverConfig, DifferentICDInterfaceVersions) {
358    FrameworkEnvironment env{};
359    env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_ICD_GIPA));
360    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
361    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
362
363    TestICD& icd0 = env.get_test_icd(0);
364    icd0.physical_devices.emplace_back("physical_device_0");
365    icd0.max_icd_interface_version = 1;
366
367    TestICD& icd1 = env.get_test_icd(1);
368    icd1.physical_devices.emplace_back("physical_device_1");
369    icd1.min_icd_interface_version = 2;
370    icd1.max_icd_interface_version = 5;
371
372    InstWrapper inst{env.vulkan_functions};
373    inst.CheckCreate();
374
375    std::array<VkPhysicalDevice, 2> phys_devs_array;
376    uint32_t phys_dev_count = 2;
377    ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
378    ASSERT_EQ(phys_dev_count, 2U);
379}
380
381TEST(MultipleDriverConfig, DifferentICDsWithDevices) {
382    FrameworkEnvironment env{};
383    env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_ICD_GIPA));
384    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
385    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
386
387    // Make sure the loader returns all devices from all active ICDs.  Many of the other
388    // tests add multiple devices to a single ICD, this just makes sure the loader combines
389    // device info across multiple drivers properly.
390    TestICD& icd0 = env.get_test_icd(0);
391    icd0.physical_devices.emplace_back("physical_device_0");
392    icd0.min_icd_interface_version = 5;
393    icd0.max_icd_interface_version = 5;
394
395    TestICD& icd1 = env.get_test_icd(1);
396    icd1.physical_devices.emplace_back("physical_device_1");
397    icd1.physical_devices.emplace_back("physical_device_2");
398    icd1.min_icd_interface_version = 5;
399    icd1.max_icd_interface_version = 5;
400
401    TestICD& icd2 = env.get_test_icd(2);
402    icd2.physical_devices.emplace_back("physical_device_3");
403    icd2.min_icd_interface_version = 5;
404    icd2.max_icd_interface_version = 5;
405
406    InstWrapper inst{env.vulkan_functions};
407    inst.CheckCreate();
408
409    std::array<VkPhysicalDevice, 4> phys_devs_array;
410    uint32_t phys_dev_count = 4;
411    ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
412    ASSERT_EQ(phys_dev_count, 4U);
413}
414
415TEST(MultipleDriverConfig, DifferentICDsWithDevicesAndGroups) {
416    FrameworkEnvironment env{};
417    env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_ICD_GIPA));
418    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
419    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
420
421    // The loader has to be able to handle drivers that support device groups in combination
422    // with drivers that don't support device groups.  When this is the case, the loader needs
423    // to take every driver that doesn't support device groups and put each of its devices in
424    // a separate group.  Then it combines that information with the drivers that support
425    // device groups returned info.
426
427    // ICD 0 :  No 1.1 support (so 1 device will become 1 group in loader)
428    TestICD& icd0 = env.get_test_icd(0);
429    icd0.physical_devices.emplace_back("physical_device_0");
430    icd0.min_icd_interface_version = 5;
431    icd0.max_icd_interface_version = 5;
432    icd0.set_icd_api_version(VK_API_VERSION_1_0);
433
434    // ICD 1 :  1.1 support (with 1 group with 2 devices)
435    TestICD& icd1 = env.get_test_icd(1);
436    icd1.physical_devices.emplace_back("physical_device_1").set_api_version(VK_API_VERSION_1_1);
437    icd1.physical_devices.emplace_back("physical_device_2").set_api_version(VK_API_VERSION_1_1);
438    icd1.physical_device_groups.emplace_back(icd1.physical_devices[0]);
439    icd1.physical_device_groups.back().use_physical_device(icd1.physical_devices[1]);
440    icd1.min_icd_interface_version = 5;
441    icd1.max_icd_interface_version = 5;
442    icd1.set_icd_api_version(VK_API_VERSION_1_1);
443
444    // ICD 2 :  No 1.1 support (so 3 devices will become 3 groups in loader)
445    TestICD& icd2 = env.get_test_icd(2);
446    icd2.physical_devices.emplace_back("physical_device_3");
447    icd2.physical_devices.emplace_back("physical_device_4");
448    icd2.physical_devices.emplace_back("physical_device_5");
449    icd2.min_icd_interface_version = 5;
450    icd2.max_icd_interface_version = 5;
451    icd2.set_icd_api_version(VK_API_VERSION_1_0);
452
453    InstWrapper inst{env.vulkan_functions};
454    inst.create_info.set_api_version(1, 1, 0);
455    inst.CheckCreate();
456
457    uint32_t group_count = static_cast<uint32_t>(5);
458    uint32_t returned_group_count = 0;
459    ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, nullptr));
460    ASSERT_EQ(group_count, returned_group_count);
461
462    std::vector<VkPhysicalDeviceGroupProperties> group_props{};
463    group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
464    ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props.data()));
465    ASSERT_EQ(group_count, returned_group_count);
466}
467
468#if defined(WIN32)
469// This is testing when there are drivers that support the Windows device adapter sorting mechanism by exporting
470// EnumerateAdapterPhysicalDevices and drivers that do not expose that functionality
471TEST(MultipleICDConfig, version_5_and_version_6) {
472    FrameworkEnvironment env;
473
474    const char* regular_layer_name = "VK_LAYER_TestLayer1";
475    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
476                                                         .set_name(regular_layer_name)
477                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
478                                                         .set_api_version(VK_MAKE_API_VERSION(0, 1, 1, 0))
479                                                         .set_disable_environment("DisableMeIfYouCan")),
480                           "regular_test_layer.json");
481
482    MockQueueFamilyProperties family_props{{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true};
483
484    uint32_t physical_count = 0;
485    for (uint32_t i = 0; i < 3; i++) {
486        env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES));
487        env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
488        auto& driver_5 = env.get_test_icd(i * 2 + 1);
489        driver_5.set_max_icd_interface_version(5);
490        driver_5.set_min_icd_interface_version(5);
491        driver_5.setup_WSI();
492        driver_5.physical_devices.push_back({});
493        driver_5.physical_devices.back().queue_family_properties.push_back(family_props);
494        driver_5.physical_devices.push_back({});
495        driver_5.physical_devices.back().queue_family_properties.push_back(family_props);
496        driver_5.physical_devices.push_back({});
497        driver_5.physical_devices.back().queue_family_properties.push_back(family_props);
498        physical_count += static_cast<uint32_t>(driver_5.physical_devices.size());
499
500        auto& driver_6 = env.get_test_icd(i * 2);
501        driver_6.setup_WSI();
502        driver_6.physical_devices.emplace_back("physical_device_0");
503        driver_6.physical_devices.back().queue_family_properties.push_back(family_props);
504        driver_6.physical_devices.emplace_back("physical_device_1");
505        driver_6.physical_devices.back().queue_family_properties.push_back(family_props);
506        physical_count += static_cast<uint32_t>(driver_6.physical_devices.size());
507
508        driver_6.set_max_icd_interface_version(6);
509        driver_6.set_min_icd_interface_version(5);
510
511        uint32_t driver_index = i % 4;  // which drive this test pretends to be, must stay below 4
512        auto& known_driver = known_driver_list.at(driver_index);
513        DXGI_ADAPTER_DESC1 desc1{};
514        desc1.VendorId = known_driver.vendor_id;
515        desc1.AdapterLuid = LUID{100 + i, static_cast<LONG>(100 + i)};
516        driver_6.set_adapterLUID(desc1.AdapterLuid);
517        env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
518    }
519    uint32_t returned_physical_count = 0;
520    InstWrapper inst{env.vulkan_functions};
521    inst.create_info.setup_WSI();
522    inst.CheckCreate();
523
524    ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
525    ASSERT_EQ(physical_count, returned_physical_count);
526    std::vector<VkPhysicalDevice> physical_device_handles{returned_physical_count};
527    ASSERT_EQ(VK_SUCCESS,
528              env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
529    ASSERT_EQ(physical_count, returned_physical_count);
530
531    VkSurfaceKHR surface{};
532    ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
533    for (const auto& handle : physical_device_handles) {
534        handle_assert_has_value(handle);
535
536        VkBool32 supported = false;
537        EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(handle, 0, surface, &supported));
538    }
539    for (uint32_t i = 0; i < 3; i++) {
540        auto& driver_6 = env.get_test_icd(i * 2);
541        EXPECT_EQ(driver_6.called_enumerate_adapter_physical_devices, true);
542    }
543}
544#endif  // defined(WIN32)
545
546// shim function pointers for 1.3
547// Should use autogen for this - it generates 'shim' functions for validation layers, maybe that could be used here.
548void test_vkCmdBeginRendering(VkCommandBuffer, const VkRenderingInfo*) {}
549void test_vkCmdBindVertexBuffers2(VkCommandBuffer, uint32_t, uint32_t, const VkBuffer*, const VkDeviceSize*, const VkDeviceSize*,
550                                  const VkDeviceSize*) {}
551void test_vkCmdBlitImage2(VkCommandBuffer, const VkBlitImageInfo2*) {}
552void test_vkCmdCopyBuffer2(VkCommandBuffer, const VkCopyBufferInfo2*) {}
553void test_vkCmdCopyBufferToImage2(VkCommandBuffer, const VkCopyBufferToImageInfo2*) {}
554void test_vkCmdCopyImage2(VkCommandBuffer, const VkCopyImageInfo2*) {}
555void test_vkCmdCopyImageToBuffer2(VkCommandBuffer, const VkCopyImageToBufferInfo2*) {}
556void test_vkCmdEndRendering(VkCommandBuffer) {}
557void test_vkCmdPipelineBarrier2(VkCommandBuffer, const VkDependencyInfo*) {}
558void test_vkCmdResetEvent2(VkCommandBuffer, VkEvent, VkPipelineStageFlags2) {}
559void test_vkCmdResolveImage2(VkCommandBuffer, const VkResolveImageInfo2*) {}
560void test_vkCmdSetCullMode(VkCommandBuffer, VkCullModeFlags) {}
561void test_vkCmdSetDepthBiasEnable(VkCommandBuffer, VkBool32) {}
562void test_vkCmdSetDepthBoundsTestEnable(VkCommandBuffer, VkBool32) {}
563void test_vkCmdSetDepthCompareOp(VkCommandBuffer, VkCompareOp) {}
564void test_vkCmdSetDepthTestEnable(VkCommandBuffer, VkBool32) {}
565void test_vkCmdSetDepthWriteEnable(VkCommandBuffer, VkBool32) {}
566void test_vkCmdSetEvent2(VkCommandBuffer, VkEvent, const VkDependencyInfo*) {}
567void test_vkCmdSetFrontFace(VkCommandBuffer, VkFrontFace) {}
568void test_vkCmdSetPrimitiveRestartEnable(VkCommandBuffer, VkBool32) {}
569void test_vkCmdSetPrimitiveTopology(VkCommandBuffer, VkPrimitiveTopology) {}
570void test_vkCmdSetRasterizerDiscardEnable(VkCommandBuffer, VkBool32) {}
571void test_vkCmdSetScissorWithCount(VkCommandBuffer, uint32_t, const VkRect2D*) {}
572void test_vkCmdSetStencilOp(VkCommandBuffer, VkStencilFaceFlags, VkStencilOp, VkStencilOp, VkStencilOp, VkCompareOp) {}
573void test_vkCmdSetStencilTestEnable(VkCommandBuffer, VkBool32) {}
574void test_vkCmdSetViewportWithCount(VkCommandBuffer, uint32_t, const VkViewport*) {}
575void test_vkCmdWaitEvents2(VkCommandBuffer, uint32_t, const VkEvent*, const VkDependencyInfo*) {}
576void test_vkCmdWriteTimestamp2(VkCommandBuffer, VkPipelineStageFlags2, VkQueryPool, uint32_t) {}
577VkResult test_vkCreatePrivateDataSlot(VkDevice, const VkPrivateDataSlotCreateInfo*, const VkAllocationCallbacks*,
578                                      VkPrivateDataSlot*) {
579    return VK_SUCCESS;
580}
581void test_vkDestroyPrivateDataSlot(VkDevice, VkPrivateDataSlot, const VkAllocationCallbacks*) {}
582void test_vkGetDeviceBufferMemoryRequirements(VkDevice, const VkDeviceBufferMemoryRequirements*, VkMemoryRequirements2*) {}
583void test_vkGetDeviceImageMemoryRequirements(VkDevice, const VkDeviceImageMemoryRequirements*, VkMemoryRequirements2*) {}
584void test_vkGetDeviceImageSparseMemoryRequirements(VkDevice, const VkDeviceImageMemoryRequirements*, uint32_t*,
585                                                   VkSparseImageMemoryRequirements2*) {}
586void test_vkGetPrivateData(VkDevice, VkObjectType, uint64_t, VkPrivateDataSlot, uint64_t*) {}
587VkResult test_vkQueueSubmit2(VkQueue, uint32_t, const VkSubmitInfo2*, VkFence) { return VK_SUCCESS; }
588VkResult test_vkSetPrivateData(VkDevice, VkObjectType, uint64_t, VkPrivateDataSlot, uint64_t) { return VK_SUCCESS; }
589
590TEST(MinorVersionUpdate, Version1_3) {
591    FrameworkEnvironment env{};
592    auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
593    driver.physical_devices.back().known_device_functions = {
594        VulkanFunction{"vkCmdBeginRendering", to_vkVoidFunction(test_vkCmdBeginRendering)},
595        VulkanFunction{"vkCmdBindVertexBuffers2", to_vkVoidFunction(test_vkCmdBindVertexBuffers2)},
596        VulkanFunction{"vkCmdBlitImage2", to_vkVoidFunction(test_vkCmdBlitImage2)},
597        VulkanFunction{"vkCmdCopyBuffer2", to_vkVoidFunction(test_vkCmdCopyBuffer2)},
598        VulkanFunction{"vkCmdCopyBufferToImage2", to_vkVoidFunction(test_vkCmdCopyBufferToImage2)},
599        VulkanFunction{"vkCmdCopyImage2", to_vkVoidFunction(test_vkCmdCopyImage2)},
600        VulkanFunction{"vkCmdCopyImageToBuffer2", to_vkVoidFunction(test_vkCmdCopyImageToBuffer2)},
601        VulkanFunction{"vkCmdEndRendering", to_vkVoidFunction(test_vkCmdEndRendering)},
602        VulkanFunction{"vkCmdPipelineBarrier2", to_vkVoidFunction(test_vkCmdPipelineBarrier2)},
603        VulkanFunction{"vkCmdResetEvent2", to_vkVoidFunction(test_vkCmdResetEvent2)},
604        VulkanFunction{"vkCmdResolveImage2", to_vkVoidFunction(test_vkCmdResolveImage2)},
605        VulkanFunction{"vkCmdSetCullMode", to_vkVoidFunction(test_vkCmdSetCullMode)},
606        VulkanFunction{"vkCmdSetDepthBiasEnable", to_vkVoidFunction(test_vkCmdSetDepthBiasEnable)},
607        VulkanFunction{"vkCmdSetDepthBoundsTestEnable", to_vkVoidFunction(test_vkCmdSetDepthBoundsTestEnable)},
608        VulkanFunction{"vkCmdSetDepthCompareOp", to_vkVoidFunction(test_vkCmdSetDepthCompareOp)},
609        VulkanFunction{"vkCmdSetDepthTestEnable", to_vkVoidFunction(test_vkCmdSetDepthTestEnable)},
610        VulkanFunction{"vkCmdSetDepthWriteEnable", to_vkVoidFunction(test_vkCmdSetDepthWriteEnable)},
611        VulkanFunction{"vkCmdSetEvent2", to_vkVoidFunction(test_vkCmdSetEvent2)},
612        VulkanFunction{"vkCmdSetFrontFace", to_vkVoidFunction(test_vkCmdSetFrontFace)},
613        VulkanFunction{"vkCmdSetPrimitiveRestartEnable", to_vkVoidFunction(test_vkCmdSetPrimitiveRestartEnable)},
614        VulkanFunction{"vkCmdSetPrimitiveTopology", to_vkVoidFunction(test_vkCmdSetPrimitiveTopology)},
615        VulkanFunction{"vkCmdSetRasterizerDiscardEnable", to_vkVoidFunction(test_vkCmdSetRasterizerDiscardEnable)},
616        VulkanFunction{"vkCmdSetScissorWithCount", to_vkVoidFunction(test_vkCmdSetScissorWithCount)},
617        VulkanFunction{"vkCmdSetStencilOp", to_vkVoidFunction(test_vkCmdSetStencilOp)},
618        VulkanFunction{"vkCmdSetStencilTestEnable", to_vkVoidFunction(test_vkCmdSetStencilTestEnable)},
619        VulkanFunction{"vkCmdSetViewportWithCount", to_vkVoidFunction(test_vkCmdSetViewportWithCount)},
620        VulkanFunction{"vkCmdWaitEvents2", to_vkVoidFunction(test_vkCmdWaitEvents2)},
621        VulkanFunction{"vkCmdWriteTimestamp2", to_vkVoidFunction(test_vkCmdWriteTimestamp2)},
622        VulkanFunction{"vkCreatePrivateDataSlot", to_vkVoidFunction(test_vkCreatePrivateDataSlot)},
623        VulkanFunction{"vkDestroyPrivateDataSlot", to_vkVoidFunction(test_vkDestroyPrivateDataSlot)},
624        VulkanFunction{"vkGetDeviceBufferMemoryRequirements", to_vkVoidFunction(test_vkGetDeviceBufferMemoryRequirements)},
625        VulkanFunction{"vkGetDeviceImageMemoryRequirements", to_vkVoidFunction(test_vkGetDeviceImageMemoryRequirements)},
626        VulkanFunction{"vkGetDeviceImageSparseMemoryRequirements",
627                       to_vkVoidFunction(test_vkGetDeviceImageSparseMemoryRequirements)},
628        VulkanFunction{"vkGetPrivateData", to_vkVoidFunction(test_vkGetPrivateData)},
629        VulkanFunction{"vkQueueSubmit2", to_vkVoidFunction(test_vkQueueSubmit2)},
630        VulkanFunction{"vkSetPrivateData", to_vkVoidFunction(test_vkSetPrivateData)},
631    };
632    driver.physical_devices.back().add_extension({"VK_SOME_EXT_haha"});
633    InstWrapper inst{env.vulkan_functions};
634    inst.create_info.set_api_version(1, 3, 0);
635    inst.CheckCreate();
636
637    auto phys_dev = inst.GetPhysDev();
638
639    PFN_vkGetPhysicalDeviceToolProperties GetPhysicalDeviceToolProperties = inst.load("vkGetPhysicalDeviceToolProperties");
640    uint32_t tool_count = 0;
641    ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceToolProperties(phys_dev, &tool_count, nullptr));
642    ASSERT_EQ(tool_count, 0U);
643    VkPhysicalDeviceToolProperties props;
644    ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceToolProperties(phys_dev, &tool_count, &props));
645
646    DeviceWrapper device{inst};
647    device.CheckCreate(phys_dev);
648
649    PFN_vkCreateCommandPool CreateCommandPool = device.load("vkCreateCommandPool");
650    PFN_vkAllocateCommandBuffers AllocateCommandBuffers = device.load("vkAllocateCommandBuffers");
651    PFN_vkDestroyCommandPool DestroyCommandPool = device.load("vkDestroyCommandPool");
652    VkCommandPool command_pool{};
653    VkCommandPoolCreateInfo pool_create_info{};
654    pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
655    ASSERT_EQ(VK_SUCCESS, CreateCommandPool(device, &pool_create_info, nullptr, &command_pool));
656    VkCommandBufferAllocateInfo buffer_allocate_info{};
657    buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
658    buffer_allocate_info.commandPool = command_pool;
659    buffer_allocate_info.commandBufferCount = 1;
660    VkCommandBuffer command_buffer{};
661    ASSERT_EQ(VK_SUCCESS, AllocateCommandBuffers(device, &buffer_allocate_info, &command_buffer));
662    DestroyCommandPool(device, command_pool, nullptr);
663
664    PFN_vkCmdBeginRendering CmdBeginRendering = device.load("vkCmdBeginRendering");
665    VkRenderingInfoKHR rendering_info{};
666    CmdBeginRendering(command_buffer, &rendering_info);
667
668    PFN_vkCmdBindVertexBuffers2 CmdBindVertexBuffers2 = device.load("vkCmdBindVertexBuffers2");
669    CmdBindVertexBuffers2(command_buffer, 0, 0, nullptr, nullptr, nullptr, nullptr);
670
671    PFN_vkCmdBlitImage2 CmdBlitImage2 = device.load("vkCmdBlitImage2");
672    VkBlitImageInfo2 image_info{};
673    CmdBlitImage2(command_buffer, &image_info);
674
675    PFN_vkCmdCopyBuffer2 CmdCopyBuffer2 = device.load("vkCmdCopyBuffer2");
676    VkCopyBufferInfo2 copy_info{};
677    CmdCopyBuffer2(command_buffer, &copy_info);
678
679    PFN_vkCmdCopyBufferToImage2 CmdCopyBufferToImage2 = device.load("vkCmdCopyBufferToImage2");
680    VkCopyBufferToImageInfo2 copy_buf_image{};
681    CmdCopyBufferToImage2(command_buffer, &copy_buf_image);
682
683    PFN_vkCmdCopyImage2 CmdCopyImage2 = device.load("vkCmdCopyImage2");
684    VkCopyImageInfo2 copy_image_info{};
685    CmdCopyImage2(command_buffer, &copy_image_info);
686
687    PFN_vkCmdCopyImageToBuffer2 CmdCopyImageToBuffer2 = device.load("vkCmdCopyImageToBuffer2");
688    VkCopyImageToBufferInfo2 copy_image_buf;
689    CmdCopyImageToBuffer2(command_buffer, &copy_image_buf);
690
691    PFN_vkCmdEndRendering CmdEndRendering = device.load("vkCmdEndRendering");
692    CmdEndRendering(command_buffer);
693
694    PFN_vkCmdPipelineBarrier2 CmdPipelineBarrier2 = device.load("vkCmdPipelineBarrier2");
695    VkDependencyInfo deps_info;
696    CmdPipelineBarrier2(command_buffer, &deps_info);
697
698    PFN_vkCmdResetEvent2 CmdResetEvent2 = device.load("vkCmdResetEvent2");
699    CmdResetEvent2(command_buffer, {}, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
700
701    PFN_vkCmdResolveImage2 CmdResolveImage2 = device.load("vkCmdResolveImage2");
702    VkResolveImageInfo2 resolve_image{};
703    CmdResolveImage2(command_buffer, &resolve_image);
704
705    PFN_vkCmdSetCullMode CmdSetCullMode = device.load("vkCmdSetCullMode");
706    CmdSetCullMode(command_buffer, VK_CULL_MODE_BACK_BIT);
707
708    PFN_vkCmdSetDepthBiasEnable CmdSetDepthBiasEnable = device.load("vkCmdSetDepthBiasEnable");
709    CmdSetDepthBiasEnable(command_buffer, true);
710
711    PFN_vkCmdSetDepthBoundsTestEnable CmdSetDepthBoundsTestEnable = device.load("vkCmdSetDepthBoundsTestEnable");
712    CmdSetDepthBoundsTestEnable(command_buffer, true);
713
714    PFN_vkCmdSetDepthCompareOp CmdSetDepthCompareOp = device.load("vkCmdSetDepthCompareOp");
715    CmdSetDepthCompareOp(command_buffer, VK_COMPARE_OP_ALWAYS);
716
717    PFN_vkCmdSetDepthTestEnable CmdSetDepthTestEnable = device.load("vkCmdSetDepthTestEnable");
718    CmdSetDepthTestEnable(command_buffer, true);
719
720    PFN_vkCmdSetDepthWriteEnable CmdSetDepthWriteEnable = device.load("vkCmdSetDepthWriteEnable");
721    CmdSetDepthWriteEnable(command_buffer, true);
722
723    PFN_vkCmdSetEvent2 CmdSetEvent2 = device.load("vkCmdSetEvent2");
724    CmdSetEvent2(command_buffer, {}, &deps_info);
725
726    PFN_vkCmdSetFrontFace CmdSetFrontFace = device.load("vkCmdSetFrontFace");
727    CmdSetFrontFace(command_buffer, VK_FRONT_FACE_CLOCKWISE);
728
729    PFN_vkCmdSetPrimitiveRestartEnable CmdSetPrimitiveRestartEnable = device.load("vkCmdSetPrimitiveRestartEnable");
730    CmdSetPrimitiveRestartEnable(command_buffer, true);
731
732    PFN_vkCmdSetPrimitiveTopology CmdSetPrimitiveTopology = device.load("vkCmdSetPrimitiveTopology");
733    CmdSetPrimitiveTopology(command_buffer, VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
734
735    PFN_vkCmdSetRasterizerDiscardEnable CmdSetRasterizerDiscardEnable = device.load("vkCmdSetRasterizerDiscardEnable");
736    CmdSetRasterizerDiscardEnable(command_buffer, true);
737
738    PFN_vkCmdSetScissorWithCount CmdSetScissorWithCount = device.load("vkCmdSetScissorWithCount");
739    CmdSetScissorWithCount(command_buffer, 0, nullptr);
740
741    PFN_vkCmdSetStencilOp CmdSetStencilOp = device.load("vkCmdSetStencilOp");
742    CmdSetStencilOp(command_buffer, VK_STENCIL_FACE_BACK_BIT, VK_STENCIL_OP_DECREMENT_AND_WRAP, VK_STENCIL_OP_DECREMENT_AND_CLAMP,
743                    VK_STENCIL_OP_DECREMENT_AND_WRAP, VK_COMPARE_OP_ALWAYS);
744
745    PFN_vkCmdSetStencilTestEnable CmdSetStencilTestEnable = device.load("vkCmdSetStencilTestEnable");
746    CmdSetStencilTestEnable(command_buffer, true);
747
748    PFN_vkCmdSetViewportWithCount CmdSetViewportWithCount = device.load("vkCmdSetViewportWithCount");
749    CmdSetViewportWithCount(command_buffer, 0, nullptr);
750
751    PFN_vkCmdWaitEvents2 CmdWaitEvents2 = device.load("vkCmdWaitEvents2");
752    CmdWaitEvents2(command_buffer, 0, nullptr, &deps_info);
753
754    PFN_vkCmdWriteTimestamp2 CmdWriteTimestamp2 = device.load("vkCmdWriteTimestamp2");
755    CmdWriteTimestamp2(command_buffer, VK_PIPELINE_STAGE_2_BLIT_BIT, {}, 0);
756
757    PFN_vkCreatePrivateDataSlot CreatePrivateDataSlot = device.load("vkCreatePrivateDataSlot");
758    CreatePrivateDataSlot(device, nullptr, nullptr, nullptr);
759    PFN_vkDestroyPrivateDataSlot DestroyPrivateDataSlot = device.load("vkDestroyPrivateDataSlot");
760    DestroyPrivateDataSlot(device, VK_NULL_HANDLE, nullptr);
761    PFN_vkGetDeviceBufferMemoryRequirements GetDeviceBufferMemoryRequirements = device.load("vkGetDeviceBufferMemoryRequirements");
762    GetDeviceBufferMemoryRequirements(device, nullptr, nullptr);
763    PFN_vkGetDeviceImageMemoryRequirements GetDeviceImageMemoryRequirements = device.load("vkGetDeviceImageMemoryRequirements");
764    GetDeviceImageMemoryRequirements(device, nullptr, nullptr);
765    PFN_vkGetDeviceImageSparseMemoryRequirements GetDeviceImageSparseMemoryRequirements =
766        device.load("vkGetDeviceImageSparseMemoryRequirements");
767    GetDeviceImageSparseMemoryRequirements(device, nullptr, nullptr, nullptr);
768    PFN_vkGetPrivateData GetPrivateData = device.load("vkGetPrivateData");
769    GetPrivateData(device, VK_OBJECT_TYPE_UNKNOWN, 0, {}, nullptr);
770    PFN_vkQueueSubmit2 QueueSubmit2 = device.load("vkQueueSubmit2");
771    QueueSubmit2(nullptr, 0, nullptr, VK_NULL_HANDLE);
772    PFN_vkSetPrivateData SetPrivateData = device.load("vkSetPrivateData");
773    SetPrivateData(device, VK_OBJECT_TYPE_UNKNOWN, 0, {}, 0);
774}
775
776TEST(ApplicationInfoVersion, NonVulkanVariant) {
777    FrameworkEnvironment env{};
778    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
779
780    DebugUtilsLogger log;
781    InstWrapper inst{env.vulkan_functions};
782    inst.create_info.set_api_version(VK_MAKE_API_VERSION(1, 0, 0, 0));
783    FillDebugUtilsCreateDetails(inst.create_info, log);
784    inst.CheckCreate();
785    ASSERT_TRUE(log.find(
786        std::string("vkCreateInstance: The API Variant specified in pCreateInfo->pApplicationInfo.apiVersion is 1 instead of "
787                    "the expected value of 0.")));
788}
789
790TEST(DriverManifest, NonVulkanVariant) {
791    FrameworkEnvironment env{};
792    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(1, 1, 0, 0))).add_physical_device({});
793
794    DebugUtilsLogger log;
795    InstWrapper inst{env.vulkan_functions};
796    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
797    FillDebugUtilsCreateDetails(inst.create_info, log);
798    inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
799    ASSERT_TRUE(log.find("loader_parse_icd_manifest: Driver's ICD JSON "));
800    // log prints the path to the file, don't look for it since it is hard to determine inside the test what the path should be.
801    ASSERT_TRUE(log.find("\'api_version\' field contains a non-zero variant value of 1.  Skipping ICD JSON."));
802}
803
804TEST(LayerManifest, ImplicitNonVulkanVariant) {
805    FrameworkEnvironment env{};
806    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 0, 0))).add_physical_device({});
807
808    const char* implicit_layer_name = "ImplicitTestLayer";
809    env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
810                                                         .set_name(implicit_layer_name)
811                                                         .set_api_version(VK_MAKE_API_VERSION(1, 1, 0, 0))
812                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
813                                                         .set_disable_environment("DISABLE_ME")),
814                           "implicit_test_layer.json");
815
816    DebugUtilsLogger log;
817    InstWrapper inst{env.vulkan_functions};
818    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
819    FillDebugUtilsCreateDetails(inst.create_info, log);
820    inst.CheckCreate();
821    ASSERT_TRUE(log.find(std::string("Layer \"") + implicit_layer_name +
822                         "\" has an \'api_version\' field which contains a non-zero variant value of 1.  Skipping Layer."));
823}
824
825TEST(LayerManifest, ExplicitNonVulkanVariant) {
826    FrameworkEnvironment env{};
827    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 0, 0))).add_physical_device({});
828
829    const char* explicit_layer_name = "ExplicitTestLayer";
830    env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
831                                                         .set_name(explicit_layer_name)
832                                                         .set_api_version(VK_MAKE_API_VERSION(1, 1, 0, 0))
833                                                         .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
834                           "explicit_test_layer.json");
835
836    DebugUtilsLogger log;
837    InstWrapper inst{env.vulkan_functions};
838    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0)).add_layer(explicit_layer_name);
839    FillDebugUtilsCreateDetails(inst.create_info, log);
840    inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
841    ASSERT_TRUE(log.find(std::string("Layer \"") + explicit_layer_name +
842                         "\" has an \'api_version\' field which contains a non-zero variant value of 1.  Skipping Layer."));
843}
844
845TEST(DriverManifest, UnknownManifestVersion) {
846    FrameworkEnvironment env{};
847    env.add_icd(
848           TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_file_format_version({3, 2, 1})))
849        .add_physical_device({});
850
851    DebugUtilsLogger log;
852    InstWrapper inst{env.vulkan_functions};
853    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
854    FillDebugUtilsCreateDetails(inst.create_info, log);
855    inst.CheckCreate();
856    ASSERT_TRUE(log.find("loader_parse_icd_manifest: "));
857    // log prints the path to the file, don't look for it since it is hard to determine inside the test what the path should be.
858    ASSERT_TRUE(log.find("has unknown icd manifest file version 3.2.1. May cause errors."));
859}
860
861TEST(DriverManifest, LargeUnknownManifestVersion) {
862    FrameworkEnvironment env{};
863    env.add_icd(TestICDDetails(
864                    ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_file_format_version({100, 222, 111})))
865        .add_physical_device({});
866
867    DebugUtilsLogger log;
868    InstWrapper inst{env.vulkan_functions};
869    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
870    FillDebugUtilsCreateDetails(inst.create_info, log);
871    inst.CheckCreate();
872    ASSERT_TRUE(log.find("loader_parse_icd_manifest: "));
873    // log prints the path to the file, don't look for it since it is hard to determine inside the test what the path should be.
874    ASSERT_TRUE(log.find("has unknown icd manifest file version 100.222.111. May cause errors."));
875}
876
877TEST(LayerManifest, UnknownManifestVersion) {
878    FrameworkEnvironment env{};
879    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
880
881    const char* implicit_layer_name = "ImplicitTestLayer";
882    env.add_implicit_layer(ManifestLayer{}
883                               .add_layer(ManifestLayer::LayerDescription{}
884                                              .set_name(implicit_layer_name)
885                                              .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))
886                                              .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
887                                              .set_disable_environment("DISABLE_ME"))
888                               .set_file_format_version({3, 2, 1}),
889                           "implicit_test_layer.json");
890
891    DebugUtilsLogger log;
892    InstWrapper inst{env.vulkan_functions};
893    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
894    FillDebugUtilsCreateDetails(inst.create_info, log);
895    inst.CheckCreate();
896    ASSERT_TRUE(log.find("loader_add_layer_properties: "));
897    // log prints the path to the file, don't look for it since it is hard to determine inside the test what the path should be.
898    ASSERT_TRUE(log.find("has unknown layer manifest file version 3.2.1.  May cause errors."));
899}
900
901TEST(LayerManifest, LargeUnknownManifestVersion) {
902    FrameworkEnvironment env{};
903    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
904
905    const char* implicit_layer_name = "ImplicitTestLayer";
906    env.add_implicit_layer(ManifestLayer{}
907                               .add_layer(ManifestLayer::LayerDescription{}
908                                              .set_name(implicit_layer_name)
909                                              .set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))
910                                              .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
911                                              .set_disable_environment("DISABLE_ME"))
912                               .set_file_format_version({100, 222, 111}),
913                           "implicit_test_layer.json");
914
915    DebugUtilsLogger log;
916    InstWrapper inst{env.vulkan_functions};
917    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
918    FillDebugUtilsCreateDetails(inst.create_info, log);
919    inst.CheckCreate();
920    ASSERT_TRUE(log.find("loader_add_layer_properties: "));
921    // log prints the path to the file, don't look for it since it is hard to determine inside the test what the path should be.
922    ASSERT_TRUE(log.find("has unknown layer manifest file version 100.222.111.  May cause errors."));
923}
924
925struct DriverInfo {
926    DriverInfo(TestICDDetails icd_details, uint32_t driver_version, bool expect_to_find) noexcept
927        : icd_details(icd_details), driver_version(driver_version), expect_to_find(expect_to_find) {}
928    TestICDDetails icd_details;
929    uint32_t driver_version = 0;
930    bool expect_to_find = false;
931};
932
933void CheckDirectDriverLoading(FrameworkEnvironment& env, std::vector<DriverInfo> const& normal_drivers,
934                              std::vector<DriverInfo> const& direct_drivers, bool exclusive) {
935    std::vector<VkDirectDriverLoadingInfoLUNARG> ddl_infos;
936    uint32_t expected_driver_count = 0;
937
938    for (auto const& driver : direct_drivers) {
939        auto& direct_driver_icd = env.add_icd(driver.icd_details);
940        direct_driver_icd.physical_devices.push_back({});
941        direct_driver_icd.physical_devices.at(0).properties.driverVersion = driver.driver_version;
942        VkDirectDriverLoadingInfoLUNARG ddl_info{};
943        ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
944        ddl_info.pfnGetInstanceProcAddr = env.icds.back().icd_library.get_symbol("vk_icdGetInstanceProcAddr");
945        ddl_infos.push_back(ddl_info);
946        if (driver.expect_to_find) {
947            expected_driver_count++;
948        }
949    }
950
951    for (auto const& driver : normal_drivers) {
952        auto& direct_driver_icd = env.add_icd(driver.icd_details);
953        direct_driver_icd.physical_devices.push_back({});
954        direct_driver_icd.physical_devices.at(0).properties.driverVersion = driver.driver_version;
955        if (!exclusive && driver.expect_to_find) {
956            expected_driver_count++;
957        }
958    }
959
960    VkDirectDriverLoadingListLUNARG ddl_list{};
961    ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
962    ddl_list.mode = exclusive ? VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG : VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
963    ddl_list.driverCount = static_cast<uint32_t>(ddl_infos.size());
964    ddl_list.pDrivers = ddl_infos.data();
965
966    DebugUtilsLogger log;
967    InstWrapper inst{env.vulkan_functions};
968    FillDebugUtilsCreateDetails(inst.create_info, log);
969    log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
970    inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
971    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
972    ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
973
974    if (exclusive) {
975        ASSERT_TRUE(
976            log.find("loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension is active and specified "
977                     "VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG, skipping system and environment "
978                     "variable driver search mechanisms."));
979    }
980
981    // Make sure all drivers we expect to load were found - including checking that the pfn matches exactly.
982    for (uint32_t i = 0; i < direct_drivers.size(); i++) {
983        if (direct_drivers.at(i).expect_to_find) {
984            std::stringstream ss;
985            ss << "loader_add_direct_driver: Adding driver found in index " << i
986               << " of VkDirectDriverLoadingListLUNARG::pDrivers structure. pfnGetInstanceProcAddr was set to "
987               << reinterpret_cast<const void*>(ddl_infos.at(i).pfnGetInstanceProcAddr);
988            std::string log_message = ss.str();
989            ASSERT_TRUE(log.find(log_message));
990        }
991    }
992
993    auto phys_devs = inst.GetPhysDevs();
994    ASSERT_EQ(phys_devs.size(), expected_driver_count);
995
996    // We have to iterate through the driver lists backwards because the loader *prepends* icd's, so the last found ICD is found
997    // first in the driver list
998    uint32_t driver_index = 0;
999    for (size_t i = normal_drivers.size() - 1; i == 0; i--) {
1000        if (normal_drivers.at(i).expect_to_find) {
1001            VkPhysicalDeviceProperties props{};
1002            inst.functions->vkGetPhysicalDeviceProperties(phys_devs.at(driver_index), &props);
1003            ASSERT_EQ(props.driverVersion, normal_drivers.at(i).driver_version);
1004            driver_index++;
1005        }
1006    }
1007    for (size_t i = direct_drivers.size() - 1; i == 0; i--) {
1008        if (direct_drivers.at(i).expect_to_find) {
1009            VkPhysicalDeviceProperties props{};
1010            inst.functions->vkGetPhysicalDeviceProperties(phys_devs.at(driver_index), &props);
1011            ASSERT_EQ(props.driverVersion, direct_drivers.at(i).driver_version);
1012            driver_index++;
1013        }
1014    }
1015}
1016
1017// Only 1 direct driver
1018TEST(DirectDriverLoading, Individual) {
1019    FrameworkEnvironment env{};
1020    std::vector<DriverInfo> normal_drivers;
1021    std::vector<DriverInfo> direct_drivers;
1022    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 10, true);
1023
1024    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
1025}
1026
1027// 2 direct drivers
1028TEST(DirectDriverLoading, MultipleDirectDrivers) {
1029    FrameworkEnvironment env{};
1030    std::vector<DriverInfo> normal_drivers;
1031    std::vector<DriverInfo> direct_drivers;
1032    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 13, true);
1033    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 7, true);
1034    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
1035}
1036
1037// Multiple direct drivers with a normal driver in the middle
1038TEST(DirectDriverLoading, MultipleDirectDriversAndNormalDrivers) {
1039    FrameworkEnvironment env{};
1040    std::vector<DriverInfo> normal_drivers;
1041    std::vector<DriverInfo> direct_drivers;
1042    normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA), 90, true);
1043    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 80, true);
1044    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 70, true);
1045    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
1046}
1047
1048// Normal driver and direct driver with direct driver exclusivity
1049TEST(DirectDriverLoading, ExclusiveWithNormalDriver) {
1050    FrameworkEnvironment env{};
1051    std::vector<DriverInfo> normal_drivers;
1052    std::vector<DriverInfo> direct_drivers;
1053    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 33, true);
1054    normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2), 44, false);
1055    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
1056}
1057
1058TEST(DirectDriverLoading, ExclusiveWithMultipleNormalDriver) {
1059    FrameworkEnvironment env{};
1060    std::vector<DriverInfo> normal_drivers;
1061    std::vector<DriverInfo> direct_drivers;
1062    normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2), 55, true);
1063    normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2), 66, true);
1064    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 77, true);
1065    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
1066}
1067
1068TEST(DirectDriverLoading, ExclusiveWithDriverEnvVar) {
1069    FrameworkEnvironment env{};
1070    std::vector<DriverInfo> normal_drivers;
1071    std::vector<DriverInfo> direct_drivers;
1072    normal_drivers.emplace_back(
1073        TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::env_var), 4, false);
1074    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 5, true);
1075    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
1076}
1077
1078TEST(DirectDriverLoading, ExclusiveWithAddDriverEnvVar) {
1079    FrameworkEnvironment env{};
1080    std::vector<DriverInfo> normal_drivers;
1081    std::vector<DriverInfo> direct_drivers;
1082
1083    normal_drivers.emplace_back(
1084        TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::add_env_var), 6, false);
1085    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 7, true);
1086    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
1087}
1088
1089TEST(DirectDriverLoading, InclusiveWithFilterSelect) {
1090    FrameworkEnvironment env{};
1091    std::vector<DriverInfo> normal_drivers;
1092    std::vector<DriverInfo> direct_drivers;
1093
1094    EnvVarWrapper driver_filter_select_env_var{"VK_LOADER_DRIVERS_SELECT", "normal_driver.json"};
1095
1096    normal_drivers.emplace_back(
1097        TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 8, true);
1098    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 9, true);
1099
1100    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
1101}
1102
1103TEST(DirectDriverLoading, ExclusiveWithFilterSelect) {
1104    FrameworkEnvironment env{};
1105    std::vector<DriverInfo> normal_drivers;
1106    std::vector<DriverInfo> direct_drivers;
1107
1108    EnvVarWrapper driver_filter_select_env_var{"VK_LOADER_DRIVERS_SELECT", "normal_driver.json"};
1109
1110    normal_drivers.emplace_back(
1111        TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 10,
1112        false);
1113    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 11, true);
1114
1115    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
1116}
1117
1118TEST(DirectDriverLoading, InclusiveWithFilterDisable) {
1119    FrameworkEnvironment env{};
1120    std::vector<DriverInfo> normal_drivers;
1121    std::vector<DriverInfo> direct_drivers;
1122
1123    EnvVarWrapper driver_filter_disable_env_var{"VK_LOADER_DRIVERS_DISABLE", "normal_driver.json"};
1124
1125    normal_drivers.emplace_back(
1126        TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 12,
1127        false);
1128    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 13, true);
1129    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
1130}
1131
1132TEST(DirectDriverLoading, ExclusiveWithFilterDisable) {
1133    FrameworkEnvironment env{};
1134    std::vector<DriverInfo> normal_drivers;
1135    std::vector<DriverInfo> direct_drivers;
1136
1137    EnvVarWrapper driver_filter_disable_env_var{"VK_LOADER_DRIVERS_DISABLE", "normal_driver.json"};
1138
1139    normal_drivers.emplace_back(
1140        TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 14,
1141        false);
1142    direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 15, true);
1143    ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
1144}
1145
1146// The VK_LUNARG_direct_driver_loading extension is not enabled
1147TEST(DirectDriverLoading, ExtensionNotEnabled) {
1148    FrameworkEnvironment env{};
1149
1150    auto& direct_driver_icd = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none));
1151    direct_driver_icd.physical_devices.push_back({});
1152
1153    VkDirectDriverLoadingInfoLUNARG ddl_info{};
1154    ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
1155    ddl_info.pfnGetInstanceProcAddr = env.icds.back().icd_library.get_symbol("vk_icdGetInstanceProcAddr");
1156
1157    VkDirectDriverLoadingListLUNARG ddl_list{};
1158    ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
1159    ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
1160    ddl_list.driverCount = 1U;
1161    ddl_list.pDrivers = &ddl_info;
1162
1163    DebugUtilsLogger log;
1164    InstWrapper inst{env.vulkan_functions};
1165    FillDebugUtilsCreateDetails(inst.create_info, log);
1166    log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
1167    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
1168    ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
1169
1170    ASSERT_TRUE(
1171        log.find("loader_scan_for_direct_drivers: The pNext chain of VkInstanceCreateInfo contained the "
1172                 "VkDirectDriverLoadingListLUNARG structure, but the VK_LUNARG_direct_driver_loading extension was "
1173                 "not enabled."));
1174}
1175
1176// VkDirectDriverLoadingListLUNARG is not in the pNext chain of VkInstanceCreateInfo
1177TEST(DirectDriverLoading, DriverListNotInPnextChain) {
1178    FrameworkEnvironment env{};
1179
1180    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none)).add_physical_device({});
1181
1182    DebugUtilsLogger log;
1183    InstWrapper inst{env.vulkan_functions};
1184    FillDebugUtilsCreateDetails(inst.create_info, log);
1185    inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
1186    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
1187    ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
1188
1189    ASSERT_TRUE(
1190        log.find("loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension was enabled but the pNext chain of "
1191                 "VkInstanceCreateInfo did not contain the "
1192                 "VkDirectDriverLoadingListLUNARG structure."));
1193}
1194
1195// User sets the pDrivers pointer in VkDirectDriverLoadingListLUNARG to nullptr
1196TEST(DirectDriverLoading, DriverListHasNullDriverPointer) {
1197    FrameworkEnvironment env{};
1198
1199    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none)).add_physical_device({});
1200
1201    VkDirectDriverLoadingListLUNARG ddl_list{};
1202    ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
1203    ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
1204    ddl_list.driverCount = 1U;
1205    ddl_list.pDrivers = nullptr;  // user forgot to set the pDrivers
1206
1207    DebugUtilsLogger log;
1208    InstWrapper inst{env.vulkan_functions};
1209    FillDebugUtilsCreateDetails(inst.create_info, log);
1210    log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
1211    inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
1212    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
1213    ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
1214
1215    ASSERT_TRUE(
1216        log.find("loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
1217                 "VkInstanceCreateInfo has a NULL pDrivers member."));
1218}
1219
1220// User sets the driverCount in VkDirectDriverLoadingListLUNARG to zero
1221TEST(DirectDriverLoading, DriverListHasZeroInfoCount) {
1222    FrameworkEnvironment env{};
1223
1224    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none)).add_physical_device({});
1225
1226    VkDirectDriverLoadingInfoLUNARG ddl_info{};
1227    ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
1228    ddl_info.pfnGetInstanceProcAddr = env.icds.back().icd_library.get_symbol("vk_icdGetInstanceProcAddr");
1229
1230    VkDirectDriverLoadingListLUNARG ddl_list{};
1231    ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
1232    ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
1233    ddl_list.driverCount = 0;  // user set 0 for the info list
1234    ddl_list.pDrivers = &ddl_info;
1235
1236    DebugUtilsLogger log;
1237    InstWrapper inst{env.vulkan_functions};
1238    FillDebugUtilsCreateDetails(inst.create_info, log);
1239    log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
1240    inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
1241    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
1242    ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
1243
1244    ASSERT_TRUE(
1245        log.find("loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
1246                 "VkInstanceCreateInfo has a non-null pDrivers member but a driverCount member with a value "
1247                 "of zero."));
1248}
1249
1250// pfnGetInstanceProcAddr in VkDirectDriverLoadingInfoLUNARG is nullptr
1251TEST(DirectDriverLoading, DriverInfoMissingGetInstanceProcAddr) {
1252    FrameworkEnvironment env{};
1253
1254    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none)).add_physical_device({});
1255
1256    std::array<VkDirectDriverLoadingInfoLUNARG, 2> ddl_infos{};
1257    ddl_infos[0].sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
1258    ddl_infos[0].pfnGetInstanceProcAddr = nullptr;  // user didn't set the pfnGetInstanceProcAddr to the driver's handle
1259
1260    ddl_infos[1].sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
1261    ddl_infos[1].pfnGetInstanceProcAddr = nullptr;  // user didn't set the pfnGetInstanceProcAddr to the driver's handle
1262
1263    VkDirectDriverLoadingListLUNARG ddl_list{};
1264    ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
1265    ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
1266    ddl_list.driverCount = static_cast<uint32_t>(ddl_infos.size());
1267    ddl_list.pDrivers = ddl_infos.data();
1268
1269    DebugUtilsLogger log;
1270    InstWrapper inst{env.vulkan_functions};
1271    FillDebugUtilsCreateDetails(inst.create_info, log);
1272    log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
1273    inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
1274    inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
1275    ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
1276
1277    ASSERT_TRUE(
1278        log.find("loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index 0 contains a NULL pointer for the "
1279                 "pfnGetInstanceProcAddr member, skipping."));
1280    ASSERT_TRUE(
1281        log.find("loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index 1 contains a NULL pointer for the "
1282                 "pfnGetInstanceProcAddr member, skipping."));
1283}
1284
1285// test the various error paths in loader_add_direct_driver
1286TEST(DirectDriverLoading, DriverDoesNotExportNegotiateFunction) {
1287    FrameworkEnvironment env{};
1288
1289    auto& direct_driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none))
1290                              .add_physical_device({})
1291                              .set_exposes_vk_icdNegotiateLoaderICDInterfaceVersion(false)
1292                              .set_exposes_vkCreateInstance(false)
1293                              .set_exposes_vkEnumerateInstanceExtensionProperties(false);
1294
1295    VkDirectDriverLoadingInfoLUNARG ddl_info{};
1296    ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
1297    ddl_info.pfnGetInstanceProcAddr = env.icds.back().icd_library.get_symbol("vk_icdGetInstanceProcAddr");
1298
1299    VkDirectDriverLoadingListLUNARG ddl_list{};
1300    ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
1301    ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
1302    ddl_list.driverCount = 1;
1303    ddl_list.pDrivers = &ddl_info;
1304
1305    {
1306        DebugUtilsLogger log;
1307        InstWrapper inst{env.vulkan_functions};
1308        FillDebugUtilsCreateDetails(inst.create_info, log);
1309        log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
1310        inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
1311        inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
1312        ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
1313
1314        ASSERT_TRUE(
1315            log.find("loader_add_direct_driver: Could not get 'vk_icdNegotiateLoaderICDInterfaceVersion' from "
1316                     "VkDirectDriverLoadingInfoLUNARG structure at "
1317                     "index 0, skipping."));
1318    }
1319
1320    // Allow the negotiate function to be found, now it should fail to find instance creation function
1321    direct_driver.set_exposes_vk_icdNegotiateLoaderICDInterfaceVersion(true);
1322    direct_driver.set_max_icd_interface_version(4);
1323
1324    {
1325        DebugUtilsLogger log;
1326        InstWrapper inst{env.vulkan_functions};
1327        FillDebugUtilsCreateDetails(inst.create_info, log);
1328        log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
1329        inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
1330        inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
1331        ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
1332
1333        ASSERT_TRUE(log.find(
1334            "loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index 0 supports interface version 4, "
1335            "which is incompatible with the Loader Driver Interface version that supports the VK_LUNARG_direct_driver_loading "
1336            "extension, skipping."));
1337    }
1338    direct_driver.set_max_icd_interface_version(7);
1339
1340    {
1341        DebugUtilsLogger log;
1342        InstWrapper inst{env.vulkan_functions};
1343        FillDebugUtilsCreateDetails(inst.create_info, log);
1344        log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
1345        inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
1346        inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
1347        ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
1348
1349        ASSERT_TRUE(
1350            log.find("loader_add_direct_driver: Could not get 'vkEnumerateInstanceExtensionProperties' from "
1351                     "VkDirectDriverLoadingInfoLUNARG structure at index 0, skipping."));
1352    }
1353
1354    // Allow the instance creation function to be found, now it should fail to find EnumInstExtProps
1355    direct_driver.set_exposes_vkCreateInstance(true);
1356
1357    {
1358        DebugUtilsLogger log;
1359        InstWrapper inst{env.vulkan_functions};
1360        FillDebugUtilsCreateDetails(inst.create_info, log);
1361        log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
1362        inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
1363        inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
1364        ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
1365
1366        ASSERT_TRUE(
1367            log.find("loader_add_direct_driver: Could not get 'vkEnumerateInstanceExtensionProperties' from "
1368                     "VkDirectDriverLoadingInfoLUNARG structure at index 0, skipping."));
1369    }
1370}
1371
1372TEST(DriverManifest, VersionMismatchWithEnumerateInstanceVersion) {
1373    FrameworkEnvironment env{};
1374    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
1375        .set_icd_api_version(VK_API_VERSION_1_0)
1376        .add_physical_device({});
1377
1378    InstWrapper inst{env.vulkan_functions};
1379    inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
1380    FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
1381    inst.CheckCreate();
1382
1383    ASSERT_TRUE(env.debug_log.find(std::string("terminator_CreateInstance: Manifest ICD for \"") + env.get_test_icd_path().str() +
1384                                   "\" contained a 1.1 or greater API version, but "
1385                                   "vkEnumerateInstanceVersion returned 1.0, treating as a 1.0 ICD"));
1386}
1387
1388TEST(DriverManifest, EnumerateInstanceVersionNotSupported) {
1389    FrameworkEnvironment env{};
1390    env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
1391        .set_icd_api_version(VK_API_VERSION_1_0)
1392        .set_can_query_vkEnumerateInstanceVersion(false)
1393        .add_physical_device({});
1394
1395    InstWrapper inst{env.vulkan_functions};
1396    inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
1397    FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
1398    inst.CheckCreate();
1399
1400    ASSERT_TRUE(env.debug_log.find(std::string("terminator_CreateInstance: Manifest ICD for \"") + env.get_test_icd_path().str() +
1401                                   "\" contained a 1.1 or greater API version, but does "
1402                                   "not support vkEnumerateInstanceVersion, treating as a 1.0 ICD"));
1403}
1404