blob: 28191fc38daeb94e81cd5ba90986bb70f9560a40 [file] [log] [blame]
/*
* Copyright (c) 2021-2023 The Khronos Group Inc.
* Copyright (c) 2021-2023 Valve Corporation
* Copyright (c) 2021-2023 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
* deal in the Materials without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Materials, and to permit persons to whom the Materials are
* furnished to do so, subject to the following conditions:
*
* The above copyright notice(s) and this permission notice shall be included in
* all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
*
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
* USE OR OTHER DEALINGS IN THE MATERIALS.
*
* Author: Charles Giessen <charles@lunarg.com>
*/
#include "test_environment.h"
TEST(ICDInterfaceVersion2Plus, vk_icdNegotiateLoaderICDInterfaceVersion) {
FrameworkEnvironment env{};
auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
for (uint32_t i = 0; i <= 6; i++) {
for (uint32_t j = i; j <= 6; j++) {
driver.set_min_icd_interface_version(i).set_max_icd_interface_version(j);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
}
}
}
TEST(ICDInterfaceVersion2Plus, version_3) {
FrameworkEnvironment env{};
auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
{
driver.set_min_icd_interface_version(2).set_enable_icd_wsi(true);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
ASSERT_FALSE(driver.is_using_icd_wsi);
}
{
driver.set_min_icd_interface_version(3).set_enable_icd_wsi(false);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
ASSERT_FALSE(driver.is_using_icd_wsi);
}
{
driver.set_min_icd_interface_version(3).set_enable_icd_wsi(true);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
ASSERT_TRUE(driver.is_using_icd_wsi);
}
}
TEST(ICDInterfaceVersion2Plus, version_4) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0");
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
}
TEST(ICDInterfaceVersion2Plus, l4_icd4) {
// TODO:
// ICD must fail with VK_ERROR_INCOMPATIBLE_DRIVER for all vkCreateInstance calls with apiVersion set to > Vulkan 1.0
// because both the loader and ICD support interface version <= 4. Otherwise, the ICD should behave as normal.
}
TEST(ICDInterfaceVersion2Plus, l4_icd5) {
// TODO:
// ICD must fail with VK_ERROR_INCOMPATIBLE_DRIVER for all vkCreateInstance calls with apiVersion set to > Vulkan 1.0
// because the loader is still at interface version <= 4. Otherwise, the ICD should behave as normal.
}
TEST(ICDInterfaceVersion2Plus, l5_icd4) {
// TODO:
// Loader will fail with VK_ERROR_INCOMPATIBLE_DRIVER if it can't handle the apiVersion. ICD may pass for all apiVersions,
// 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
// fail with VK_ERROR_INCOMPATIBLE_DRIVER. Otherwise, the ICD should behave as normal.
}
TEST(ICDInterfaceVersion2Plus, l5_icd5) {
// TODO:
// Loader will fail with VK_ERROR_INCOMPATIBLE_DRIVER if it can't handle the apiVersion, and ICDs should fail with
// VK_ERROR_INCOMPATIBLE_DRIVER only if they can not support the specified apiVersion. Otherwise, the ICD should behave as
// normal.
}
#if defined(WIN32)
// This test makes sure that EnumerateAdapterPhysicalDevices on drivers found in the Khronos/Vulkan/Drivers registry
TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, version_6_in_drivers_registry) {
FrameworkEnvironment env{};
auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES));
driver.physical_devices.emplace_back("physical_device_1");
driver.physical_devices.emplace_back("physical_device_0");
uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
uint32_t returned_physical_count = static_cast<uint32_t>(driver.physical_devices.size());
std::vector<VkPhysicalDevice> physical_device_handles = std::vector<VkPhysicalDevice>(physical_count);
driver.min_icd_interface_version = 5;
auto& known_driver = known_driver_list.at(2); // which drive this test pretends to be
DXGI_ADAPTER_DESC1 desc1{};
desc1.AdapterLuid = _LUID{10, 1000};
desc1.VendorId = known_driver.vendor_id;
env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
driver.set_adapterLUID(desc1.AdapterLuid);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
ASSERT_EQ(physical_count, returned_physical_count);
ASSERT_TRUE(driver.called_enumerate_adapter_physical_devices);
}
// Make the version_6 driver found through the D3DKMT driver discovery mechanism of the loader
TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, version_6) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_3}.set_discovery_type(ManifestDiscoveryType::null_dir));
// Version 6 provides a mechanism to allow the loader to sort physical devices.
// The loader will only attempt to sort physical devices on an ICD if version 6 of the interface is supported.
// This version provides the vk_icdEnumerateAdapterPhysicalDevices function.
auto& driver = env.get_test_icd(0);
driver.physical_devices.emplace_back("physical_device_1");
driver.physical_devices.emplace_back("physical_device_0");
uint32_t physical_count = 2;
uint32_t returned_physical_count = physical_count;
std::vector<VkPhysicalDevice> physical_device_handles{physical_count};
driver.min_icd_interface_version = 6;
auto& known_driver = known_driver_list.at(2); // which drive this test pretends to be
DXGI_ADAPTER_DESC1 desc1{};
desc1.AdapterLuid = _LUID{10, 1000};
desc1.VendorId = known_driver.vendor_id;
env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
driver.set_adapterLUID(desc1.AdapterLuid);
env.platform_shim->add_d3dkmt_adapter(
D3DKMT_Adapter{0, desc1.AdapterLuid}.add_driver_manifest_path(env.get_icd_manifest_path(0)));
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
ASSERT_EQ(physical_count, returned_physical_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
ASSERT_EQ(physical_count, returned_physical_count);
ASSERT_TRUE(driver.called_enumerate_adapter_physical_devices);
// Make sure that the loader doesn't write past the the end of the pointer
auto temp_ptr = std::unique_ptr<int>(new int());
for (auto& phys_dev : physical_device_handles) {
phys_dev = reinterpret_cast<VkPhysicalDevice>(temp_ptr.get());
}
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
returned_physical_count = 0;
ASSERT_EQ(VK_INCOMPLETE,
env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
ASSERT_EQ(0U, returned_physical_count);
for (auto& phys_dev : physical_device_handles) {
ASSERT_EQ(phys_dev, reinterpret_cast<VkPhysicalDevice>(temp_ptr.get()));
}
}
// Declare drivers using the D3DKMT driver interface and make sure the loader can find them - but don't export
// EnumerateAdapterPhysicalDevices
TEST(ICDInterfaceVersion2, EnumAdapters2) {
FrameworkEnvironment env{};
auto& driver =
env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA}.set_discovery_type(ManifestDiscoveryType::null_dir));
InstWrapper inst{env.vulkan_functions};
driver.physical_devices.emplace_back("physical_device_1");
driver.physical_devices.emplace_back("physical_device_0");
uint32_t physical_count = static_cast<uint32_t>(driver.physical_devices.size());
uint32_t returned_physical_count = static_cast<uint32_t>(driver.physical_devices.size());
std::vector<VkPhysicalDevice> physical_device_handles = std::vector<VkPhysicalDevice>(physical_count);
driver.adapterLUID = _LUID{10, 1000};
env.platform_shim->add_d3dkmt_adapter(D3DKMT_Adapter{0, _LUID{10, 1000}}.add_driver_manifest_path(env.get_icd_manifest_path()));
inst.CheckCreate();
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
ASSERT_EQ(physical_count, returned_physical_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
ASSERT_EQ(physical_count, returned_physical_count);
ASSERT_FALSE(driver.called_enumerate_adapter_physical_devices);
}
// Make sure that physical devices are found through EnumerateAdapterPhysicalDevices
// Verify that the handles are correct by calling vkGetPhysicalDeviceProperties with them
TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, VerifyPhysDevResults) {
FrameworkEnvironment env{};
auto& driver =
env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES, VK_API_VERSION_1_1}
.set_discovery_type(ManifestDiscoveryType::null_dir))
.set_min_icd_interface_version(6)
.set_icd_api_version(VK_API_VERSION_1_1);
const std::vector<std::string> physical_device_names = {"physical_device_4", "physical_device_3", "physical_device_2",
"physical_device_1", "physical_device_0"};
for (const auto& dev_name : physical_device_names) driver.physical_devices.push_back(dev_name);
auto& known_driver = known_driver_list.at(2); // which drive this test pretends to be
DXGI_ADAPTER_DESC1 desc1{};
desc1.VendorId = known_driver.vendor_id;
desc1.AdapterLuid = _LUID{10, 1000};
env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
driver.set_adapterLUID(desc1.AdapterLuid);
env.platform_shim->add_d3dkmt_adapter(D3DKMT_Adapter{0, _LUID{10, 1000}}.add_driver_manifest_path(env.get_icd_manifest_path()));
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
const size_t phys_dev_count = physical_device_names.size();
// The test ICD should completely swap the order of devices.
// Since we can't compare VkPhysicalDevice handles because they will be different per VkInstance, we will
// compare the property names returned, which should still be equal.
std::vector<VkPhysicalDevice> adapter_pds{phys_dev_count};
uint32_t count = static_cast<uint32_t>(adapter_pds.size());
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &count, adapter_pds.data()));
ASSERT_EQ(phys_dev_count, count);
for (uint32_t dev = 0; dev < phys_dev_count; ++dev) {
VkPhysicalDeviceProperties props;
env.vulkan_functions.vkGetPhysicalDeviceProperties(adapter_pds[dev], &props);
std::string dev_name = props.deviceName;
// index in reverse
ASSERT_EQ(dev_name, physical_device_names[physical_device_names.size() - 1 - dev]);
}
}
// Make sure physical device groups enumerated through EnumerateAdapterPhysicalDevices are properly found
TEST(ICDInterfaceVersion2PlusEnumerateAdapterPhysicalDevices, VerifyGroupResults) {
FrameworkEnvironment env{};
auto& driver =
env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES, VK_API_VERSION_1_1}
.set_discovery_type(ManifestDiscoveryType::null_dir))
.set_min_icd_interface_version(6)
.set_icd_api_version(VK_API_VERSION_1_1);
const std::vector<std::string> physical_device_names = {"physical_device_4", "physical_device_3", "physical_device_2",
"physical_device_1", "physical_device_0"};
for (const auto& dev_name : physical_device_names) {
driver.physical_devices.push_back(dev_name);
}
driver.physical_device_groups.emplace_back(driver.physical_devices[0]).use_physical_device(driver.physical_devices[1]);
driver.physical_device_groups.emplace_back(driver.physical_devices[2]);
driver.physical_device_groups.emplace_back(driver.physical_devices[3]).use_physical_device(driver.physical_devices[4]);
auto& known_driver = known_driver_list.at(2); // which driver this test pretends to be
DXGI_ADAPTER_DESC1 desc1{};
desc1.VendorId = known_driver.vendor_id;
desc1.AdapterLuid = _LUID{10, 1000};
env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
driver.set_adapterLUID(desc1.AdapterLuid);
env.platform_shim->add_d3dkmt_adapter(D3DKMT_Adapter{0, _LUID{10, 1000}}.add_driver_manifest_path(env.get_icd_manifest_path()));
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
// The test ICD should completely swap the order of devices.
// Since we can't compare VkPhysicalDevice handles because they will be different per VkInstance, we will
// compare the property names returned, which should still be equal.
// And, since this is device groups, the groups themselves should also be in reverse order with the devices
// inside each group in revers order.
const uint32_t actual_group_count = 3;
uint32_t count = actual_group_count;
std::array<VkPhysicalDeviceGroupProperties, actual_group_count> groups{};
for (uint32_t group = 0; group < actual_group_count; ++group) {
groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
}
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &count, groups.data()));
ASSERT_EQ(actual_group_count, count);
size_t cur_device_name_index = physical_device_names.size() - 1; // start at last index and reverse through it
for (uint32_t group = 0; group < actual_group_count; ++group) {
for (uint32_t dev = 0; dev < groups[group].physicalDeviceCount; ++dev) {
VkPhysicalDeviceProperties props;
env.vulkan_functions.vkGetPhysicalDeviceProperties(groups[group].physicalDevices[dev], &props);
std::string dev_name = props.deviceName;
ASSERT_EQ(dev_name, physical_device_names[cur_device_name_index]);
cur_device_name_index--;
}
}
}
#endif // defined(WIN32)
TEST(ICDInterfaceVersion7, SingleDriver) {
FrameworkEnvironment env{};
auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7_WITH_ADDITIONAL_EXPORTS)).add_physical_device({});
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
DeviceWrapper dev{inst};
dev.CheckCreate(inst.GetPhysDev());
ASSERT_EQ(driver.interface_version_check, InterfaceVersionCheck::version_is_supported);
}
TEST(ICDInterfaceVersion7, SingleDriverWithoutExportedFunctions) {
FrameworkEnvironment env{};
auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7)).add_physical_device({});
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
DeviceWrapper dev{inst};
dev.CheckCreate(inst.GetPhysDev());
ASSERT_EQ(driver.interface_version_check, InterfaceVersionCheck::version_is_supported);
}
TEST(MultipleICDConfig, Basic) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
env.get_test_icd(0).physical_devices.emplace_back("physical_device_0");
env.get_test_icd(1).physical_devices.emplace_back("physical_device_1");
env.get_test_icd(2).physical_devices.emplace_back("physical_device_2");
env.get_test_icd(0).physical_devices.at(0).properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
env.get_test_icd(1).physical_devices.at(0).properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
env.get_test_icd(2).physical_devices.at(0).properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_CPU;
copy_string_to_char_array("dev0", env.get_test_icd(0).physical_devices.at(0).properties.deviceName, VK_MAX_EXTENSION_NAME_SIZE);
copy_string_to_char_array("dev1", env.get_test_icd(1).physical_devices.at(0).properties.deviceName, VK_MAX_EXTENSION_NAME_SIZE);
copy_string_to_char_array("dev2", env.get_test_icd(2).physical_devices.at(0).properties.deviceName, VK_MAX_EXTENSION_NAME_SIZE);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
std::array<VkPhysicalDevice, 3> phys_devs_array;
uint32_t phys_dev_count = 3;
ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
ASSERT_EQ(phys_dev_count, 3U);
ASSERT_EQ(env.get_test_icd(0).physical_devices.at(0).properties.deviceType, VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU);
ASSERT_EQ(env.get_test_icd(1).physical_devices.at(0).properties.deviceType, VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU);
ASSERT_EQ(env.get_test_icd(2).physical_devices.at(0).properties.deviceType, VK_PHYSICAL_DEVICE_TYPE_CPU);
}
TEST(MultipleDriverConfig, DifferentICDInterfaceVersions) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_ICD_GIPA));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
TestICD& icd0 = env.get_test_icd(0);
icd0.physical_devices.emplace_back("physical_device_0");
icd0.max_icd_interface_version = 1;
TestICD& icd1 = env.get_test_icd(1);
icd1.physical_devices.emplace_back("physical_device_1");
icd1.min_icd_interface_version = 2;
icd1.max_icd_interface_version = 5;
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
std::array<VkPhysicalDevice, 2> phys_devs_array;
uint32_t phys_dev_count = 2;
ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
ASSERT_EQ(phys_dev_count, 2U);
}
TEST(MultipleDriverConfig, DifferentICDsWithDevices) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_ICD_GIPA));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
// Make sure the loader returns all devices from all active ICDs. Many of the other
// tests add multiple devices to a single ICD, this just makes sure the loader combines
// device info across multiple drivers properly.
TestICD& icd0 = env.get_test_icd(0);
icd0.physical_devices.emplace_back("physical_device_0");
icd0.min_icd_interface_version = 5;
icd0.max_icd_interface_version = 5;
TestICD& icd1 = env.get_test_icd(1);
icd1.physical_devices.emplace_back("physical_device_1");
icd1.physical_devices.emplace_back("physical_device_2");
icd1.min_icd_interface_version = 5;
icd1.max_icd_interface_version = 5;
TestICD& icd2 = env.get_test_icd(2);
icd2.physical_devices.emplace_back("physical_device_3");
icd2.min_icd_interface_version = 5;
icd2.max_icd_interface_version = 5;
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
std::array<VkPhysicalDevice, 4> phys_devs_array;
uint32_t phys_dev_count = 4;
ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
ASSERT_EQ(phys_dev_count, 4U);
}
TEST(MultipleDriverConfig, DifferentICDsWithDevicesAndGroups) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_ICD_GIPA));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
// The loader has to be able to handle drivers that support device groups in combination
// with drivers that don't support device groups. When this is the case, the loader needs
// to take every driver that doesn't support device groups and put each of its devices in
// a separate group. Then it combines that information with the drivers that support
// device groups returned info.
// ICD 0 : No 1.1 support (so 1 device will become 1 group in loader)
TestICD& icd0 = env.get_test_icd(0);
icd0.physical_devices.emplace_back("physical_device_0");
icd0.min_icd_interface_version = 5;
icd0.max_icd_interface_version = 5;
icd0.set_icd_api_version(VK_API_VERSION_1_0);
// ICD 1 : 1.1 support (with 1 group with 2 devices)
TestICD& icd1 = env.get_test_icd(1);
icd1.physical_devices.emplace_back("physical_device_1").set_api_version(VK_API_VERSION_1_1);
icd1.physical_devices.emplace_back("physical_device_2").set_api_version(VK_API_VERSION_1_1);
icd1.physical_device_groups.emplace_back(icd1.physical_devices[0]);
icd1.physical_device_groups.back().use_physical_device(icd1.physical_devices[1]);
icd1.min_icd_interface_version = 5;
icd1.max_icd_interface_version = 5;
icd1.set_icd_api_version(VK_API_VERSION_1_1);
// ICD 2 : No 1.1 support (so 3 devices will become 3 groups in loader)
TestICD& icd2 = env.get_test_icd(2);
icd2.physical_devices.emplace_back("physical_device_3");
icd2.physical_devices.emplace_back("physical_device_4");
icd2.physical_devices.emplace_back("physical_device_5");
icd2.min_icd_interface_version = 5;
icd2.max_icd_interface_version = 5;
icd2.set_icd_api_version(VK_API_VERSION_1_0);
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(1, 1, 0);
inst.CheckCreate();
uint32_t group_count = static_cast<uint32_t>(5);
uint32_t returned_group_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, nullptr));
ASSERT_EQ(group_count, returned_group_count);
std::vector<VkPhysicalDeviceGroupProperties> group_props{};
group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props.data()));
ASSERT_EQ(group_count, returned_group_count);
}
#if defined(WIN32)
// This is testing when there are drivers that support the Windows device adapter sorting mechanism by exporting
// EnumerateAdapterPhysicalDevices and drivers that do not expose that functionality
TEST(MultipleICDConfig, version_5_and_version_6) {
FrameworkEnvironment env;
const char* regular_layer_name = "VK_LAYER_TestLayer1";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(regular_layer_name)
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_api_version(VK_MAKE_API_VERSION(0, 1, 1, 0))
.set_disable_environment("DisableMeIfYouCan")),
"regular_test_layer.json");
MockQueueFamilyProperties family_props{{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, true};
uint32_t physical_count = 0;
for (uint32_t i = 0; i < 3; i++) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
auto& driver_5 = env.get_test_icd(i * 2 + 1);
driver_5.set_max_icd_interface_version(5);
driver_5.set_min_icd_interface_version(5);
driver_5.setup_WSI();
driver_5.physical_devices.push_back({});
driver_5.physical_devices.back().queue_family_properties.push_back(family_props);
driver_5.physical_devices.push_back({});
driver_5.physical_devices.back().queue_family_properties.push_back(family_props);
driver_5.physical_devices.push_back({});
driver_5.physical_devices.back().queue_family_properties.push_back(family_props);
physical_count += static_cast<uint32_t>(driver_5.physical_devices.size());
auto& driver_6 = env.get_test_icd(i * 2);
driver_6.setup_WSI();
driver_6.physical_devices.emplace_back("physical_device_0");
driver_6.physical_devices.back().queue_family_properties.push_back(family_props);
driver_6.physical_devices.emplace_back("physical_device_1");
driver_6.physical_devices.back().queue_family_properties.push_back(family_props);
physical_count += static_cast<uint32_t>(driver_6.physical_devices.size());
driver_6.set_max_icd_interface_version(6);
driver_6.set_min_icd_interface_version(5);
uint32_t driver_index = i % 4; // which drive this test pretends to be, must stay below 4
auto& known_driver = known_driver_list.at(driver_index);
DXGI_ADAPTER_DESC1 desc1{};
desc1.VendorId = known_driver.vendor_id;
desc1.AdapterLuid = LUID{100 + i, static_cast<LONG>(100 + i)};
driver_6.set_adapterLUID(desc1.AdapterLuid);
env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1);
}
uint32_t returned_physical_count = 0;
InstWrapper inst{env.vulkan_functions};
inst.create_info.setup_WSI();
inst.CheckCreate();
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr));
ASSERT_EQ(physical_count, returned_physical_count);
std::vector<VkPhysicalDevice> physical_device_handles{returned_physical_count};
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_device_handles.data()));
ASSERT_EQ(physical_count, returned_physical_count);
VkSurfaceKHR surface{};
ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
for (const auto& handle : physical_device_handles) {
handle_assert_has_value(handle);
VkBool32 supported = false;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkGetPhysicalDeviceSurfaceSupportKHR(handle, 0, surface, &supported));
}
for (uint32_t i = 0; i < 3; i++) {
auto& driver_6 = env.get_test_icd(i * 2);
EXPECT_EQ(driver_6.called_enumerate_adapter_physical_devices, true);
}
}
#endif // defined(WIN32)
// shim function pointers for 1.3
// Should use autogen for this - it generates 'shim' functions for validation layers, maybe that could be used here.
void test_vkCmdBeginRendering(VkCommandBuffer, const VkRenderPassBeginInfo*, VkSubpassContents) {}
void test_vkCmdBindVertexBuffers2(VkCommandBuffer, uint32_t, uint32_t, const VkBuffer*, const VkDeviceSize*, const VkDeviceSize*,
const VkDeviceSize*) {}
void test_vkCmdBlitImage2(VkCommandBuffer, const VkBlitImageInfo2*) {}
void test_vkCmdCopyBuffer2(VkCommandBuffer, const VkCopyBufferInfo2*) {}
void test_vkCmdCopyBufferToImage2(VkCommandBuffer, const VkCopyBufferToImageInfo2*) {}
void test_vkCmdCopyImage2(VkCommandBuffer, const VkCopyImageInfo2*) {}
void test_vkCmdCopyImageToBuffer2(VkCommandBuffer, const VkCopyImageToBufferInfo2*) {}
void test_vkCmdEndRendering(VkCommandBuffer) {}
void test_vkCmdPipelineBarrier2(VkCommandBuffer, const VkDependencyInfo*) {}
void test_vkCmdResetEvent2(VkCommandBuffer, VkEvent, VkPipelineStageFlags2) {}
void test_vkCmdResolveImage2(VkCommandBuffer, const VkResolveImageInfo2*) {}
void test_vkCmdSetCullMode(VkCommandBuffer, VkCullModeFlags) {}
void test_vkCmdSetDepthBiasEnable(VkCommandBuffer, VkBool32) {}
void test_vkCmdSetDepthBoundsTestEnable(VkCommandBuffer, VkBool32) {}
void test_vkCmdSetDepthCompareOp(VkCommandBuffer, VkCompareOp) {}
void test_vkCmdSetDepthTestEnable(VkCommandBuffer, VkBool32) {}
void test_vkCmdSetDepthWriteEnable(VkCommandBuffer, VkBool32) {}
void test_vkCmdSetEvent2(VkCommandBuffer, VkEvent, const VkDependencyInfo*) {}
void test_vkCmdSetFrontFace(VkCommandBuffer, VkFrontFace) {}
void test_vkCmdSetPrimitiveRestartEnable(VkCommandBuffer, VkBool32) {}
void test_vkCmdSetPrimitiveTopology(VkCommandBuffer, VkPrimitiveTopology) {}
void test_vkCmdSetRasterizerDiscardEnable(VkCommandBuffer, VkBool32) {}
void test_vkCmdSetScissorWithCount(VkCommandBuffer, uint32_t, const VkRect2D*) {}
void test_vkCmdSetStencilOp(VkCommandBuffer, VkStencilFaceFlags, VkStencilOp, VkStencilOp, VkStencilOp, VkCompareOp) {}
void test_vkCmdSetStencilTestEnable(VkCommandBuffer, VkBool32) {}
void test_vkCmdSetViewportWithCount(VkCommandBuffer, uint32_t, const VkViewport*) {}
void test_vkCmdWaitEvents2(VkCommandBuffer, uint32_t, const VkEvent*, const VkDependencyInfo*) {}
void test_vkCmdWriteTimestamp2(VkCommandBuffer, VkPipelineStageFlags2, VkQueryPool, uint32_t) {}
VkResult test_vkCreatePrivateDataSlot(VkDevice, const VkPrivateDataSlotCreateInfo*, const VkAllocationCallbacks*,
VkPrivateDataSlot*) {
return VK_SUCCESS;
}
void test_vkDestroyPrivateDataSlot(VkDevice, VkPrivateDataSlot, const VkAllocationCallbacks*) {}
void test_vkGetDeviceBufferMemoryRequirements(VkDevice, const VkDeviceBufferMemoryRequirements*, VkMemoryRequirements2*) {}
void test_vkGetDeviceImageMemoryRequirements(VkDevice, const VkDeviceImageMemoryRequirements*, VkMemoryRequirements2*) {}
void test_vkGetDeviceImageSparseMemoryRequirements(VkDevice, const VkDeviceImageMemoryRequirements*, uint32_t*,
VkSparseImageMemoryRequirements2*) {}
void test_vkGetPrivateData(VkDevice, VkObjectType, uint64_t, VkPrivateDataSlot, uint64_t*) {}
VkResult test_vkQueueSubmit2(VkQueue, uint32_t, const VkSubmitInfo2*, VkFence) { return VK_SUCCESS; }
VkResult test_vkSetPrivateData(VkDevice, VkObjectType, uint64_t, VkPrivateDataSlot, uint64_t) { return VK_SUCCESS; }
TEST(MinorVersionUpdate, Version1_3) {
FrameworkEnvironment env{};
auto& driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
driver.physical_devices.back().known_device_functions = {
VulkanFunction{"vkCmdBeginRendering", to_vkVoidFunction(test_vkCmdBeginRendering)},
VulkanFunction{"vkCmdBindVertexBuffers2", to_vkVoidFunction(test_vkCmdBindVertexBuffers2)},
VulkanFunction{"vkCmdBlitImage2", to_vkVoidFunction(test_vkCmdBlitImage2)},
VulkanFunction{"vkCmdCopyBuffer2", to_vkVoidFunction(test_vkCmdCopyBuffer2)},
VulkanFunction{"vkCmdCopyBufferToImage2", to_vkVoidFunction(test_vkCmdCopyBufferToImage2)},
VulkanFunction{"vkCmdCopyImage2", to_vkVoidFunction(test_vkCmdCopyImage2)},
VulkanFunction{"vkCmdCopyImageToBuffer2", to_vkVoidFunction(test_vkCmdCopyImageToBuffer2)},
VulkanFunction{"vkCmdEndRendering", to_vkVoidFunction(test_vkCmdEndRendering)},
VulkanFunction{"vkCmdPipelineBarrier2", to_vkVoidFunction(test_vkCmdPipelineBarrier2)},
VulkanFunction{"vkCmdResetEvent2", to_vkVoidFunction(test_vkCmdResetEvent2)},
VulkanFunction{"vkCmdResolveImage2", to_vkVoidFunction(test_vkCmdResolveImage2)},
VulkanFunction{"vkCmdSetCullMode", to_vkVoidFunction(test_vkCmdSetCullMode)},
VulkanFunction{"vkCmdSetDepthBiasEnable", to_vkVoidFunction(test_vkCmdSetDepthBiasEnable)},
VulkanFunction{"vkCmdSetDepthBoundsTestEnable", to_vkVoidFunction(test_vkCmdSetDepthBoundsTestEnable)},
VulkanFunction{"vkCmdSetDepthCompareOp", to_vkVoidFunction(test_vkCmdSetDepthCompareOp)},
VulkanFunction{"vkCmdSetDepthTestEnable", to_vkVoidFunction(test_vkCmdSetDepthTestEnable)},
VulkanFunction{"vkCmdSetDepthWriteEnable", to_vkVoidFunction(test_vkCmdSetDepthWriteEnable)},
VulkanFunction{"vkCmdSetEvent2", to_vkVoidFunction(test_vkCmdSetEvent2)},
VulkanFunction{"vkCmdSetFrontFace", to_vkVoidFunction(test_vkCmdSetFrontFace)},
VulkanFunction{"vkCmdSetPrimitiveRestartEnable", to_vkVoidFunction(test_vkCmdSetPrimitiveRestartEnable)},
VulkanFunction{"vkCmdSetPrimitiveTopology", to_vkVoidFunction(test_vkCmdSetPrimitiveTopology)},
VulkanFunction{"vkCmdSetRasterizerDiscardEnable", to_vkVoidFunction(test_vkCmdSetRasterizerDiscardEnable)},
VulkanFunction{"vkCmdSetScissorWithCount", to_vkVoidFunction(test_vkCmdSetScissorWithCount)},
VulkanFunction{"vkCmdSetStencilOp", to_vkVoidFunction(test_vkCmdSetStencilOp)},
VulkanFunction{"vkCmdSetStencilTestEnable", to_vkVoidFunction(test_vkCmdSetStencilTestEnable)},
VulkanFunction{"vkCmdSetViewportWithCount", to_vkVoidFunction(test_vkCmdSetViewportWithCount)},
VulkanFunction{"vkCmdWaitEvents2", to_vkVoidFunction(test_vkCmdWaitEvents2)},
VulkanFunction{"vkCmdWriteTimestamp2", to_vkVoidFunction(test_vkCmdWriteTimestamp2)},
VulkanFunction{"vkCreatePrivateDataSlot", to_vkVoidFunction(test_vkCreatePrivateDataSlot)},
VulkanFunction{"vkDestroyPrivateDataSlot", to_vkVoidFunction(test_vkDestroyPrivateDataSlot)},
VulkanFunction{"vkGetDeviceBufferMemoryRequirements", to_vkVoidFunction(test_vkGetDeviceBufferMemoryRequirements)},
VulkanFunction{"vkGetDeviceImageMemoryRequirements", to_vkVoidFunction(test_vkGetDeviceImageMemoryRequirements)},
VulkanFunction{"vkGetDeviceImageSparseMemoryRequirements",
to_vkVoidFunction(test_vkGetDeviceImageSparseMemoryRequirements)},
VulkanFunction{"vkGetPrivateData", to_vkVoidFunction(test_vkGetPrivateData)},
VulkanFunction{"vkQueueSubmit2", to_vkVoidFunction(test_vkQueueSubmit2)},
VulkanFunction{"vkSetPrivateData", to_vkVoidFunction(test_vkSetPrivateData)},
};
driver.physical_devices.back().add_extension({"VK_SOME_EXT_haha"});
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(1, 3, 0);
inst.CheckCreate();
auto phys_dev = inst.GetPhysDev();
PFN_vkGetPhysicalDeviceToolProperties GetPhysicalDeviceToolProperties = inst.load("vkGetPhysicalDeviceToolProperties");
uint32_t tool_count = 0;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceToolProperties(phys_dev, &tool_count, nullptr));
ASSERT_EQ(tool_count, 0U);
VkPhysicalDeviceToolProperties props;
ASSERT_EQ(VK_SUCCESS, GetPhysicalDeviceToolProperties(phys_dev, &tool_count, &props));
DeviceWrapper device{inst};
device.CheckCreate(phys_dev);
PFN_vkCreateCommandPool CreateCommandPool = device.load("vkCreateCommandPool");
PFN_vkAllocateCommandBuffers AllocateCommandBuffers = device.load("vkAllocateCommandBuffers");
PFN_vkDestroyCommandPool DestroyCommandPool = device.load("vkDestroyCommandPool");
VkCommandPool command_pool{};
VkCommandPoolCreateInfo pool_create_info{};
pool_create_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
ASSERT_EQ(VK_SUCCESS, CreateCommandPool(device, &pool_create_info, nullptr, &command_pool));
VkCommandBufferAllocateInfo buffer_allocate_info{};
buffer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
buffer_allocate_info.commandPool = command_pool;
buffer_allocate_info.commandBufferCount = 1;
VkCommandBuffer command_buffer{};
ASSERT_EQ(VK_SUCCESS, AllocateCommandBuffers(device, &buffer_allocate_info, &command_buffer));
DestroyCommandPool(device, command_pool, nullptr);
PFN_vkCmdBeginRendering CmdBeginRendering = device.load("vkCmdBeginRendering");
VkRenderingInfoKHR rendering_info{};
CmdBeginRendering(command_buffer, &rendering_info);
PFN_vkCmdBindVertexBuffers2 CmdBindVertexBuffers2 = device.load("vkCmdBindVertexBuffers2");
CmdBindVertexBuffers2(command_buffer, 0, 0, nullptr, nullptr, nullptr, nullptr);
PFN_vkCmdBlitImage2 CmdBlitImage2 = device.load("vkCmdBlitImage2");
VkBlitImageInfo2 image_info{};
CmdBlitImage2(command_buffer, &image_info);
PFN_vkCmdCopyBuffer2 CmdCopyBuffer2 = device.load("vkCmdCopyBuffer2");
VkCopyBufferInfo2 copy_info{};
CmdCopyBuffer2(command_buffer, &copy_info);
PFN_vkCmdCopyBufferToImage2 CmdCopyBufferToImage2 = device.load("vkCmdCopyBufferToImage2");
VkCopyBufferToImageInfo2 copy_buf_image{};
CmdCopyBufferToImage2(command_buffer, &copy_buf_image);
PFN_vkCmdCopyImage2 CmdCopyImage2 = device.load("vkCmdCopyImage2");
VkCopyImageInfo2 copy_image_info{};
CmdCopyImage2(command_buffer, &copy_image_info);
PFN_vkCmdCopyImageToBuffer2 CmdCopyImageToBuffer2 = device.load("vkCmdCopyImageToBuffer2");
VkCopyImageToBufferInfo2 copy_image_buf;
CmdCopyImageToBuffer2(command_buffer, &copy_image_buf);
PFN_vkCmdEndRendering CmdEndRendering = device.load("vkCmdEndRendering");
CmdEndRendering(command_buffer);
PFN_vkCmdPipelineBarrier2 CmdPipelineBarrier2 = device.load("vkCmdPipelineBarrier2");
VkDependencyInfo deps_info;
CmdPipelineBarrier2(command_buffer, &deps_info);
PFN_vkCmdResetEvent2 CmdResetEvent2 = device.load("vkCmdResetEvent2");
CmdResetEvent2(command_buffer, {}, VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
PFN_vkCmdResolveImage2 CmdResolveImage2 = device.load("vkCmdResolveImage2");
VkResolveImageInfo2 resolve_image{};
CmdResolveImage2(command_buffer, &resolve_image);
PFN_vkCmdSetCullMode CmdSetCullMode = device.load("vkCmdSetCullMode");
CmdSetCullMode(command_buffer, VK_CULL_MODE_BACK_BIT);
PFN_vkCmdSetDepthBiasEnable CmdSetDepthBiasEnable = device.load("vkCmdSetDepthBiasEnable");
CmdSetDepthBiasEnable(command_buffer, true);
PFN_vkCmdSetDepthBoundsTestEnable CmdSetDepthBoundsTestEnable = device.load("vkCmdSetDepthBoundsTestEnable");
CmdSetDepthBoundsTestEnable(command_buffer, true);
PFN_vkCmdSetDepthCompareOp CmdSetDepthCompareOp = device.load("vkCmdSetDepthCompareOp");
CmdSetDepthCompareOp(command_buffer, VK_COMPARE_OP_ALWAYS);
PFN_vkCmdSetDepthTestEnable CmdSetDepthTestEnable = device.load("vkCmdSetDepthTestEnable");
CmdSetDepthTestEnable(command_buffer, true);
PFN_vkCmdSetDepthWriteEnable CmdSetDepthWriteEnable = device.load("vkCmdSetDepthWriteEnable");
CmdSetDepthWriteEnable(command_buffer, true);
PFN_vkCmdSetEvent2 CmdSetEvent2 = device.load("vkCmdSetEvent2");
CmdSetEvent2(command_buffer, {}, &deps_info);
PFN_vkCmdSetFrontFace CmdSetFrontFace = device.load("vkCmdSetFrontFace");
CmdSetFrontFace(command_buffer, VK_FRONT_FACE_CLOCKWISE);
PFN_vkCmdSetPrimitiveRestartEnable CmdSetPrimitiveRestartEnable = device.load("vkCmdSetPrimitiveRestartEnable");
CmdSetPrimitiveRestartEnable(command_buffer, true);
PFN_vkCmdSetPrimitiveTopology CmdSetPrimitiveTopology = device.load("vkCmdSetPrimitiveTopology");
CmdSetPrimitiveTopology(command_buffer, VK_PRIMITIVE_TOPOLOGY_LINE_LIST);
PFN_vkCmdSetRasterizerDiscardEnable CmdSetRasterizerDiscardEnable = device.load("vkCmdSetRasterizerDiscardEnable");
CmdSetRasterizerDiscardEnable(command_buffer, true);
PFN_vkCmdSetScissorWithCount CmdSetScissorWithCount = device.load("vkCmdSetScissorWithCount");
CmdSetScissorWithCount(command_buffer, 0, nullptr);
PFN_vkCmdSetStencilOp CmdSetStencilOp = device.load("vkCmdSetStencilOp");
CmdSetStencilOp(command_buffer, VK_STENCIL_FACE_BACK_BIT, VK_STENCIL_OP_DECREMENT_AND_WRAP, VK_STENCIL_OP_DECREMENT_AND_CLAMP,
VK_STENCIL_OP_DECREMENT_AND_WRAP, VK_COMPARE_OP_ALWAYS);
PFN_vkCmdSetStencilTestEnable CmdSetStencilTestEnable = device.load("vkCmdSetStencilTestEnable");
CmdSetStencilTestEnable(command_buffer, true);
PFN_vkCmdSetViewportWithCount CmdSetViewportWithCount = device.load("vkCmdSetViewportWithCount");
CmdSetViewportWithCount(command_buffer, 0, nullptr);
PFN_vkCmdWaitEvents2 CmdWaitEvents2 = device.load("vkCmdWaitEvents2");
CmdWaitEvents2(command_buffer, 0, nullptr, &deps_info);
PFN_vkCmdWriteTimestamp2 CmdWriteTimestamp2 = device.load("vkCmdWriteTimestamp2");
CmdWriteTimestamp2(command_buffer, VK_PIPELINE_STAGE_2_BLIT_BIT, {}, 0);
PFN_vkCreatePrivateDataSlot CreatePrivateDataSlot = device.load("vkCreatePrivateDataSlot");
CreatePrivateDataSlot(device, nullptr, nullptr, nullptr);
PFN_vkDestroyPrivateDataSlot DestroyPrivateDataSlot = device.load("vkDestroyPrivateDataSlot");
DestroyPrivateDataSlot(device, VK_NULL_HANDLE, nullptr);
PFN_vkGetDeviceBufferMemoryRequirements GetDeviceBufferMemoryRequirements = device.load("vkGetDeviceBufferMemoryRequirements");
GetDeviceBufferMemoryRequirements(device, nullptr, nullptr);
PFN_vkGetDeviceImageMemoryRequirements GetDeviceImageMemoryRequirements = device.load("vkGetDeviceImageMemoryRequirements");
GetDeviceImageMemoryRequirements(device, nullptr, nullptr);
PFN_vkGetDeviceImageSparseMemoryRequirements GetDeviceImageSparseMemoryRequirements =
device.load("vkGetDeviceImageSparseMemoryRequirements");
GetDeviceImageSparseMemoryRequirements(device, nullptr, nullptr, nullptr);
PFN_vkGetPrivateData GetPrivateData = device.load("vkGetPrivateData");
GetPrivateData(device, VK_OBJECT_TYPE_UNKNOWN, 0, {}, nullptr);
PFN_vkQueueSubmit2 QueueSubmit2 = device.load("vkQueueSubmit2");
QueueSubmit2(nullptr, 0, nullptr, VK_NULL_HANDLE);
PFN_vkSetPrivateData SetPrivateData = device.load("vkSetPrivateData");
SetPrivateData(device, VK_OBJECT_TYPE_UNKNOWN, 0, {}, 0);
}
TEST(ApplicationInfoVersion, NonVulkanVariant) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_MAKE_API_VERSION(1, 0, 0, 0));
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
ASSERT_TRUE(log.find(
std::string("vkCreateInstance: The API Variant specified in pCreateInfo->pApplicationInfo.apiVersion is 1 instead of "
"the expected value of 0.")));
}
TEST(DriverManifest, NonVulkanVariant) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(1, 1, 0, 0))).add_physical_device({});
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER);
ASSERT_TRUE(log.find("loader_parse_icd_manifest: Driver's ICD JSON "));
// 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.
ASSERT_TRUE(log.find("\'api_version\' field contains a non-zero variant value of 1. Skipping ICD JSON."));
}
TEST(LayerManifest, ImplicitNonVulkanVariant) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 0, 0))).add_physical_device({});
const char* implicit_layer_name = "ImplicitTestLayer";
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
.set_api_version(VK_MAKE_API_VERSION(1, 1, 0, 0))
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ME")),
"implicit_test_layer.json");
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
ASSERT_TRUE(log.find(std::string("Layer \"") + implicit_layer_name +
"\" has an \'api_version\' field which contains a non-zero variant value of 1. Skipping Layer."));
}
TEST(LayerManifest, ExplicitNonVulkanVariant) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA, VK_MAKE_API_VERSION(0, 1, 0, 0))).add_physical_device({});
const char* explicit_layer_name = "ExplicitTestLayer";
env.add_explicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name(explicit_layer_name)
.set_api_version(VK_MAKE_API_VERSION(1, 1, 0, 0))
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)),
"explicit_test_layer.json");
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0)).add_layer(explicit_layer_name);
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
ASSERT_TRUE(log.find(std::string("Layer \"") + explicit_layer_name +
"\" has an \'api_version\' field which contains a non-zero variant value of 1. Skipping Layer."));
}
TEST(DriverManifest, UnknownManifestVersion) {
FrameworkEnvironment env{};
env.add_icd(
TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_file_format_version({3, 2, 1})))
.add_physical_device({});
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
ASSERT_TRUE(log.find("loader_parse_icd_manifest: "));
// 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.
ASSERT_TRUE(log.find("has unknown icd manifest file version 3.2.1. May cause errors."));
}
TEST(DriverManifest, LargeUnknownManifestVersion) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(
ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_file_format_version({100, 222, 111})))
.add_physical_device({});
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
ASSERT_TRUE(log.find("loader_parse_icd_manifest: "));
// 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.
ASSERT_TRUE(log.find("has unknown icd manifest file version 100.222.111. May cause errors."));
}
TEST(LayerManifest, UnknownManifestVersion) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
const char* implicit_layer_name = "ImplicitTestLayer";
env.add_implicit_layer(ManifestLayer{}
.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ME"))
.set_file_format_version({3, 2, 1}),
"implicit_test_layer.json");
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
ASSERT_TRUE(log.find("loader_add_layer_properties: "));
// 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.
ASSERT_TRUE(log.find("has unknown layer manifest file version 3.2.1. May cause errors."));
}
TEST(LayerManifest, LargeUnknownManifestVersion) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)).add_physical_device({});
const char* implicit_layer_name = "ImplicitTestLayer";
env.add_implicit_layer(ManifestLayer{}
.add_layer(ManifestLayer::LayerDescription{}
.set_name(implicit_layer_name)
.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0))
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ME"))
.set_file_format_version({100, 222, 111}),
"implicit_test_layer.json");
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.CheckCreate();
ASSERT_TRUE(log.find("loader_add_layer_properties: "));
// 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.
ASSERT_TRUE(log.find("has unknown layer manifest file version 100.222.111. May cause errors."));
}
struct DriverInfo {
DriverInfo(TestICDDetails icd_details, uint32_t driver_version, bool expect_to_find) noexcept
: icd_details(icd_details), driver_version(driver_version), expect_to_find(expect_to_find) {}
TestICDDetails icd_details;
uint32_t driver_version = 0;
bool expect_to_find = false;
};
void CheckDirectDriverLoading(FrameworkEnvironment& env, std::vector<DriverInfo> const& normal_drivers,
std::vector<DriverInfo> const& direct_drivers, bool exclusive) {
std::vector<VkDirectDriverLoadingInfoLUNARG> ddl_infos;
uint32_t expected_driver_count = 0;
for (auto const& driver : direct_drivers) {
auto& direct_driver_icd = env.add_icd(driver.icd_details);
direct_driver_icd.physical_devices.push_back({});
direct_driver_icd.physical_devices.at(0).properties.driverVersion = driver.driver_version;
VkDirectDriverLoadingInfoLUNARG ddl_info{};
ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
ddl_info.pfnGetInstanceProcAddr = env.icds.back().icd_library.get_symbol("vk_icdGetInstanceProcAddr");
ddl_infos.push_back(ddl_info);
if (driver.expect_to_find) {
expected_driver_count++;
}
}
for (auto const& driver : normal_drivers) {
auto& direct_driver_icd = env.add_icd(driver.icd_details);
direct_driver_icd.physical_devices.push_back({});
direct_driver_icd.physical_devices.at(0).properties.driverVersion = driver.driver_version;
if (!exclusive && driver.expect_to_find) {
expected_driver_count++;
}
}
VkDirectDriverLoadingListLUNARG ddl_list{};
ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
ddl_list.mode = exclusive ? VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG : VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
ddl_list.driverCount = static_cast<uint32_t>(ddl_infos.size());
ddl_list.pDrivers = ddl_infos.data();
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate());
if (exclusive) {
ASSERT_TRUE(
log.find("loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension is active and specified "
"VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG, skipping system and environment "
"variable driver search mechanisms."));
}
// Make sure all drivers we expect to load were found - including checking that the pfn matches exactly.
for (uint32_t i = 0; i < direct_drivers.size(); i++) {
if (direct_drivers.at(i).expect_to_find) {
std::stringstream ss;
ss << "loader_add_direct_driver: Adding driver found in index " << i
<< " of VkDirectDriverLoadingListLUNARG::pDrivers structure. pfnGetInstanceProcAddr was set to "
<< reinterpret_cast<const void*>(ddl_infos.at(i).pfnGetInstanceProcAddr);
std::string log_message = ss.str();
ASSERT_TRUE(log.find(log_message));
}
}
auto phys_devs = inst.GetPhysDevs();
ASSERT_EQ(phys_devs.size(), expected_driver_count);
// We have to iterate through the driver lists backwards because the loader *prepends* icd's, so the last found ICD is found
// first in the driver list
uint32_t driver_index = 0;
for (size_t i = normal_drivers.size() - 1; i == 0; i--) {
if (normal_drivers.at(i).expect_to_find) {
VkPhysicalDeviceProperties props{};
inst.functions->vkGetPhysicalDeviceProperties(phys_devs.at(driver_index), &props);
ASSERT_EQ(props.driverVersion, normal_drivers.at(i).driver_version);
driver_index++;
}
}
for (size_t i = direct_drivers.size() - 1; i == 0; i--) {
if (direct_drivers.at(i).expect_to_find) {
VkPhysicalDeviceProperties props{};
inst.functions->vkGetPhysicalDeviceProperties(phys_devs.at(driver_index), &props);
ASSERT_EQ(props.driverVersion, direct_drivers.at(i).driver_version);
driver_index++;
}
}
}
// Only 1 direct driver
TEST(DirectDriverLoading, Individual) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 10, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
}
// 2 direct drivers
TEST(DirectDriverLoading, MultipleDirectDrivers) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 13, true);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 7, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
}
// Multiple direct drivers with a normal driver in the middle
TEST(DirectDriverLoading, MultipleDirectDriversAndNormalDrivers) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA), 90, true);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 80, true);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 70, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
}
// Normal driver and direct driver with direct driver exclusivity
TEST(DirectDriverLoading, ExclusiveWithNormalDriver) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 33, true);
normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2), 44, false);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
}
TEST(DirectDriverLoading, ExclusiveWithMultipleNormalDriver) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2), 55, true);
normal_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_2), 66, true);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 77, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
}
TEST(DirectDriverLoading, ExclusiveWithDriverEnvVar) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
normal_drivers.emplace_back(
TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::env_var), 4, false);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 5, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
}
TEST(DirectDriverLoading, ExclusiveWithAddDriverEnvVar) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
normal_drivers.emplace_back(
TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_discovery_type(ManifestDiscoveryType::add_env_var), 6, false);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 7, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
}
TEST(DirectDriverLoading, InclusiveWithFilterSelect) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
EnvVarWrapper driver_filter_select_env_var{"VK_LOADER_DRIVERS_SELECT", "normal_driver.json"};
normal_drivers.emplace_back(
TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 8, true);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 9, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
}
TEST(DirectDriverLoading, ExclusiveWithFilterSelect) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
EnvVarWrapper driver_filter_select_env_var{"VK_LOADER_DRIVERS_SELECT", "normal_driver.json"};
normal_drivers.emplace_back(
TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 10,
false);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 11, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
}
TEST(DirectDriverLoading, InclusiveWithFilterDisable) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
EnvVarWrapper driver_filter_disable_env_var{"VK_LOADER_DRIVERS_DISABLE", "normal_driver.json"};
normal_drivers.emplace_back(
TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 12,
false);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 13, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, false));
}
TEST(DirectDriverLoading, ExclusiveWithFilterDisable) {
FrameworkEnvironment env{};
std::vector<DriverInfo> normal_drivers;
std::vector<DriverInfo> direct_drivers;
EnvVarWrapper driver_filter_disable_env_var{"VK_LOADER_DRIVERS_DISABLE", "normal_driver.json"};
normal_drivers.emplace_back(
TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_disable_icd_inc(true).set_json_name("normal_driver"), 14,
false);
direct_drivers.emplace_back(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none), 15, true);
ASSERT_NO_FATAL_FAILURE(CheckDirectDriverLoading(env, normal_drivers, direct_drivers, true));
}
// The VK_LUNARG_direct_driver_loading extension is not enabled
TEST(DirectDriverLoading, ExtensionNotEnabled) {
FrameworkEnvironment env{};
auto& direct_driver_icd = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none));
direct_driver_icd.physical_devices.push_back({});
VkDirectDriverLoadingInfoLUNARG ddl_info{};
ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
ddl_info.pfnGetInstanceProcAddr = env.icds.back().icd_library.get_symbol("vk_icdGetInstanceProcAddr");
VkDirectDriverLoadingListLUNARG ddl_list{};
ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
ddl_list.driverCount = 1U;
ddl_list.pDrivers = &ddl_info;
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
ASSERT_TRUE(
log.find("loader_scan_for_direct_drivers: The pNext chain of VkInstanceCreateInfo contained the "
"VkDirectDriverLoadingListLUNARG structure, but the VK_LUNARG_direct_driver_loading extension was "
"not enabled."));
}
// VkDirectDriverLoadingListLUNARG is not in the pNext chain of VkInstanceCreateInfo
TEST(DirectDriverLoading, DriverListNotInPnextChain) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none)).add_physical_device({});
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
ASSERT_TRUE(
log.find("loader_scan_for_direct_drivers: The VK_LUNARG_direct_driver_loading extension was enabled but the pNext chain of "
"VkInstanceCreateInfo did not contain the "
"VkDirectDriverLoadingListLUNARG structure."));
}
// User sets the pDrivers pointer in VkDirectDriverLoadingListLUNARG to nullptr
TEST(DirectDriverLoading, DriverListHasNullDriverPointer) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none)).add_physical_device({});
VkDirectDriverLoadingListLUNARG ddl_list{};
ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
ddl_list.driverCount = 1U;
ddl_list.pDrivers = nullptr; // user forgot to set the pDrivers
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
ASSERT_TRUE(
log.find("loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
"VkInstanceCreateInfo has a NULL pDrivers member."));
}
// User sets the driverCount in VkDirectDriverLoadingListLUNARG to zero
TEST(DirectDriverLoading, DriverListHasZeroInfoCount) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none)).add_physical_device({});
VkDirectDriverLoadingInfoLUNARG ddl_info{};
ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
ddl_info.pfnGetInstanceProcAddr = env.icds.back().icd_library.get_symbol("vk_icdGetInstanceProcAddr");
VkDirectDriverLoadingListLUNARG ddl_list{};
ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
ddl_list.driverCount = 0; // user set 0 for the info list
ddl_list.pDrivers = &ddl_info;
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
ASSERT_TRUE(
log.find("loader_scan_for_direct_drivers: The VkDirectDriverLoadingListLUNARG structure in the pNext chain of "
"VkInstanceCreateInfo has a non-null pDrivers member but a driverCount member with a value "
"of zero."));
}
// pfnGetInstanceProcAddr in VkDirectDriverLoadingInfoLUNARG is nullptr
TEST(DirectDriverLoading, DriverInfoMissingGetInstanceProcAddr) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none)).add_physical_device({});
std::array<VkDirectDriverLoadingInfoLUNARG, 2> ddl_infos{};
ddl_infos[0].sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
ddl_infos[0].pfnGetInstanceProcAddr = nullptr; // user didn't set the pfnGetInstanceProcAddr to the driver's handle
ddl_infos[1].sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
ddl_infos[1].pfnGetInstanceProcAddr = nullptr; // user didn't set the pfnGetInstanceProcAddr to the driver's handle
VkDirectDriverLoadingListLUNARG ddl_list{};
ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
ddl_list.driverCount = static_cast<uint32_t>(ddl_infos.size());
ddl_list.pDrivers = ddl_infos.data();
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
ASSERT_TRUE(
log.find("loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index 0 contains a NULL pointer for the "
"pfnGetInstanceProcAddr member, skipping."));
ASSERT_TRUE(
log.find("loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index 1 contains a NULL pointer for the "
"pfnGetInstanceProcAddr member, skipping."));
}
// test the various error paths in loader_add_direct_driver
TEST(DirectDriverLoading, DriverDoesNotExportNegotiateFunction) {
FrameworkEnvironment env{};
auto& direct_driver = env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none))
.add_physical_device({})
.set_exposes_vk_icdNegotiateLoaderICDInterfaceVersion(false)
.set_exposes_vkCreateInstance(false)
.set_exposes_vkEnumerateInstanceExtensionProperties(false);
VkDirectDriverLoadingInfoLUNARG ddl_info{};
ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG;
ddl_info.pfnGetInstanceProcAddr = env.icds.back().icd_library.get_symbol("vk_icdGetInstanceProcAddr");
VkDirectDriverLoadingListLUNARG ddl_list{};
ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG;
ddl_list.driverCount = 1;
ddl_list.pDrivers = &ddl_info;
{
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
ASSERT_TRUE(
log.find("loader_add_direct_driver: Could not get 'vk_icdNegotiateLoaderICDInterfaceVersion' from "
"VkDirectDriverLoadingInfoLUNARG structure at "
"index 0, skipping."));
}
// Allow the negotiate function to be found, now it should fail to find instance creation function
direct_driver.set_exposes_vk_icdNegotiateLoaderICDInterfaceVersion(true);
direct_driver.set_max_icd_interface_version(4);
{
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
ASSERT_TRUE(log.find(
"loader_add_direct_driver: VkDirectDriverLoadingInfoLUNARG structure at index 0 supports interface version 4, "
"which is incompatible with the Loader Driver Interface version that supports the VK_LUNARG_direct_driver_loading "
"extension, skipping."));
}
direct_driver.set_max_icd_interface_version(7);
{
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
ASSERT_TRUE(
log.find("loader_add_direct_driver: Could not get 'vkEnumerateInstanceExtensionProperties' from "
"VkDirectDriverLoadingInfoLUNARG structure at index 0, skipping."));
}
// Allow the instance creation function to be found, now it should fail to find EnumInstExtProps
direct_driver.set_exposes_vkCreateInstance(true);
{
DebugUtilsLogger log;
InstWrapper inst{env.vulkan_functions};
FillDebugUtilsCreateDetails(inst.create_info, log);
log.get()->pNext = reinterpret_cast<const void*>(&ddl_list);
inst.create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME);
inst.create_info.set_api_version(VK_MAKE_API_VERSION(0, 1, 0, 0));
ASSERT_NO_FATAL_FAILURE(inst.CheckCreate(VK_ERROR_INCOMPATIBLE_DRIVER));
ASSERT_TRUE(
log.find("loader_add_direct_driver: Could not get 'vkEnumerateInstanceExtensionProperties' from "
"VkDirectDriverLoadingInfoLUNARG structure at index 0, skipping."));
}
}
TEST(DriverManifest, VersionMismatchWithEnumerateInstanceVersion) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
.set_icd_api_version(VK_API_VERSION_1_0)
.add_physical_device({});
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.CheckCreate();
ASSERT_TRUE(env.debug_log.find(std::string("terminator_CreateInstance: Manifest ICD for \"") + env.get_test_icd_path().str() +
"\" contained a 1.1 or greater API version, but "
"vkEnumerateInstanceVersion returned 1.0, treating as a 1.0 ICD"));
}
TEST(DriverManifest, EnumerateInstanceVersionNotSupported) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2, VK_API_VERSION_1_1))
.set_icd_api_version(VK_API_VERSION_1_0)
.set_can_query_vkEnumerateInstanceVersion(false)
.add_physical_device({});
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
FillDebugUtilsCreateDetails(inst.create_info, env.debug_log);
inst.CheckCreate();
ASSERT_TRUE(env.debug_log.find(std::string("terminator_CreateInstance: Manifest ICD for \"") + env.get_test_icd_path().str() +
"\" contained a 1.1 or greater API version, but does "
"not support vkEnumerateInstanceVersion, treating as a 1.0 ICD"));
}