From 845b2c663757a9030ae108dc76602cc57495f1cc Mon Sep 17 00:00:00 2001 From: Mark Young Date: Tue, 18 Apr 2017 19:52:18 -0600 Subject: loader: Add validation for apiVersion Add a check to determine if the API version being requested can be handled by the loader. If it can't, then we return incompatible driver. If we can, we continue along our merry way. An addendum is that we also bumped the Loader/ICD interface version. This was requested by Nvidia so that the ICDs know that we pay attention to the version in the loader. If they don't see the new Loader/ICD interface version, they will handle the failing on all non-1.0 API requests. Change-Id: Icb7dd45e754c9f6a6c8186198333bacc68077b93 --- loader/LoaderAndLayerInterface.md | 31 +++++++++++++++++++++++++++++-- loader/loader.c | 14 ++++++-------- loader/loader.h | 3 --- loader/trampoline.c | 16 ++++++++++++++++ 4 files changed, 51 insertions(+), 13 deletions(-) (limited to 'loader') diff --git a/loader/LoaderAndLayerInterface.md b/loader/LoaderAndLayerInterface.md index fa8c1d0e..cf3f4c60 100644 --- a/loader/LoaderAndLayerInterface.md +++ b/loader/LoaderAndLayerInterface.md @@ -398,6 +398,7 @@ extension or core device entry-points. ##### ABI Versioning + The Vulkan loader library will be distributed in various ways including Vulkan SDKs, OS package distributions and Independent Hardware Vendor (IHV) driver packages. These details are beyond the scope of this document. However, the name @@ -1821,6 +1822,7 @@ ICD to properly hand-shake. * [Windows and Linux ICD Negotiation](#windows-and-linux-icd-negotiation) * [Version Negotiation Between Loader and ICDs](#version-negotiation-between-loader-and-icds) * [Interfacing With Legacy ICDs or Loader](#interfacing-with-legacy-icds-or-loader) + * [Loader Version 5 Interface Requirements](#loader-version-5-interface-requirements) * [Loader Version 4 Interface Requirements](#loader-version-4-interface-requirements) * [Loader Version 3 Interface Requirements](#loader-version-3-interface-requirements) * [Loader Version 2 Interface Requirements](#loader-version-2-interface-requirements) @@ -2333,6 +2335,31 @@ is a legacy loader supporting version 0 or 1. If the loader calls the loader only supports version 0. +##### Loader Version 5 Interface Requirements + +Version 5 of the loader/ICD interface has no changes to the actual interface. +If the loader requests interface version 5 or greater, it is simply +an indication to ICDs that the loader is now evaluating if the API Version info +passed into vkCreateInstance is a valid version for the loader. If it is not, +the loader will catch this during vkCreateInstance and fail with a +VK_ERROR_INCOMPATIBLE_DRIVER error. + +On the other hand, if version 5 or newer is not requested by the loader, then it +indicates to the ICD that the loader is ignorant of the API version being +requested. Because of this, it falls on the ICD to validate that the API +Version is not greater than major = 1 and minor = 0. If it is, then the ICD +should automatically fail with a VK_ERROR_INCOMPATIBLE_DRIVER error since the +loader is a 1.0 loader, and is unaware of the version. + +Here is a table of the expected behaviors: + +| Loader Supports I/f Version | ICD Supports I/f Version | Result | +| :---: |:---:|------------------------| +| <= 4 | <= 4 | 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. | +| <= 4 | >= 5 | 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. | +| >= 5 | <= 4 | Loader will fail with `VK_ERROR_INCOMPATIBLE_DRIVER` if it can't handle the apiVersion. ICD may pass for all apiVersions, but since it's 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. | +| >= 5 | >= 5 | 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. | + ##### Loader Version 4 Interface Requirements The major change to version 4 of the loader/ICD interface is the support of @@ -2425,7 +2452,7 @@ Loader. These are referenced throughout the text, but collected here for ease of discovery. | Environment Variable | Behavior | Example Format | -|----------------|---------------------|----------------------| +|:---:|---------------------|----------------------| | VK_ICD_FILENAMES | Force the loader to use the specific ICD JSON files. The value should contain a list of delimited full path listings to ICD JSON Manifest files. **NOTE:** If you fail to use the global path to a JSON file, you may encounter issues. | `export VK_ICD_FILENAMES=\intel.json:\amd.json`

`set VK_ICD_FILENAMES=\nvidia.json;\mesa.json` | | VK_INSTANCE_LAYERS | Force the loader to add the given layers to the list of Enabled layers normally passed into `vkCreateInstance`. These layers are added first, and the loader will remove any duplicate layers that appear in both this list as well as that passed into `ppEnabledLayerNames`. | `export VK_INSTANCE_LAYERS=:`

