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-03-26 02:08:57 +0300
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>2022-04-05 04:17:07 +0300
commita06dd5484ade7c4a5613e6b6e82b8c8f36b7c1fb (patch)
tree521cfe537d46a3164adf2b0177b755546b5ce868
parentaeec557162daa92786e77f5c94d984ed365e79ce (diff)
Clean up version checking logic
Add a few helper functions to simplify checking that a X.Y.Z version is sufficient.
-rw-r--r--loader/loader.c161
-rw-r--r--loader/loader.h15
-rw-r--r--loader/loader_common.h3
-rw-r--r--loader/loader_linux.c14
-rw-r--r--loader/terminator.c21
-rw-r--r--loader/trampoline.c11
-rw-r--r--loader/vk_loader_platform.h4
-rw-r--r--tests/loader_layer_tests.cpp34
8 files changed, 134 insertions, 129 deletions
diff --git a/loader/loader.c b/loader/loader.c
index 82d42690c..376067937 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -101,6 +101,32 @@ static struct loader_icd_tramp_list scanned_icds;
LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
+loader_api_version loader_make_version(uint32_t version) {
+ loader_api_version out_version;
+ out_version.major = VK_API_VERSION_MAJOR(version);
+ out_version.minor = VK_API_VERSION_MINOR(version);
+ out_version.patch = VK_API_VERSION_PATCH(version);
+ return out_version;
+}
+
+loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32_t patch) {
+ loader_api_version out_version;
+ out_version.major = major;
+ out_version.minor = minor;
+ out_version.patch = patch;
+ return out_version;
+}
+
+// Helper macros for determining if a version is valid or not
+bool loader_check_version_meets_required(loader_api_version required, loader_api_version version) {
+ // major version is satisfied
+ return (version.major > required.major) ||
+ // major version is equal, minor version is patch version is gerater to minimum minor
+ (version.major == required.major && version.minor > required.minor) ||
+ // major and minor version are equal, patch version is greater or equal to minimum patch
+ (version.major == required.major && version.minor == required.minor && version.patch >= required.patch);
+}
+
// Wrapper around opendir so that the dirent_on_windows gets the instance it needs
// while linux opendir & readdir does not
DIR *loader_opendir(const struct loader_instance *instance, const char *name) {
@@ -246,7 +272,7 @@ static size_t loader_platform_combine_path(char *dest, size_t len, ...) {
// Given string of three part form "maj.min.pat" convert to a vulkan version number.
// Also can understand four part form "variant.major.minor.patch" if provided.
-static uint32_t loader_make_version(char *vers_str) {
+static uint32_t loader_parse_version_string(char *vers_str) {
uint32_t variant = 0, major = 0, minor = 0, patch = 0;
char *vers_tok;
@@ -279,15 +305,6 @@ static uint32_t loader_make_version(char *vers_str) {
return VK_MAKE_API_VERSION(variant, major, minor, patch);
}
-static loader_api_version loader_make_api_version(char *vers_str) {
- uint32_t version = loader_make_version(vers_str);
- loader_api_version api_version;
- api_version.major = VK_API_VERSION_MAJOR(version);
- api_version.minor = VK_API_VERSION_MINOR(version);
- api_version.patch = VK_API_VERSION_PATCH(version);
- return api_version;
-}
-
bool compare_vk_extension_properties(const VkExtensionProperties *op1, const VkExtensionProperties *op2) {
return strcmp(op1->extensionName, op2->extensionName) == 0 ? true : false;
}
@@ -949,15 +966,13 @@ static void loader_add_implicit_layer(const struct loader_instance *inst, const
// If the implicit layer is supposed to be enable, make sure the layer supports at least the same API version
// that the application is asking (i.e. layer's API >= app's API). If it's not, disable this layer.
if (enable) {
- uint16_t layer_api_major_version = VK_API_VERSION_MAJOR(prop->info.specVersion);
- uint16_t layer_api_minor_version = VK_API_VERSION_MINOR(prop->info.specVersion);
- if (inst->app_api_major_version > layer_api_major_version ||
- (inst->app_api_major_version == layer_api_major_version && inst->app_api_minor_version > layer_api_minor_version)) {
+ loader_api_version prop_version = loader_make_version(prop->info.specVersion);
+ if (!loader_check_version_meets_required(inst->app_api_version, prop_version)) {
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
"loader_add_implicit_layer: Disabling implicit layer %s for using an old API version %d.%d versus "
"application requested %d.%d",
- prop->info.layerName, layer_api_major_version, layer_api_minor_version, inst->app_api_major_version,
- inst->app_api_minor_version);
+ prop->info.layerName, prop_version.major, prop_version.minor, inst->app_api_version.major,
+ inst->app_api_version.minor);
enable = false;
}
}
@@ -981,21 +996,18 @@ bool loader_add_meta_layer(const struct loader_instance *inst, const struct load
bool found = true;
// We need to add all the individual component layers
- uint16_t meta_layer_api_major_version = VK_API_VERSION_MAJOR(prop->info.specVersion);
- uint16_t meta_layer_api_minor_version = VK_API_VERSION_MINOR(prop->info.specVersion);
+ loader_api_version meta_layer_api_version = loader_make_version(prop->info.specVersion);
for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) {
const struct loader_layer_properties *search_prop =
loader_find_layer_property(prop->component_layer_names[comp_layer], source_list);
if (search_prop != NULL) {
- uint16_t search_layer_api_major_version = VK_API_VERSION_MAJOR(search_prop->info.specVersion);
- uint16_t search_layer_api_minor_version = VK_API_VERSION_MINOR(search_prop->info.specVersion);
- if (meta_layer_api_major_version != search_layer_api_major_version ||
- meta_layer_api_minor_version > search_layer_api_minor_version) {
+ loader_api_version search_prop_version = loader_make_version(prop->info.specVersion);
+ if (!loader_check_version_meets_required(meta_layer_api_version, search_prop_version)) {
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
"loader_add_meta_layer: Meta-layer API version %u.%u, component layer %s version %u.%u, may have "
"incompatibilities (Policy #LLP_LAYER_8)!",
- meta_layer_api_major_version, meta_layer_api_minor_version, search_prop->info.layerName,
- search_layer_api_major_version, meta_layer_api_minor_version);
+ meta_layer_api_version.major, meta_layer_api_version.minor, search_prop->info.layerName,
+ search_prop_version.major, search_prop_version.minor);
}
// If the component layer is itself an implicit layer, we need to do the implicit layer enable
@@ -1474,13 +1486,12 @@ static VkResult loader_scanned_icd_add(const struct loader_instance *inst, struc
icd_tramp_list->capacity *= 2;
}
- uint32_t major_version = VK_API_VERSION_MAJOR(api_version);
- uint32_t minor_version = VK_API_VERSION_MINOR(api_version);
- if (interface_vers <= 4 && 1 == major_version && 0 < minor_version) {
+ loader_api_version api_version_struct = loader_make_version(api_version);
+ if (interface_vers <= 4 && loader_check_version_meets_required(LOADER_VERSION_1_1_0, api_version_struct)) {
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
"loader_scanned_icd_add: Driver %s supports Vulkan %u.%u, but only supports loader interface version %u."
" Interface version 5 or newer required to support this version of Vulkan (Policy #LDP_DRIVER_7)",
- filename, major_version, minor_version, interface_vers);
+ filename, api_version_struct.major, api_version_struct.minor, interface_vers);
}
new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]);
@@ -1520,8 +1531,8 @@ void loader_initialize(void) {
windows_initialization();
#endif
- loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "Vulkan Loader Version %d.%d.%d", VK_API_VERSION_MAJOR(VK_HEADER_VERSION_COMPLETE),
- VK_API_VERSION_MINOR(VK_HEADER_VERSION_COMPLETE), VK_API_VERSION_PATCH(VK_HEADER_VERSION_COMPLETE));
+ loader_api_version version = loader_make_version(VK_HEADER_VERSION_COMPLETE);
+ loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "Vulkan Loader Version %d.%d.%d", version.major, version.minor, version.patch);
#if defined(GIT_BRANCH_NAME) && defined(GIT_TAG_INFO)
#define LOADER_GIT_STRINGIFY(x) #x
@@ -1713,8 +1724,7 @@ out:
static bool verify_meta_layer_component_layers(const struct loader_instance *inst, struct loader_layer_properties *prop,
struct loader_layer_list *instance_layers) {
bool success = true;
- const uint32_t expected_major = VK_API_VERSION_MAJOR(prop->info.specVersion);
- const uint32_t expected_minor = VK_API_VERSION_MINOR(prop->info.specVersion);
+ loader_api_version meta_layer_version = loader_make_version(prop->info.specVersion);
for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) {
struct loader_layer_properties *comp_prop =
@@ -1729,14 +1739,14 @@ static bool verify_meta_layer_component_layers(const struct loader_instance *ins
break;
}
- // Check the version of each layer, they need to at least match MAJOR and MINOR
- uint32_t cur_major = VK_API_VERSION_MAJOR(comp_prop->info.specVersion);
- uint32_t cur_minor = VK_API_VERSION_MINOR(comp_prop->info.specVersion);
- if (cur_major != expected_major || cur_minor != expected_minor) {
+ // Check the version of each layer, they need to be equal
+ loader_api_version comp_prop_version = loader_make_version(comp_prop->info.specVersion);
+ if (meta_layer_version.major != comp_prop_version.major || meta_layer_version.minor != comp_prop_version.minor) {
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
"verify_meta_layer_component_layers: Meta-layer uses API version %d.%d, but component "
"layer %d uses API version %d.%d. Skipping this layer.",
- expected_major, expected_minor, comp_layer, cur_major, cur_minor);
+ meta_layer_version.major, meta_layer_version.minor, comp_layer, comp_prop_version.major,
+ comp_prop_version.minor);
success = false;
break;
@@ -1898,11 +1908,6 @@ static void remove_all_non_valid_override_layers(struct loader_instance *inst, s
}
}
-static inline bool layer_json_supports_pre_instance_tag(const loader_api_version *layer_json) {
- // Supported versions started in 1.1.2, so anything newer
- return layer_json->major > 1 || layer_json->minor > 1 || (layer_json->minor == 1 && layer_json->patch > 1);
-}
-
static VkResult loader_read_layer_json(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list,
cJSON *layer_node, loader_api_version version, cJSON *item, bool is_implicit,
char *filename) {
@@ -2001,8 +2006,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
// is completely optional. So, no check put in place.
if (!strcmp(name, VK_OVERRIDE_LAYER_NAME)) {
cJSON *expiration;
-
- if (version.major == 0 || (version.minor == 1 && version.patch < 2) || version.minor == 0) {
+ if (!loader_check_version_meets_required(loader_combine_version(1, 1, 2), version)) {
loader_log(
inst, VULKAN_LOADER_WARN_BIT, 0,
"Override layer expiration date not added until version 1.1.2. Please update JSON file version appropriately.");
@@ -2110,7 +2114,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
}
}
} else if (NULL != component_layers) {
- if (version.major == 0 || (version.minor == 1 && version.patch < 1) || (version.minor == 0)) {
+ if (!loader_check_version_meets_required(LOADER_VERSION_1_1_0, version)) {
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
"Indicating meta-layer-specific component_layers, but using older JSON file version.");
}
@@ -2196,7 +2200,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
override_paths = cJSON_GetObjectItem(layer_node, "override_paths");
if (NULL != override_paths) {
- if (version.major == 0 || (version.minor == 1 && version.patch < 1) || version.minor == 0) {
+ if (!loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
"Indicating meta-layer-specific override paths, but using older JSON file version.");
}
@@ -2241,7 +2245,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Layer name %s does not conform to naming standard (Policy #LLP_LAYER_3)",
props->info.layerName);
}
- props->info.specVersion = loader_make_version(api_version);
+ props->info.specVersion = loader_parse_version_string(api_version);
props->info.implementationVersion = atoi(implementation_version);
strncpy((char *)props->info.description, description, sizeof(props->info.description));
props->info.description[sizeof(props->info.description) - 1] = '\0';
@@ -2306,7 +2310,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
// vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0)
GET_JSON_OBJECT(layer_node, functions)
if (functions != NULL) {
- if (version.major > 1 || version.minor >= 1) {
+ if (loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
GET_JSON_ITEM(inst, functions, vkNegotiateLoaderLayerInterfaceVersion)
if (vkNegotiateLoaderLayerInterfaceVersion != NULL)
strncpy(props->functions.str_negotiate_interface, vkNegotiateLoaderLayerInterfaceVersion,
@@ -2319,7 +2323,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
GET_JSON_ITEM(inst, functions, vkGetDeviceProcAddr)
if (vkGetInstanceProcAddr != NULL) {
strncpy(props->functions.str_gipa, vkGetInstanceProcAddr, sizeof(props->functions.str_gipa));
- if (version.major > 1 || version.minor >= 1) {
+ if (loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
"Layer \"%s\" using deprecated \'vkGetInstanceProcAddr\' tag which was deprecated starting with JSON "
"file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
@@ -2330,7 +2334,7 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] = '\0';
if (vkGetDeviceProcAddr != NULL) {
strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr, sizeof(props->functions.str_gdpa));
- if (version.major > 1 || version.minor >= 1) {
+ if (loader_check_version_meets_required(loader_combine_version(1, 1, 0), version)) {
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
"Layer \"%s\" using deprecated \'vkGetDeviceProcAddr\' tag which was deprecated starting with JSON "
"file version 1.1.0. The new vkNegotiateLoaderLayerInterfaceVersion function is preferred, though for "
@@ -2435,7 +2439,8 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
// Read in the pre-instance stuff
cJSON *pre_instance = cJSON_GetObjectItem(layer_node, "pre_instance_functions");
if (NULL != pre_instance) {
- if (!layer_json_supports_pre_instance_tag(&version)) {
+ // Supported versions started in 1.1.2, so anything newer
+ if (!loader_check_version_meets_required(loader_combine_version(1, 1, 2), version)) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"Found pre_instance_functions section in layer from \"%s\". This section is only valid in manifest version "
"1.1.2 or later. The section will be ignored",
@@ -2550,14 +2555,6 @@ static inline bool is_valid_layer_json_version(const loader_api_version *layer_j
return false;
}
-static inline bool layer_json_supports_multiple_layers(const loader_api_version *layer_json) {
- // Supported versions started in 1.0.1, so anything newer
- if ((layer_json->major > 1 || layer_json->minor > 0 || layer_json->patch > 1)) {
- return true;
- }
- return false;
-}
-
// Given a cJSON struct (json) of the top level JSON object from layer manifest
// file, add entry to the layer_list. Fill out the layer_properties in this list
// entry from the input cJSON object.
@@ -2590,7 +2587,7 @@ static VkResult loader_add_layer_properties(const struct loader_instance *inst,
}
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Found manifest file %s (file version %s)", filename, file_vers);
// Get the major/minor/and patch as integers for easier comparison
- json_version = loader_make_api_version(file_vers);
+ json_version = loader_make_version(loader_parse_version_string(file_vers));
if (!is_valid_layer_json_version(&json_version)) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_LAYER_BIT, 0,
@@ -2603,7 +2600,8 @@ static VkResult loader_add_layer_properties(const struct loader_instance *inst,
layers_node = cJSON_GetObjectItem(json, "layers");
if (layers_node != NULL) {
int numItems = cJSON_GetArraySize(layers_node);
- if (!layer_json_supports_multiple_layers(&json_version)) {
+ // Supported versions started in 1.0.1, so anything newer
+ if (!loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
"loader_add_layer_properties: \'layers\' tag not supported until file version 1.0.1, but %s is reporting "
"version %s",
@@ -2641,7 +2639,7 @@ static VkResult loader_add_layer_properties(const struct loader_instance *inst,
// Throw a warning if we encounter multiple "layer" objects in file
// versions newer than 1.0.0. Having multiple objects with the same
// name at the same level is actually a JSON standard violation.
- if (layer_count > 1 && layer_json_supports_multiple_layers(&json_version)) {
+ if (layer_count > 1 && loader_check_version_meets_required(loader_combine_version(1, 0, 1), json_version)) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
"loader_add_layer_properties: Multiple 'layer' nodes are deprecated starting in file version \"1.0.1\". "
"Please use 'layers' : [] array instead in %s.",
@@ -3437,9 +3435,10 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t
loader_log(inst, VULKAN_LOADER_DRIVER_BIT, 0, "Found ICD manifest file %s, version %s", file_str, file_vers);
// Get the version of the driver manifest
- json_file_version = loader_make_api_version(file_vers);
+ json_file_version = loader_make_version(loader_parse_version_string(file_vers));
- if (json_file_version.major != 1 || json_file_version.minor != 0 || json_file_version.patch > 1) {
+ // Loader only knows versions 1.0.0 and 1.0.1, anything above it is unknown
+ if (loader_check_version_meets_required(loader_combine_version(1, 0, 2), json_file_version)) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
"loader_icd_scan: %s has unknown icd manifest file version %d.%d.%d. May cause errors.", file_str,
json_file_version.major, json_file_version.minor, json_file_version.patch);
@@ -3525,7 +3524,7 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t
json = NULL;
continue;
}
- vers = loader_make_version(temp);
+ vers = loader_parse_version_string(temp);
cJSON_Free(inst, temp);
} else {
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
@@ -4132,12 +4131,6 @@ out:
VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo,
const struct loader_layer_list *instance_layers) {
- VkResult err = VK_SUCCESS;
- uint16_t layer_api_major_version;
- uint16_t layer_api_minor_version;
- uint32_t i;
- struct loader_layer_properties *prop;
-
assert(inst && "Cannot have null instance");
if (!loader_init_layer_list(inst, &inst->app_activated_layer_list)) {
@@ -4156,33 +4149,31 @@ VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkIns
loader_add_implicit_layers(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, instance_layers);
// Add any layers specified via environment variable next
- err = loader_add_environment_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, "VK_INSTANCE_LAYERS",
- &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, instance_layers);
+ VkResult err =
+ loader_add_environment_layers(inst, VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER, "VK_INSTANCE_LAYERS",
+ &inst->app_activated_layer_list, &inst->expanded_activated_layer_list, instance_layers);
if (err != VK_SUCCESS) {
- goto out;
+ return err;
}
// Add layers specified by the application
err = loader_add_layer_names_to_list(inst, &inst->app_activated_layer_list, &inst->expanded_activated_layer_list,
pCreateInfo->enabledLayerCount, pCreateInfo->ppEnabledLayerNames, instance_layers);
- for (i = 0; i < inst->expanded_activated_layer_list.count; i++) {
+ for (uint32_t i = 0; i < inst->expanded_activated_layer_list.count; i++) {
// Verify that the layer api version is at least that of the application's request, if not, throw a warning since
// undefined behavior could occur.
- prop = inst->expanded_activated_layer_list.list + i;
- layer_api_major_version = VK_API_VERSION_MAJOR(prop->info.specVersion);
- layer_api_minor_version = VK_API_VERSION_MINOR(prop->info.specVersion);
- if (inst->app_api_major_version > layer_api_major_version ||
- (inst->app_api_major_version == layer_api_major_version && inst->app_api_minor_version > layer_api_minor_version)) {
+ struct loader_layer_properties *prop = inst->expanded_activated_layer_list.list + i;
+ loader_api_version prop_spec_version = loader_make_version(prop->info.specVersion);
+ if (!loader_check_version_meets_required(inst->app_api_version, prop_spec_version)) {
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
"loader_add_to_layer_list: Explicit layer %s is using an old API version %" PRIu16 ".%" PRIu16
" versus application requested %" PRIu16 ".%" PRIu16,
- prop->info.layerName, layer_api_major_version, layer_api_minor_version, inst->app_api_major_version,
- inst->app_api_minor_version);
+ prop->info.layerName, prop_spec_version.major, prop_spec_version.minor, inst->app_api_version.major,
+ inst->app_api_version.minor);
}
}
-out:
return err;
}
@@ -5177,7 +5168,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI
// Force on "VK_KHR_get_physical_device_properties2" for Linux as we use it for GPU sorting. This
// should be done if the API version of either the application or the driver does not natively support
// the core version of vkGetPhysicalDevicePoroperties2 entrypoint.
- if ((ptr_instance->app_api_major_version == 1 && ptr_instance->app_api_minor_version == 0) ||
+ if ((ptr_instance->app_api_version.major == 1 && ptr_instance->app_api_version.minor == 0) ||
(VK_API_VERSION_MAJOR(icd_term->scanned_icd->api_version) == 1 &&
VK_API_VERSION_MINOR(icd_term->scanned_icd->api_version) == 0)) {
prop = get_extension_property(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, &icd_exts);
@@ -5228,7 +5219,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI
VkApplicationInfo icd_app_info;
uint32_t icd_version_nopatch =
VK_MAKE_API_VERSION(0, VK_API_VERSION_MAJOR(icd_version), VK_API_VERSION_MINOR(icd_version), 0);
- uint32_t requested_version = pCreateInfo == NULL || pCreateInfo->pApplicationInfo == NULL
+ uint32_t requested_version = (pCreateInfo == NULL || pCreateInfo->pApplicationInfo == NULL)
? VK_API_VERSION_1_0
: pCreateInfo->pApplicationInfo->apiVersion;
if ((requested_version != 0) && (icd_version_nopatch == VK_API_VERSION_1_0)) {
diff --git a/loader/loader.h b/loader/loader.h
index 23d6229dd..48faed94b 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -163,3 +163,18 @@ VkStringErrorFlags vk_string_validate(const int max_length, const char *char_arr
char *loader_get_next_path(char *path);
VkResult add_data_files(const struct loader_instance *inst, char *search_path, struct loader_data_files *out_files,
bool use_first_found_manifest);
+
+loader_api_version loader_make_version(uint32_t version);
+loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32_t patch);
+
+// Helper macros for determining if a version is valid or not
+bool loader_check_version_meets_required(loader_api_version required, loader_api_version version);
+
+// Convenience macros for common versions
+#ifndef LOADER_VERSION_1_0_0
+#define LOADER_VERSION_1_0_0 loader_combine_version(1, 0, 0)
+#endif
+
+#ifndef LOADER_VERSION_1_1_0
+#define LOADER_VERSION_1_1_0 loader_combine_version(1, 1, 0)
+#endif \ No newline at end of file
diff --git a/loader/loader_common.h b/loader/loader_common.h
index cee3eca1a..94b11d523 100644
--- a/loader/loader_common.h
+++ b/loader/loader_common.h
@@ -236,8 +236,7 @@ struct loader_instance {
uint64_t magic; // Should be LOADER_MAGIC_NUMBER
// Vulkan API version the app is intending to use.
- uint16_t app_api_major_version;
- uint16_t app_api_minor_version;
+ loader_api_version app_api_version;
// We need to manually track physical devices over time. If the user
// re-queries the information, we don't want to delete old data or
diff --git a/loader/loader_linux.c b/loader/loader_linux.c
index b78a5ecb2..4df20134e 100644
--- a/loader/loader_linux.c
+++ b/loader/loader_linux.c
@@ -236,10 +236,7 @@ VkResult linux_read_sorted_physical_devices(struct loader_instance *inst, uint32
struct loader_phys_dev_per_icd *icd_devices, uint32_t phys_dev_count,
struct loader_physical_device_term **sorted_device_term) {
VkResult res = VK_SUCCESS;
- bool app_is_vulkan_1_1 = false;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
- app_is_vulkan_1_1 = true;
- }
+ bool app_is_vulkan_1_1 = loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version);
struct LinuxSortedDeviceInfo *sorted_device_info =
loader_instance_heap_alloc(inst, phys_dev_count * sizeof(struct LinuxSortedDeviceInfo), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
@@ -271,7 +268,7 @@ VkResult linux_read_sorted_physical_devices(struct loader_instance *inst, uint32
sorted_device_info[index].device_id = dev_props.deviceID;
bool device_is_1_1_capable =
- VK_API_VERSION_MAJOR(dev_props.apiVersion) == 1 && VK_API_VERSION_MINOR(dev_props.apiVersion) >= 1;
+ loader_check_version_meets_required(LOADER_VERSION_1_1_0, loader_make_version(dev_props.apiVersion));
if (!sorted_device_info[index].has_pci_bus_info) {
uint32_t ext_count;
icd_term->dispatch.EnumerateDeviceExtensionProperties(sorted_device_info[index].physical_device, NULL, &ext_count,
@@ -353,10 +350,7 @@ out:
VkResult linux_sort_physical_device_groups(struct loader_instance *inst, uint32_t group_count,
struct loader_physical_device_group_term *sorted_group_term) {
VkResult res = VK_SUCCESS;
- bool app_is_vulkan_1_1 = false;
- if (inst->app_api_major_version >= 1 && inst->app_api_minor_version >= 1) {
- app_is_vulkan_1_1 = true;
- }
+ bool app_is_vulkan_1_1 = loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version);
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, "linux_sort_physical_device_groups: Original order:");
@@ -380,7 +374,7 @@ VkResult linux_sort_physical_device_groups(struct loader_instance *inst, uint32_
sorted_group_term[group].internal_device_info[gpu].device_id = dev_props.deviceID;
bool device_is_1_1_capable =
- VK_API_VERSION_MAJOR(dev_props.apiVersion) == 1 && VK_API_VERSION_MINOR(dev_props.apiVersion) >= 1;
+ loader_check_version_meets_required(LOADER_VERSION_1_1_0, loader_make_version(dev_props.apiVersion));
if (!sorted_group_term[group].internal_device_info[gpu].has_pci_bus_info) {
uint32_t ext_count;
icd_term->dispatch.EnumerateDeviceExtensionProperties(
diff --git a/loader/terminator.c b/loader/terminator.c
index 5b890f725..0f768c32d 100644
--- a/loader/terminator.c
+++ b/loader/terminator.c
@@ -31,6 +31,7 @@
#include "allocation.h"
#include "loader_common.h"
+#include "loader.h"
#include "log.h"
// Terminators for 1.0 functions
@@ -132,7 +133,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures2(VkPhysicalDevic
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceFeatures2 fpGetPhysicalDeviceFeatures2 = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceFeatures2 = icd_term->dispatch.GetPhysicalDeviceFeatures2;
}
if (fpGetPhysicalDeviceFeatures2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
@@ -188,7 +189,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties2(VkPhysicalDev
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceProperties2 fpGetPhysicalDeviceProperties2 = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceProperties2 = icd_term->dispatch.GetPhysicalDeviceProperties2;
}
if (fpGetPhysicalDeviceProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
@@ -251,7 +252,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties2(VkPhysi
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceFormatProperties2 fpGetPhysicalDeviceFormatProperties2 = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceFormatProperties2;
}
if (fpGetPhysicalDeviceFormatProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
@@ -289,7 +290,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceImageFormatProperties2 fpGetPhysicalDeviceImageFormatProperties2 = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceImageFormatProperties2;
}
if (fpGetPhysicalDeviceImageFormatProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
@@ -329,7 +330,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties2(Vk
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceQueueFamilyProperties2 fpGetPhysicalDeviceQueueFamilyProperties2 = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceQueueFamilyProperties2 = icd_term->dispatch.GetPhysicalDeviceQueueFamilyProperties2;
}
if (fpGetPhysicalDeviceQueueFamilyProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
@@ -387,7 +388,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties2(VkPhysi
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceMemoryProperties2 fpGetPhysicalDeviceMemoryProperties2 = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceMemoryProperties2 = icd_term->dispatch.GetPhysicalDeviceMemoryProperties2;
}
if (fpGetPhysicalDeviceMemoryProperties2 == NULL && inst->enabled_known_extensions.khr_get_physical_device_properties2) {
@@ -425,7 +426,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperti
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceSparseImageFormatProperties2 fpGetPhysicalDeviceSparseImageFormatProperties2 = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceSparseImageFormatProperties2 = icd_term->dispatch.GetPhysicalDeviceSparseImageFormatProperties2;
}
if (fpGetPhysicalDeviceSparseImageFormatProperties2 == NULL &&
@@ -495,7 +496,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalBufferProperties(
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceExternalBufferProperties fpGetPhysicalDeviceExternalBufferProperties = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceExternalBufferProperties = icd_term->dispatch.GetPhysicalDeviceExternalBufferProperties;
}
if (fpGetPhysicalDeviceExternalBufferProperties == NULL && inst->enabled_known_extensions.khr_external_memory_capabilities) {
@@ -538,7 +539,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalSemaphoreProperti
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceExternalSemaphoreProperties fpGetPhysicalDeviceExternalSemaphoreProperties = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceExternalSemaphoreProperties = icd_term->dispatch.GetPhysicalDeviceExternalSemaphoreProperties;
}
if (fpGetPhysicalDeviceExternalSemaphoreProperties == NULL &&
@@ -585,7 +586,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceExternalFenceProperties(
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceExternalFenceProperties fpGetPhysicalDeviceExternalFenceProperties = NULL;
- if (inst->app_api_major_version > 1 || inst->app_api_minor_version >= 1) {
+ if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceExternalFenceProperties = icd_term->dispatch.GetPhysicalDeviceExternalFenceProperties;
}
if (fpGetPhysicalDeviceExternalFenceProperties == NULL && inst->enabled_known_extensions.khr_external_fence_capabilities) {
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 4b29b5694..604d69741 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -78,7 +78,8 @@ LOADER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkI
// First check if instance is valid - loader_get_instance() returns NULL if it isn't.
struct loader_instance *ptr_instance = loader_get_instance(instance);
- if (ptr_instance != NULL && (ptr_instance->app_api_minor_version > 2)) {
+ if (ptr_instance != NULL &&
+ loader_check_version_meets_required(loader_combine_version(1, 3, 0), ptr_instance->app_api_version)) {
// New behavior
return NULL;
} else {
@@ -474,11 +475,11 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
// Save the application version
if (NULL == pCreateInfo->pApplicationInfo || 0 == pCreateInfo->pApplicationInfo->apiVersion) {
- ptr_instance->app_api_major_version = 1;
- ptr_instance->app_api_minor_version = 0;
+ ptr_instance->app_api_version = LOADER_VERSION_1_0_0;
} else {
- ptr_instance->app_api_major_version = VK_API_VERSION_MAJOR(pCreateInfo->pApplicationInfo->apiVersion);
- ptr_instance->app_api_minor_version = VK_API_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion);
+ ptr_instance->app_api_version = loader_make_version(pCreateInfo->pApplicationInfo->apiVersion);
+ // zero out the patch version since we don't actually want to compare with it
+ ptr_instance->app_api_version.patch = 0;
}
// Look for one or more VK_EXT_debug_report or VK_EXT_debug_utils create info structures
diff --git a/loader/vk_loader_platform.h b/loader/vk_loader_platform.h
index ccce85b36..594a24986 100644
--- a/loader/vk_loader_platform.h
+++ b/loader/vk_loader_platform.h
@@ -194,7 +194,9 @@ static inline char *loader_platform_executable_path(char *buffer, size_t size) {
-1,
#endif
};
- if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buffer, &size, NULL, 0) < 0) return NULL;
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buffer, &size, NULL, 0) < 0) {
+ return NULL;
+ }
return buffer;
}
diff --git a/tests/loader_layer_tests.cpp b/tests/loader_layer_tests.cpp
index 9d566394c..7f2bd1e3c 100644
--- a/tests/loader_layer_tests.cpp
+++ b/tests/loader_layer_tests.cpp
@@ -766,15 +766,15 @@ TEST(OverrideMetaLayer, NewerComponentLayerInMetaLayer) {
.set_disable_environment("DisableMeIfYouCan")),
"meta_test_layer.json");
{ // global functions
- uint32_t layer_count = 1;
+ uint32_t layer_count = 0;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&layer_count, nullptr));
- EXPECT_EQ(layer_count, 1U);
+ EXPECT_EQ(layer_count, 2U);
- std::array<VkLayerProperties, 1> layer_props;
+ std::array<VkLayerProperties, 2> layer_props;
EXPECT_EQ(VK_SUCCESS, env.vulkan_functions.vkEnumerateInstanceLayerProperties(&layer_count, layer_props.data()));
- EXPECT_EQ(layer_count, 1U);
+ EXPECT_EQ(layer_count, 2U);
// Expect the explicit layer to still be found
- EXPECT_TRUE(string_eq(layer_props[0].layerName, regular_layer_name));
+ EXPECT_TRUE(check_permutation({regular_layer_name, lunarg_meta_layer_name}, layer_props));
}
{
// 1.1 instance
@@ -783,17 +783,17 @@ TEST(OverrideMetaLayer, NewerComponentLayerInMetaLayer) {
inst.create_info.set_api_version(1, 1, 0);
inst.CheckCreate();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
- ASSERT_TRUE(
- env.debug_log.find("verify_meta_layer_component_layers: Meta-layer uses API version 1.1, but component layer 0 uses "
- "API version 1.2. Skipping this layer."));
+ // Newer component is allowed now
+ EXPECT_TRUE(env.debug_log.find(std::string("Insert instance layer ") + regular_layer_name));
env.debug_log.clear();
uint32_t count = 0;
env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
- ASSERT_EQ(0U, count);
- std::array<VkLayerProperties, 1> layer_props;
+ EXPECT_EQ(2U, count);
+ std::array<VkLayerProperties, 2> layer_props;
env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, layer_props.data());
- ASSERT_EQ(0U, count);
+ EXPECT_EQ(2U, count);
+ EXPECT_TRUE(check_permutation({regular_layer_name, lunarg_meta_layer_name}, layer_props));
}
{
@@ -803,16 +803,18 @@ TEST(OverrideMetaLayer, NewerComponentLayerInMetaLayer) {
inst.create_info.set_api_version(1, 2, 0);
inst.CheckCreate();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
- ASSERT_TRUE(
- env.debug_log.find("verify_meta_layer_component_layers: Meta-layer uses API version 1.1, but component layer 0 uses "
- "API version 1.2. Skipping this layer."));
+ // Meta layer should be disabled since its less than the apiVersion of the instance
+ EXPECT_TRUE(
+ env.debug_log.find("loader_add_implicit_layer: Disabling implicit layer VK_LAYER_LUNARG_override for using an old API "
+ "version 1.1 versus application requested 1.2"));
env.debug_log.clear();
uint32_t count = 0;
env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, nullptr);
- ASSERT_EQ(0U, count);
+ EXPECT_EQ(0U, count);
std::array<VkLayerProperties, 2> layer_props;
+ count = 2;
env.vulkan_functions.vkEnumerateDeviceLayerProperties(phys_dev, &count, layer_props.data());
- ASSERT_EQ(0U, count);
+ EXPECT_EQ(0U, count);
}
}