Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/Vulkan-Loader.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Giessen <charles@lunarg.com>2022-04-05 09:14:49 +0300
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>2022-04-07 03:25:09 +0300
commit717697987eeb5614608b95e667e4b6d2def173c4 (patch)
treed029bbcd965de469e48823c8437e6e7d85eb3e3a
parent1de26aad69552f2de5ff81f5ad7ee37bef71efa0 (diff)
Warn if portability_enumeration extension should be enabled
Log an error if an application creates a VkDevice from a physical device which was enumerated from a driver that is a portability driver but the application didn't correctly enable the portability enumeration flag & extension.
-rw-r--r--loader/loader.c32
-rw-r--r--loader/loader_common.h4
-rw-r--r--loader/trampoline.c12
-rw-r--r--tests/framework/test_util.cpp6
-rw-r--r--tests/framework/test_util.h11
-rw-r--r--tests/loader_layer_tests.cpp136
-rw-r--r--tests/loader_regression_tests.cpp199
7 files changed, 299 insertions, 101 deletions
diff --git a/loader/loader.c b/loader/loader.c
index 96c904fd5..c2d651bf5 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -1169,6 +1169,13 @@ VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance
// Traverse loader's extensions, adding non-duplicate extensions to the list
debug_utils_AddInstanceExtensions(inst, inst_exts);
+ static const VkExtensionProperties portability_enumeration_extension_info[] = {
+ {VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION}};
+
+ // Add VK_KHR_portability_subset
+ loader_add_to_ext_list(inst, inst_exts, sizeof(portability_enumeration_extension_info) / sizeof(VkExtensionProperties),
+ portability_enumeration_extension_info);
+
out:
return res;
}
@@ -1365,7 +1372,8 @@ static VkResult loader_scanned_icd_init(const struct loader_instance *inst, stru
}
static VkResult loader_scanned_icd_add(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
- const char *filename, uint32_t api_version, enum loader_layer_library_status *lib_status) {
+ const char *filename, uint32_t api_version, bool is_portability_driver,
+ enum loader_layer_library_status *lib_status) {
loader_platform_dl_handle handle;
PFN_vkCreateInstance fp_create_inst;
PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
@@ -1505,6 +1513,7 @@ static VkResult loader_scanned_icd_add(const struct loader_instance *inst, struc
new_scanned_icd->EnumerateAdapterPhysicalDevices = fp_enum_dxgi_adapter_phys_devs;
#endif
new_scanned_icd->interface_version = interface_vers;
+ new_scanned_icd->portability_driver = is_portability_driver;
new_scanned_icd->lib_name = (char *)loader_instance_heap_alloc(inst, strlen(filename) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == new_scanned_icd->lib_name) {
@@ -3540,9 +3549,18 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t
json = NULL;
continue;
}
+ bool portability_driver = false;
+ item = cJSON_GetObjectItem(itemICD, "is_portability_driver");
+ if (item != NULL && item->type == cJSON_True) {
+ portability_driver = true;
+ // TODO: skip over the driver if the is_portability_driver field is present and true but the portability
+ // enumeration extension is present. Then emit an error if no drivers are present but a portability driver
+ // was skipped.
+ }
+
VkResult icd_add_res = VK_SUCCESS;
enum loader_layer_library_status lib_status;
- icd_add_res = loader_scanned_icd_add(inst, icd_tramp_list, fullpath, vers, &lib_status);
+ icd_add_res = loader_scanned_icd_add(inst, icd_tramp_list, fullpath, vers, portability_driver, &lib_status);
if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_add_res) {
res = icd_add_res;
goto out;
@@ -5415,6 +5433,16 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(VkPhysicalDevice physical
icd_exts.list = NULL;
+ // Check if the driver the VkPhysicalDevice comes from is a portability driver and emit a warning if the
+ // VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit isn't set
+ if (icd_term->scanned_icd->portability_driver && !icd_term->this_instance->portability_enumeration_enabled) {
+ loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
+ "vkCreateDevice: Attempting to create a VkDevice from a VkPhysicalDevice which is from a portability driver "
+ "without the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit in the VkInstanceCreateInfo flags being set "
+ "and the VK_KHR_portability_enumeration extension enabled. In future versions of the loader this "
+ "VkPhysicalDevice will not be enumerated.");
+ }
+
if (fpCreateDevice == NULL) {
loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
"terminator_CreateDevice: No vkCreateDevice command exposed by ICD %s", icd_term->scanned_icd->lib_name);
diff --git a/loader/loader_common.h b/loader/loader_common.h
index 94b11d523..4a6d6d182 100644
--- a/loader/loader_common.h
+++ b/loader/loader_common.h
@@ -292,6 +292,8 @@ struct loader_instance {
VkAllocationCallbacks alloc_callbacks;
+ bool portability_enumeration_enabled;
+
bool wsi_surface_enabled;
#ifdef VK_USE_PLATFORM_WIN32_KHR
bool wsi_win32_surface_enabled;
@@ -425,6 +427,8 @@ struct loader_scanned_icd {
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vk_icdEnumerateAdapterPhysicalDevices EnumerateAdapterPhysicalDevices;
#endif
+ // whether the device is a portability driver
+ bool portability_driver;
};
enum loader_data_files_type {
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 604d69741..701df9581 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -482,6 +482,18 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
ptr_instance->app_api_version.patch = 0;
}
+ // Check the VkInstanceCreateInfoFlags wether to allow the portability enumeration flag
+ if ((pCreateInfo->flags & VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR) == 1) {
+ // Make sure the extension has been enabled
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) == 0) {
+ ptr_instance->portability_enumeration_enabled = true;
+ loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
+ "Portability enumeration bit was set, enumerating portability drivers.");
+ }
+ }
+ }
+
// Look for one or more VK_EXT_debug_report or VK_EXT_debug_utils create info structures
// and setup a callback(s) for each one found.
ptr_instance->num_tmp_report_callbacks = 0;
diff --git a/tests/framework/test_util.cpp b/tests/framework/test_util.cpp
index 2dca441f1..5b8ac6b73 100644
--- a/tests/framework/test_util.cpp
+++ b/tests/framework/test_util.cpp
@@ -128,13 +128,16 @@ void print_vector_of_strings(std::string& out, const char* object_name, std::vec
}
}
+std::string to_text(bool b) { return b ? std::string("true") : std::string("false"); }
+
std::string ManifestICD::get_manifest_str() const {
std::string out;
out += "{\n";
out += " " + file_format_version.get_version_str() + "\n";
out += " \"ICD\": {\n";
out += " \"library_path\": \"" + fs::fixup_backslashes_in_path(lib_path) + "\",\n";
- out += " \"api_version\": \"" + version_to_string(api_version) + "\"\n";
+ out += " \"api_version\": \"" + version_to_string(api_version) + "\",\n";
+ out += " \"is_portability_driver\": " + to_text(is_portability_driver) + "\n";
out += " }\n";
out += "}\n";
return out;
@@ -639,6 +642,7 @@ VkInstanceCreateInfo* InstanceCreateInfo::get() noexcept {
application_info.apiVersion = api_version;
instance_info.pApplicationInfo = &application_info;
}
+ instance_info.flags = flags;
instance_info.enabledLayerCount = static_cast<uint32_t>(enabled_layers.size());
instance_info.ppEnabledLayerNames = enabled_layers.data();
instance_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
diff --git a/tests/framework/test_util.h b/tests/framework/test_util.h
index 1e8d47baa..c34c94024 100644
--- a/tests/framework/test_util.h
+++ b/tests/framework/test_util.h
@@ -536,6 +536,7 @@ struct ManifestICD {
BUILDER_VALUE(ManifestICD, ManifestVersion, file_format_version, ManifestVersion())
BUILDER_VALUE(ManifestICD, uint32_t, api_version, 0)
BUILDER_VALUE(ManifestICD, std::string, lib_path, {})
+ BUILDER_VALUE(ManifestICD, bool, is_portability_driver, false)
std::string get_manifest_str() const;
};
@@ -762,6 +763,7 @@ struct InstanceCreateInfo {
BUILDER_VALUE(InstanceCreateInfo, VkApplicationInfo, application_info, {})
BUILDER_VALUE(InstanceCreateInfo, std::string, app_name, {})
BUILDER_VALUE(InstanceCreateInfo, std::string, engine_name, {})
+ BUILDER_VALUE(InstanceCreateInfo, uint32_t, flags, 0)
BUILDER_VALUE(InstanceCreateInfo, uint32_t, app_version, 0)
BUILDER_VALUE(InstanceCreateInfo, uint32_t, engine_version, 0)
BUILDER_VALUE(InstanceCreateInfo, uint32_t, api_version, VK_API_VERSION_1_0)
@@ -852,4 +854,13 @@ bool check_permutation(std::initializer_list<const char*> expected, std::vector<
if (!found) return false;
}
return true;
+}
+
+inline bool contains(std::vector<VkExtensionProperties> const& vec, const char* name) {
+ return std::any_of(std::begin(vec), std::end(vec),
+ [name](VkExtensionProperties const& elem) { return string_eq(name, elem.extensionName); });
+}
+inline bool contains(std::vector<VkLayerProperties> const& vec, const char* name) {
+ return std::any_of(std::begin(vec), std::end(vec),
+ [name](VkLayerProperties const& elem) { return string_eq(name, elem.layerName); });
} \ No newline at end of file
diff --git a/tests/loader_layer_tests.cpp b/tests/loader_layer_tests.cpp
index c89a968fb..2b1ad9b0c 100644
--- a/tests/loader_layer_tests.cpp
+++ b/tests/loader_layer_tests.cpp
@@ -315,13 +315,13 @@ TEST(MetaLayers, InvalidComponentLayer) {
EXPECT_TRUE(string_eq(layer_props.layerName, regular_layer_name));
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 2> extensions;
+ std::array<VkExtensionProperties, 3> extensions;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- EXPECT_EQ(extension_count, 2U); // return debug report & debug utils
+ EXPECT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
EXPECT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- EXPECT_EQ(extension_count, 2U);
+ EXPECT_EQ(extension_count, 3U);
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_layer(meta_layer_name);
@@ -360,13 +360,13 @@ TEST(MetaLayers, ExplicitMetaLayer) {
EXPECT_TRUE(check_permutation({regular_layer_name, meta_layer_name}, layer_props));
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 2> extensions;
+ std::array<VkExtensionProperties, 3> extensions;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- EXPECT_EQ(extension_count, 2U); // return debug report & debug utils
+ EXPECT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
EXPECT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- EXPECT_EQ(extension_count, 2U);
+ EXPECT_EQ(extension_count, 3U);
}
{ // don't enable the layer, shouldn't find any layers when calling vkEnumerateDeviceLayerProperties
InstWrapper inst{env.vulkan_functions};
@@ -423,13 +423,13 @@ TEST(MetaLayers, MetaLayerNameInComponentLayers) {
EXPECT_TRUE(string_eq(layer_props.layerName, regular_layer_name));
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 2> extensions;
+ std::array<VkExtensionProperties, 3> extensions;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- EXPECT_EQ(extension_count, 2U); // return debug report & debug utils
+ EXPECT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
EXPECT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- EXPECT_EQ(extension_count, 2U);
+ EXPECT_EQ(extension_count, 3U);
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_layer(meta_layer_name);
@@ -472,13 +472,13 @@ TEST(MetaLayers, MetaLayerWhichAddsMetaLayer) {
EXPECT_TRUE(check_permutation({regular_layer_name, meta_layer_name, meta_meta_layer_name}, layer_props));
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 2> extensions;
+ std::array<VkExtensionProperties, 3> extensions;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- EXPECT_EQ(extension_count, 2U); // return debug report & debug utils
+ EXPECT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
EXPECT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- EXPECT_EQ(extension_count, 2U);
+ EXPECT_EQ(extension_count, 3U);
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_layer(meta_layer_name);
@@ -1318,24 +1318,22 @@ TEST(LayerExtensions, ImplicitNoAdditionalInstanceExtension) {
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&count, nullptr));
ASSERT_EQ(count, 1U);
- // // set enable env-var, layer should load
+ // set enable env-var, layer should load
set_env_var(enable_env_var, "1");
CheckLogForLayerString(env, implicit_layer_name, true);
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- if (extension_count > 0) {
- extension_props.resize(extension_count);
- ASSERT_EQ(VK_SUCCESS,
- env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
- // Make sure the extensions that are implemented only in the test layers is not present.
- for (uint32_t ext = 0; ext < extension_count; ++ext) {
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
- }
- }
+ extension_props.resize(extension_count);
+ ASSERT_EQ(VK_SUCCESS,
+ env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
+ ASSERT_EQ(extension_count, 3U); // debug_utils, debug_report, and portability enumeration
+
+ // Make sure the extensions that are implemented only in the test layers is not present.
+ ASSERT_FALSE(contains(extension_props, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
+ ASSERT_FALSE(contains(extension_props, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
@@ -1381,20 +1379,15 @@ TEST(LayerExtensions, ImplicitDirDispModeInstanceExtension) {
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 3U); // the instance extension, debug_utils, and debug_report
+ ASSERT_EQ(extension_count, 4U); // the instance extension, debug_utils, debug_report, and portability enumeration
extension_props.resize(extension_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
+ ASSERT_EQ(extension_count, 4U);
// Make sure the extensions that are implemented only in the test layers is not present.
- bool found = false;
- for (uint32_t ext = 0; ext < extension_count; ++ext) {
- if (!strcmp(extension_props[ext].extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME)) {
- found = true;
- }
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
- }
- ASSERT_EQ(true, found);
+ ASSERT_TRUE(contains(extension_props, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
+ ASSERT_FALSE(contains(extension_props, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_extension(VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME);
@@ -1441,20 +1434,15 @@ TEST(LayerExtensions, ImplicitDispSurfCountInstanceExtension) {
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 3U); // the instance extension, debug_utils, and debug_report
+ ASSERT_EQ(extension_count, 4U); // the instance extension, debug_utils, debug_report, and portability enumeration
extension_props.resize(extension_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
+ ASSERT_EQ(extension_count, 4U);
// Make sure the extensions that are implemented only in the test layers is not present.
- bool found = false;
- for (uint32_t ext = 0; ext < extension_count; ++ext) {
- if (!strcmp(extension_props[ext].extensionName, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME)) {
- found = true;
- }
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
- }
- ASSERT_EQ(true, found);
+ ASSERT_FALSE(contains(extension_props, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
+ ASSERT_TRUE(contains(extension_props, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_extension(VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME);
@@ -1503,24 +1491,15 @@ TEST(LayerExtensions, ImplicitBothInstanceExtensions) {
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 4U); // the two instance extension plus debug_utils and debug_report
+ ASSERT_EQ(extension_count, 5U); // the two instance extension plus debug_utils, debug_report, portability enumeration
extension_props.resize(extension_count);
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
+ ASSERT_EQ(extension_count, 5U);
// Make sure the extensions that are implemented only in the test layers is not present.
- bool found[2] = {false, false};
- for (uint32_t ext = 0; ext < extension_count; ++ext) {
- if (!strcmp(extension_props[ext].extensionName, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME)) {
- found[0] = true;
- }
- if (!strcmp(extension_props[ext].extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME)) {
- found[1] = true;
- }
- }
- for (uint32_t ext = 0; ext < 2; ++ext) {
- ASSERT_EQ(true, found[ext]);
- }
+ ASSERT_TRUE(contains(extension_props, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
+ ASSERT_TRUE(contains(extension_props, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_extension(VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME)
@@ -1556,16 +1535,16 @@ TEST(LayerExtensions, ExplicitNoAdditionalInstanceExtension) {
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- if (extension_count > 0) {
- extension_props.resize(extension_count);
- ASSERT_EQ(VK_SUCCESS,
- env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
+ ASSERT_EQ(extension_count, 3U); // debug utils, debug report, portability enumeration
+ extension_props.resize(extension_count);
+ ASSERT_EQ(VK_SUCCESS,
+ env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
+ ASSERT_EQ(extension_count, 3U);
- // Make sure the extensions are not present
- for (uint32_t ext = 0; ext < extension_count; ++ext) {
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
- }
+ // Make sure the extensions are not present
+ for (const auto& ext : extension_props) {
+ ASSERT_FALSE(string_eq(ext.extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
+ ASSERT_FALSE(string_eq(ext.extensionName, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
}
// Now query by layer name.
@@ -1573,17 +1552,7 @@ TEST(LayerExtensions, ExplicitNoAdditionalInstanceExtension) {
extension_props.clear();
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(explicit_layer_name, &extension_count, nullptr));
- if (extension_count > 0) {
- extension_props.resize(extension_count);
- ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(explicit_layer_name, &extension_count,
- extension_props.data()));
-
- // Make sure the extensions still aren't present in this layer
- for (uint32_t ext = 0; ext < extension_count; ++ext) {
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
- }
- }
+ ASSERT_EQ(extension_count, 0U);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
@@ -1618,16 +1587,15 @@ TEST(LayerExtensions, ExplicitDirDispModeInstanceExtension) {
uint32_t extension_count = 0;
std::vector<VkExtensionProperties> extension_props;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- if (extension_count > 0) {
- extension_props.resize(extension_count);
- ASSERT_EQ(VK_SUCCESS,
- env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
-
- // Make sure the extensions are not present
- for (uint32_t ext = 0; ext < extension_count; ++ext) {
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
- ASSERT_NE(0, strcmp(extension_props[ext].extensionName, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
- }
+ ASSERT_EQ(extension_count, 3U); // debug utils, debug report, portability enumeration
+ extension_props.resize(extension_count);
+ ASSERT_EQ(VK_SUCCESS,
+ env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_props.data()));
+ ASSERT_EQ(extension_count, 3U);
+ // Make sure the extensions are not present
+ for (const auto& ext : extension_props) {
+ ASSERT_FALSE(string_eq(ext.extensionName, VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME));
+ ASSERT_FALSE(string_eq(ext.extensionName, VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME));
}
// Now query by layer name.
diff --git a/tests/loader_regression_tests.cpp b/tests/loader_regression_tests.cpp
index c5bc2080e..dca30f480 100644
--- a/tests/loader_regression_tests.cpp
+++ b/tests/loader_regression_tests.cpp
@@ -189,32 +189,34 @@ TEST(EnumerateInstanceExtensionProperties, UsageChecks) {
env.reset_icd().add_instance_extensions({first_ext, second_ext});
{ // One Pass
- uint32_t extension_count = 4;
- std::array<VkExtensionProperties, 4> extensions;
+ uint32_t extension_count = 5;
+ std::array<VkExtensionProperties, 5> extensions;
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- ASSERT_EQ(extension_count, 4U); // return debug report & debug utils + our two extensions
+ ASSERT_EQ(extension_count, 5U); // return debug report & debug utils & portability enumeration + our two extensions
// loader always adds the debug report & debug utils extensions
ASSERT_TRUE(first_ext.extensionName == extensions[0].extensionName);
ASSERT_TRUE(second_ext.extensionName == extensions[1].extensionName);
ASSERT_TRUE(string_eq("VK_EXT_debug_report", extensions[2].extensionName));
ASSERT_TRUE(string_eq("VK_EXT_debug_utils", extensions[3].extensionName));
+ ASSERT_TRUE(string_eq("VK_KHR_portability_enumeration", extensions[4].extensionName));
}
{ // Two Pass
uint32_t extension_count = 0;
- std::array<VkExtensionProperties, 4> extensions;
+ std::array<VkExtensionProperties, 5> extensions;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 4U); // return debug report & debug utils + our two extensions
+ ASSERT_EQ(extension_count, 5U); // return debug report & debug utils + our two extensions
ASSERT_EQ(VK_SUCCESS,
env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()));
- ASSERT_EQ(extension_count, 4U);
+ ASSERT_EQ(extension_count, 5U);
// loader always adds the debug report & debug utils extensions
ASSERT_TRUE(first_ext.extensionName == extensions[0].extensionName);
ASSERT_TRUE(second_ext.extensionName == extensions[1].extensionName);
ASSERT_TRUE(string_eq("VK_EXT_debug_report", extensions[2].extensionName));
ASSERT_TRUE(string_eq("VK_EXT_debug_utils", extensions[3].extensionName));
+ ASSERT_TRUE(string_eq("VK_KHR_portability_enumeration", extensions[4].extensionName));
}
}
@@ -226,7 +228,7 @@ TEST(EnumerateInstanceExtensionProperties, PropertyCountLessThanAvailable) {
std::array<VkExtensionProperties, 2> extensions;
{ // use nullptr for null string
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr));
- ASSERT_EQ(extension_count, 2U); // return debug report & debug utils
+ ASSERT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
extension_count = 1; // artificially remove one extension
ASSERT_EQ(VK_INCOMPLETE,
@@ -237,7 +239,7 @@ TEST(EnumerateInstanceExtensionProperties, PropertyCountLessThanAvailable) {
}
{ // use "" for null string
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, nullptr));
- ASSERT_EQ(extension_count, 2U); // return debug report & debug utils
+ ASSERT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
extension_count = 1; // artificially remove one extension
ASSERT_EQ(VK_INCOMPLETE,
@@ -258,31 +260,33 @@ TEST(EnumerateInstanceExtensionProperties, FilterUnkownInstanceExtensions) {
{
uint32_t extension_count = 0;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, nullptr));
- ASSERT_EQ(extension_count, 2U); // return debug report & debug utils
+ ASSERT_EQ(extension_count, 3U); // return debug report & debug utils & portability enumeration
- std::array<VkExtensionProperties, 2> extensions;
+ std::array<VkExtensionProperties, 3> extensions;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, extensions.data()));
- ASSERT_EQ(extension_count, 2U);
+ ASSERT_EQ(extension_count, 3U);
// loader always adds the debug report & debug utils extensions
ASSERT_TRUE(string_eq(extensions[0].extensionName, "VK_EXT_debug_report"));
ASSERT_TRUE(string_eq(extensions[1].extensionName, "VK_EXT_debug_utils"));
+ ASSERT_TRUE(string_eq(extensions[2].extensionName, "VK_KHR_portability_enumeration"));
}
{ // Disable unknown instance extension filtering
set_env_var("VK_LOADER_DISABLE_INST_EXT_FILTER", "1");
uint32_t extension_count = 0;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, nullptr));
- ASSERT_EQ(extension_count, 4U);
+ ASSERT_EQ(extension_count, 5U);
- std::array<VkExtensionProperties, 4> extensions;
+ std::array<VkExtensionProperties, 5> extensions;
ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceExtensionProperties("", &extension_count, extensions.data()));
- ASSERT_EQ(extension_count, 4U);
+ ASSERT_EQ(extension_count, 5U);
ASSERT_EQ(extensions[0], first_ext.get());
ASSERT_EQ(extensions[1], second_ext.get());
// Loader always adds these two extensions
ASSERT_TRUE(string_eq(extensions[2].extensionName, "VK_EXT_debug_report"));
ASSERT_TRUE(string_eq(extensions[3].extensionName, "VK_EXT_debug_utils"));
+ ASSERT_TRUE(string_eq(extensions[4].extensionName, "VK_KHR_portability_enumeration"));
}
}
@@ -3110,3 +3114,170 @@ TEST(SortedPhysicalDevices, DeviceGroupsSortedDisabled) {
}
#endif // __linux__ || __FreeBSD__
+
+const char* portability_driver_warning =
+ "vkCreateDevice: Attempting to create a VkDevice from a VkPhysicalDevice which is from a portability driver "
+ "without the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit in the VkInstanceCreateInfo flags being set "
+ "and the VK_KHR_portability_enumeration extension enabled. In future versions of the loader this "
+ "VkPhysicalDevice will not be enumerated.";
+
+TEST(PortabilityICDConfiguration, PortabilityICDOnly) {
+ FrameworkEnvironment env{};
+ env.add_icd(
+ TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_is_portability_driver(true)));
+
+ auto& driver = env.get_test_icd();
+ driver.physical_devices.emplace_back("physical_device_0");
+ driver.max_icd_interface_version = 1;
+ // TODO - Fix tests when portability devices are not longer enumerated by default
+ { // enable portability extension and flag
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ inst.create_info.add_extension("VK_KHR_portability_enumeration");
+ inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+
+ inst.CheckCreate();
+ DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ CreateDebugUtilsMessenger(log);
+
+ auto phys_dev = inst.GetPhysDev();
+ handle_assert_has_value(phys_dev);
+
+ DeviceWrapper dev_info{inst};
+ dev_info.CheckCreate(phys_dev);
+ ASSERT_FALSE(log.find(portability_driver_warning));
+ }
+ { // enable portability flag but not extension - shouldn't be able to create an instance when filtering is enabled
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+ inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ inst.CheckCreate();
+ DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ CreateDebugUtilsMessenger(log);
+
+ auto phys_dev = inst.GetPhysDev();
+ handle_assert_has_value(phys_dev);
+
+ DeviceWrapper dev_info{inst};
+ dev_info.CheckCreate(phys_dev);
+ ASSERT_TRUE(log.find(portability_driver_warning));
+ }
+ { // enable portability extension but not flag - shouldn't be able to create an instance when filtering is enabled
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.add_extension("VK_KHR_portability_enumeration");
+ inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ inst.CheckCreate();
+ DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ CreateDebugUtilsMessenger(log);
+
+ auto phys_dev = inst.GetPhysDev();
+ handle_assert_has_value(phys_dev);
+
+ DeviceWrapper dev_info{inst};
+ dev_info.CheckCreate(phys_dev);
+ ASSERT_TRUE(log.find(portability_driver_warning));
+ }
+ { // enable neither the portability extension or the flag - shouldn't be able to create an instance when filtering is enabled
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.flags = 0; // make sure its 0 - no portability
+ inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ inst.CheckCreate();
+ DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ CreateDebugUtilsMessenger(log);
+
+ auto phys_dev = inst.GetPhysDev();
+ handle_assert_has_value(phys_dev);
+
+ DeviceWrapper dev_info{inst};
+ dev_info.CheckCreate(phys_dev);
+ ASSERT_TRUE(log.find(portability_driver_warning));
+ }
+}
+
+TEST(PortabilityICDConfiguration, PortabilityAndRegularICD) {
+ FrameworkEnvironment env{};
+ env.add_icd(TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA)));
+ env.add_icd(
+ TestICDDetails(ManifestICD{}.set_lib_path(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA).set_is_portability_driver(true)));
+
+ auto& driver0 = env.get_test_icd(0);
+ auto& driver1 = env.get_test_icd(1);
+
+ driver0.physical_devices.emplace_back("physical_device_0");
+ driver0.max_icd_interface_version = 1;
+
+ driver1.physical_devices.emplace_back("portability_physical_device_1");
+ driver1.max_icd_interface_version = 1;
+ // TODO - Fix tests when portability devices are not longer enumerated by default
+ { // enable portability extension and flag
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ inst.create_info.add_extension("VK_KHR_portability_enumeration");
+ inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+ inst.CheckCreate();
+ DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ CreateDebugUtilsMessenger(log);
+
+ auto phys_devs = inst.GetPhysDevs(2);
+ for (const auto& phys_dev : phys_devs) {
+ handle_assert_has_value(phys_dev);
+ }
+ DeviceWrapper dev_info_0{inst};
+ DeviceWrapper dev_info_1{inst};
+ dev_info_0.CheckCreate(phys_devs[0]);
+ dev_info_1.CheckCreate(phys_devs[1]);
+ ASSERT_FALSE(log.find(portability_driver_warning));
+ }
+ { // enable portability extension but not flag - should only enumerate 1 physical device when filtering is enabled
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ inst.create_info.add_extension("VK_KHR_portability_enumeration");
+ inst.CheckCreate();
+ DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ CreateDebugUtilsMessenger(log);
+
+ auto phys_devs = inst.GetPhysDevs(2);
+ for (const auto& phys_dev : phys_devs) {
+ handle_assert_has_value(phys_dev);
+ }
+ DeviceWrapper dev_info_0{inst};
+ DeviceWrapper dev_info_1{inst};
+ dev_info_0.CheckCreate(phys_devs[0]);
+ dev_info_1.CheckCreate(phys_devs[1]);
+ ASSERT_TRUE(log.find(portability_driver_warning));
+ }
+ { // enable portability flag but not extension - should only enumerate 1 physical device when filtering is enabled
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ inst.create_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+ inst.CheckCreate();
+ DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ CreateDebugUtilsMessenger(log);
+
+ auto phys_devs = inst.GetPhysDevs(2);
+ for (const auto& phys_dev : phys_devs) {
+ handle_assert_has_value(phys_dev);
+ }
+ DeviceWrapper dev_info_0{inst};
+ DeviceWrapper dev_info_1{inst};
+ dev_info_0.CheckCreate(phys_devs[0]);
+ dev_info_1.CheckCreate(phys_devs[1]);
+ ASSERT_TRUE(log.find(portability_driver_warning));
+ }
+ { // do not enable portability extension or flag - should only enumerate 1 physical device when filtering is enabled
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ inst.CheckCreate();
+ DebugUtilsWrapper log{inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ CreateDebugUtilsMessenger(log);
+ auto phys_devs = inst.GetPhysDevs(2);
+ for (const auto& phys_dev : phys_devs) {
+ handle_assert_has_value(phys_dev);
+ }
+ DeviceWrapper dev_info_0{inst};
+ DeviceWrapper dev_info_1{inst};
+ dev_info_0.CheckCreate(phys_devs[0]);
+ dev_info_1.CheckCreate(phys_devs[1]);
+ ASSERT_TRUE(log.find(portability_driver_warning));
+ }
+}