`set VK_INSTANCE_LAYERS=;` | | VK_LAYER_PATH | Override the loader's standard Layer library search folders and use the provided delimited folders to search for layer Manifest files. | `export VK_LAYER_PATH=:`

`set VK_LAYER_PATH=;` | @@ -2435,7 +2462,7 @@ of discovery. ## Glossary of Terms | Field Name | Field Value | -|----------------|--------------------| +|:---:|--------------------| | Android Loader | The loader designed to work primarily for the Android OS. This is generated from a different code-base than the desktop loader. But, in all important aspects, should be functionally equivalent. | | Desktop Loader | The loader designed to work on both Windows and Linux. This is generated from a different [code-base](#https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers) than the Android loader. But in all important aspects, should be functionally equivalent. | | Core Function | A function that is already part of the Vulkan core specification and not an extension. For example, vkCreateDevice(). | diff --git a/loader/loader.c b/loader/loader.c index 05183b3f..a3f4a598 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -716,8 +716,8 @@ static VkResult loader_add_instance_extensions(const struct loader_instance *ins bool ext_unsupported = wsi_unsupported_instance_extension(&ext_props[i]); if (!ext_unsupported) { - (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_MAJOR(ext_props[i].specVersion), - VK_MINOR(ext_props[i].specVersion), VK_PATCH(ext_props[i].specVersion)); + (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion), + VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion)); loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Instance Extension: %s (%s) version %s", ext_props[i].extensionName, lib_name, spec_version); @@ -751,9 +751,8 @@ static VkResult loader_init_device_extensions(const struct loader_instance *inst for (i = 0; i < count; i++) { char spec_version[64]; - - (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_MAJOR(ext_props[i].specVersion), - VK_MINOR(ext_props[i].specVersion), VK_PATCH(ext_props[i].specVersion)); + (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion), + VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion)); loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Device Extension: %s (%s) version %s", ext_props[i].extensionName, phys_dev_term->this_icd_term->scanned_icd->lib_name, spec_version); res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); @@ -786,9 +785,8 @@ VkResult loader_add_device_extensions(const struct loader_instance *inst, } for (i = 0; i < count; i++) { char spec_version[64]; - - (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_MAJOR(ext_props[i].specVersion), - VK_MINOR(ext_props[i].specVersion), VK_PATCH(ext_props[i].specVersion)); + (void)snprintf(spec_version, sizeof(spec_version), "%d.%d.%d", VK_VERSION_MAJOR(ext_props[i].specVersion), + VK_VERSION_MINOR(ext_props[i].specVersion), VK_VERSION_PATCH(ext_props[i].specVersion)); loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Device Extension: %s (%s) version %s", ext_props[i].extensionName, lib_name, spec_version); res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); diff --git a/loader/loader.h b/loader/loader.h index 2c65923d..3a80657d 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -48,9 +48,6 @@ #define DEBUG_DISABLE_APP_ALLOCATORS 0 #define MAX_STRING_SIZE 1024 -#define VK_MAJOR(version) (version >> 22) -#define VK_MINOR(version) ((version >> 12) & 0x3ff) -#define VK_PATCH(version) (version & 0xfff) // This is defined in vk_layer.h, but if there's problems we need to create the define // here. diff --git a/loader/trampoline.c b/loader/trampoline.c index b03ebda6..1d6105d9 100644 --- a/loader/trampoline.c +++ b/loader/trampoline.c @@ -227,6 +227,22 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr loader_platform_thread_once(&once_init, loader_initialize); + // Fail if the requested Vulkan apiVersion is > 1.0 since the loader only supports 1.0. + // Having pCreateInfo == NULL, pCreateInfo->pApplication == NULL, or + // pCreateInfo->pApplicationInfo->apiVersion == 0 all indicate that the application is + // only requesting a 1.0 instance, which this loader will always support. + uint32_t loader_major_version = 1; + uint32_t loader_minor_version = 0; + if (NULL != pCreateInfo && NULL != pCreateInfo->pApplicationInfo && + pCreateInfo->pApplicationInfo->apiVersion >= VK_MAKE_VERSION(loader_major_version, loader_minor_version + 1, 0)) { + loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "vkCreateInstance: Called with invalid API version %d.%d. Loader only supports %d.%d", + VK_VERSION_MAJOR(pCreateInfo->pApplicationInfo->apiVersion), + VK_VERSION_MINOR(pCreateInfo->pApplicationInfo->apiVersion), loader_major_version, loader_minor_version); + res = VK_ERROR_INCOMPATIBLE_DRIVER; + goto out; + } + #if (DEBUG_DISABLE_APP_ALLOCATORS == 1) { #else -- cgit v1.2.3