Add loader policy statements
authorMark Young <marky@lunarg.com>
Thu, 21 Oct 2021 16:01:42 +0000 (10:01 -0600)
committerMark Young <marky@lunarg.com>
Mon, 13 Dec 2021 18:05:15 +0000 (11:05 -0700)
Define expected behavior for a well-behaved loader, layers, and drivers.
This has been reviewed with other companies so that when issues arise,
it is easy to clearly communicate where one of the components has failed
to properly behave.

Add warnings/errors in the loader output when cases of policy that can
be detected are noticed.

docs/LoaderDriverInterface.md
docs/LoaderInterfaceArchitecture.md
docs/LoaderLayerInterface.md
loader/loader.c
loader/loader_common.h
loader/log.c
loader/trampoline.c

index 36186aefc6c46f04c29473386703ee9a324c8b03..5d916275da417ff868c56d99183e2f2d3ebf20fb 100644 (file)
@@ -52,6 +52,9 @@
     * [Loader Version 0 Interface Requirements](#loader-version-0-interface-requirements)
     * [Additional Interface Notes](#additional-interface-notes)
   * [Android Driver Negotiation](#android-driver-negotiation)
+* [Loader and Driver Policy](#loader-and-driver-policy)
+  * [Requirements of Well-Behaved Drivers](#requirements-of-well-behaved-drivers)
+  * [Requirements of a Well-Behaved Loader](#requirements-of-a-well-behaved-loader)
 
 
 ## Overview
@@ -1148,6 +1151,474 @@ The only difference is that the Android loader queries layer and extension
 information directly from the respective libraries and does not use the JSON
 manifest files used by the Windows, Linux and macOS loaders.
 
+
+## Loader and Driver Policy
+
+This section is intended to define proper behavior expected between the loader
+and drivers.
+Much of this section is additive to the Vulkan spec, and necessary for
+maintaining consistency across platforms.
+In fact, much of the language can be found throughout this document, but is
+summarized here for convenience.
+Additionally, there should be a way to identify bad or non-conformant behavior
+in adriver and remedy it as soon as possible.
+Therefore, a policy numbering system is provided to clearly identify each
+policy statement in a unique way.
+
+Finally, based on the goal of making the loader efficient and performant,
+some of these policy statements defining proper driver behavior may not
+be testable (and therefore aren't enforceable by the loader).
+However, that should not detract from the requirement in order to provide the
+best experience to end-users and developers.
+
+
+### Number Format
+
+Loader/Driver policy items start with the prefix `LDP_` (short for
+Loader/Driver Policy) which is followed by an identifier based on what
+component the policy is targeted against.
+In this case there are only two possible components:
+ - Drivers: which will have the string `DRIVER_` as part of the policy number.
+ - The Loader: which will have the string `LOADER_` as part of the policy
+   number.
+
+
+### Android Differences
+
+As stated before, the Android Loader is actually separate from the Khronos
+Loader.
+Because of this and other platform requirements, not all of these policy
+statements apply to Android.
+Each table also has a column titled "Applicable to Android?"
+which indicates which policy statements apply to drivers that are focused
+only on Android support.
+Further information on the Android loader can be found in the
+<a href="https://source.android.com/devices/graphics/implement-vulkan">
+Android Vulkan documentation</a>.
+
+
+### Requirements of Well-Behaved Drivers
+
+<table style="width:100%">
+  <tr>
+    <th>Requirement Number</th>
+    <th>Requirement Description</th>
+    <th>Result of Non-Compliance</th>
+    <th>Applicable to Android?</th>
+    <th>Enforceable by Loader?</th>
+    <th>Reference Section</th>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_1</b></small></td>
+    <td>A driver <b>must not</b> cause other drivers to fail, crash, or
+        otherwise misbehave.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td>No</td>
+    <td><small>N/A</small></td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_2</b></small></td>
+    <td>A driver <b>must not</b> crash if it detects that there are no supported
+        Vulkan Physical Devices (<i>VkPhysicalDevice</i>) on the system when a
+        call to that driver is made using any Vulkan instance of physical device
+        API.<br/>
+        This is because some devices can be hot-plugged.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td>No<br/>
+        The loader has no direct knowledge of what devices (virtual or physical)
+        may be supported by a given driver.</td>
+    <td><small>N/A</small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_3</b></small></td>
+    <td>A driver <b>must</b> be able to negotiate a supported version of the
+        loader/driver interface with the loader in accordance with the stated
+        negotiation process.
+    </td>
+    <td>The driver will not be loaded.</td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#loader-and-driver-interface-negotiation">
+        Interface Negotiation</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_4</b></small></td>
+    <td>A driver <b>must</b> have a valid JSON manifest file for the loader to
+        process that ends with the ".json" suffix.
+    </td>
+    <td>The driver will not be loaded.</td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#driver-manifest-file-format">Manifest File Format</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_5</b></small></td>
+    <td>A driver <b>must</b> pass conformance with the results submitted,
+        verified, and approved by Khronos before reporting a conformance version
+        through any mechanism provided by Vulkan (examples include inside the
+        <i>VkPhysicalDeviceVulkan12Properties</i> and the
+        <i>VkPhysicalDeviceDriverProperties</i> structs).<br/>
+        Otherwise, when such a structure containing a conformance version is
+        encountered, the driver <b>must</b> return a conformance version
+        of 0.0.0.0 to indicate it hasn't been so verified and approved.
+    </td>
+    <td>Yes</td>
+    <td>No</td>
+    <td>The loader and/or the application may make assumptions about the
+        capabilities of the driver resulting in undefined behavior
+        possibly including crashes or corruption.
+    </td>
+    <td><small>
+        <a href="https://github.com/KhronosGroup/VK-GL-CTS/blob/master/external/openglcts/README.md">
+        Vulkan CTS Documentation</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_6</b></small></td>
+    <td>A driver supporting loader/driver interface version 1 or newer <b>must
+        not</b> directly export standard Vulkan entry-points.
+        <br/>
+        Instead, it <b>must</b> export only the loader interface functions
+        required by the interface versions it does support (for example
+        <i>vk_icdGetInstanceProcAddr</i>). <br/>
+        This is because the dynamic linking on some platforms has been
+        problematic in the past and incorrectly links to exported functions from
+        the wrong dynamic library at times. <br/>
+        <b>NOTE:</b> This is actually true for all exports.
+        When in doubt, don't export any items from a driver that could cause
+        conflicts in other libraries.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes (except it always applies)</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#loader-and-driver-interface-negotiation">
+        Interface Negotiation</a></small>
+        and
+        <a href="#driver-vulkan-entry-point-discovery">
+        Vulkan Entry-point Discovery</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_7</b></small></td>
+    <td>If a driver desires to support Vulkan API 1.1 or newer, it <b>must</b>
+        expose support of Vulkan loader/driver interface 5 or newer.
+    </td>
+    <td>The driver will be used when it shouldn't be and will cause
+        undefined behavior possibly including crashes or corruption.
+    </td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#loader-version-5-interface-requirements">
+        Version 5 Interface Requirements</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_8</b></small></td>
+    <td>If a driver wishes to handle its own <i>VkSurfaceKHR</i> object
+        creation, it <b>must</b> implement loader/driver interface version 3 or
+        newer and support querying all the relevant surface functions via
+        <i>vk_icdGetInstanceProcAddr</i>.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#handling-khr-surface-objects-in-wsi-extensions">
+        Handling KHR Surface Objects</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_9</b></small></td>
+    <td>If a driver negotiation results in it using loader/driver interface
+        version 4 or earlier, the driver <b>must</b> verify that the Vulkan API
+        version passed into <i>vkCreateInstance</i> (through
+        <i>VkInstanceCreateInfo</i>’s <i>VkApplicationInfo</i>'s
+        <i>apiVersion</i>) is supported.
+        If the requested Vulkan API version can not be supported by the driver,
+        it <b>must</b> return <b>VK_ERROR_INCOMPATIBLE_DRIVER</b>. <br/>
+        This is not required if the interface version is 5 or newer because the
+        responsibility for this check then falls on the loader.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td>No</td>
+    <td><small>
+        <a href="#loader-version-5-interface-requirements">
+        Version 5 Interface Requirements</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_10</b></small></td>
+    <td>If a driver negotiation results in it using loader/driver interface
+        version 5 or newer, the driver <b>must</b> ignore the Vulkan API version
+        passed into <i>vkCreateInstance</i> (through
+        <i>VkInstanceCreateInfo</i>’s <i>VkApplicationInfo</i>'s
+        <i>apiVersion</i>).
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td>No</td>
+    <td><small>
+        <a href="#loader-version-5-interface-requirements">
+        Version 5 Interface Requirements</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_11</b></small></td>
+    <td>A driver <b>must</b> remove all Manifest files and references to those
+        files (i.e. Registry entries on Windows) when uninstalling.
+        <br/>
+        Similarly, on updating the driver files, the old files <b>must</b> be
+        all updated or removed.
+    </td>
+    <td>If an old file is left pointing to an incorrect library, it will
+        result in undefined behavior which may include crashes or corruption.
+    </td>
+    <td>No</td>
+    <td>No<br/>
+        The loader has no idea what driver files are new, old, or incorrect.
+        Any type of driver file verification would quickly become very complex
+        since it would require the loader to maintain an internal database
+        tracking badly behaving drivers based on the driver vendor, driver
+        version, targeted platform(s), and possibly other criteria.
+    </td>
+    <td><small>N/A</small></td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_DRIVER_12</b></small></td>
+    <td>To work properly with the public Khronos Loader, a driver
+        <b>must not</b> expose platform interface extensions without first
+        publishing them with Khronos.<br/>
+        Platforms under development may use modified versions of the Khronos
+        Loader until the design because stable and/or public.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes (specifically for Android extensions)</td>
+    <td>No</td>
+    <td><small>N/A</small></td>
+  </tr>
+</table>
+
+
+### Requirements of a Well-Behaved Loader
+
+<table style="width:100%">
+  <tr>
+    <th>Requirement Number</th>
+    <th>Requirement Description</th>
+    <th>Result of Non-Compliance</th>
+    <th>Applicable to Android?</th>
+    <th>Reference Section</th>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_1</b></small></td>
+    <td>A loader <b>must</b> return <b>VK_ERROR_INCOMPATIBLE_DRIVER</b> if it
+        fails to find and load a valid Vulkan driver on the system.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td><small>N/A</small></td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_2</b></small></td>
+    <td>A loader <b>must</b> attempt to load any driver's Manifest file it
+        discovers and determines is formatted in accordance with this document.
+        <br/>
+        The <b>only</b> exception is on platforms which determines driver
+        location and functionality through some other mechanism.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#driver-discovery">Driver Discovery</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_3</b></small></td>
+    <td>A loader <b>must</b> support a mechanism to load driver in one or more
+        non-standard locations.<br/>
+        This is to allow support for fully software drivers as well as
+        evaluating in-development ICDs. <br/>
+        The <b>only</b> exception to this rule is if the OS does not wish to
+        support this due to security policies.
+    </td>
+    <td>It will be more difficult to use a Vulkan loader by certain
+        tools and driver developers.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#using-pre-production-icds-or-software-drivers">
+        Pre-Production ICDs or SW</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_4</b></small></td>
+    <td>A loader <b>must not</b> load a Vulkan driver which defines an API
+        version that is incompatible with itself.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#driver-discovery">Driver Discovery</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_5</b></small></td>
+    <td>A loader <b>must</b> ignore any driver for which a compatible
+        loader/driver interface version can not be negotiated.
+    </td>
+    <td>The loader would load a driver improperly resulting in undefined
+        behavior possibly including crashes or corruption.
+    </td>
+    <td>No</td>
+    <td><small>
+        <a href="#loader-and-driver-interface-negotiation">
+        Interface Negotiation</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_6</b></small></td>
+    <td>If a driver negotiation results in it using loader/driver interface
+        version 5 or newer, a loader <b>must</b> verify that the Vulkan API
+        version passed into <i>vkCreateInstance</i> (through
+        <i>VkInstanceCreateInfo</i>’s <i>VkApplicationInfo</i>'s
+        <i>apiVersion</i>) is supported by at least one driver.
+        If the requested Vulkan API version can not be supported by any
+        driver, the loader <b>must</b> return
+        <b>VK_ERROR_INCOMPATIBLE_DRIVER</b>.<br/>
+        This is not required if the interface version is 4 or earlier because
+        the responsibility for this check then falls on the drivers.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#loader-version-5-interface-requirements">
+        Version 5 Interface Requirements</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_7</b></small></td>
+    <td>If there exist more than one driver on a system, and some of those
+        drivers support <i>only</i> Vulkan API version 1.0 while other drivers
+        support a newer Vulkan API version, then a loader <b>must</b> adjust
+        the <i>apiVersion</i> field of the <i>VkInstanceCreateInfo</i>’s
+        <i>VkApplicationInfo</i> to version 1.0 for all the drivers that are
+        only aware of Vulkan API version 1.0.<br/>
+        Otherwise, the drivers that support Vulkan API version 1.0 will
+        return <b>VK_ERROR_INCOMPATIBLE_DRIVER</b> during
+        <i>vkCreateInstance</i> since 1.0 drivers were not aware of future
+        versions.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#driver-api-version">Driver API Version</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_8</b></small></td>
+    <td>If more than one driver is present, and at least one driver <i>does not
+        support</i> instance-level functionality that other drivers support;
+        then a loader <b>must</b> support the instance-level functionality in
+        some fashion for the non-supporting drivers.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#loader-instance-extension-emulation-support">
+        Loader Instance Extension Emulation Support</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_9</b></small></td>
+    <td>A loader <b>must</b> filter out instance extensions from the
+        <i>VkInstanceCreateInfo</i> structure's <i>ppEnabledExtensionNames</i>
+        field that the driver does not support during a call to the driver's
+        <i>vkCreateInstance</i>.<br/>
+        This is because the application has no way of knowing which
+        drivers support which extensions.<br/>
+        This ties in directly with <i>LDP_LOADER_8</i> above.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#filtering-out-instance-extension-names">
+        Filtering Out Instance Extension Names</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_10</b></small></td>
+    <td>A loader <b>must</b> support creating <i>VkSurfaceKHR</i> handles
+        that <b>may</b> be shared by all underlying drivers.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#handling-khr-surface-objects-in-wsi-extensions">
+        Handling KHR Surface Objects</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_11</b></small></td>
+    <td>If a driver exposes the appropriate <i>VkSurfaceKHR</i>
+        creation/handling entry-points, a loader <b>must</b> support creating
+        the driver-specific surface object handle and provide it, and not the
+        shared <i>VkSurfaceKHR</i> handle, back to that driver when requested.
+        <br/>
+        Otherwise, a loader <b>must</b> provide the loader created
+        <i>VkSurfaceKHR</i> handle.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#handling-khr-surface-objects-in-wsi-extensions">
+        Handling KHR Surface Objects</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_12</b></small></td>
+    <td>A loader <b>must not</b> call any <i>vkEnumerate*ExtensionProperties</i>
+        entry-points in a driver if <i>pLayerName</i> is not <b>NULL</b>.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#additional-interface-notes">
+        Additional Interface Notes</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LDP_LOADER_13</b></small></td>
+    <td>A loader <b>must</b> not load from user-defined paths (including the
+        use of the <i>VK_ICD_FILENAMES</i> environment variable) when running
+        elevated (Administrator/Super-user) applications.<br/>
+        <b>This is for security reasons.</b>
+    </td>
+    <td>The behavior is undefined and may result in computer security lapses,
+        crashes or corruption.
+    </td>
+    <td>No</td>
+    <td><small>
+        <a href="#exception-for-administrator-and-super-user-mode">
+          Exception for Administrator and Super-User mode
+        </a></small>
+    </td>
+  </tr>
+</table>
+
 <br/>
 
 [Return to the top-level LoaderInterfaceArchitecture.md file.](LoaderInterfaceArchitecture.md)
index 278219847d593f887dde71bf6373b48e634aaf8d..f20a46ee89caeb7501136e3c46b2738af5143009 100644 (file)
@@ -29,6 +29,7 @@
   * [Layer Interface with the Loader](#layer-interface-with-the-loader)
   * [Driver Interface with the Loader](#driver-interface-with-the-loader)
 
+  * [Loader Policies](#loader-policies)
   * [Table of Debug Environment Variables](#table-of-debug-environment-variables)
   * [Glossary of Terms](#glossary-of-terms)
 
@@ -446,6 +447,27 @@ directory as this file.
 <br/>
 
 
+## Loader Policies
+
+Loader policies with regards to the loader interaction with drivers and layers
+ are now documented in the appropriate sections.
+The intention of these sections is to clearly define expected behavior of the
+loader with regards to its interactions with those components.
+This could be especially useful in cases where a new or specialized loader may
+be required that conforms to the behavior of the existing loader.
+Because of this, the primary focus of those sections is on expected behaviors
+for all relevant components to create a consistent experience across platforms.
+In the long-run, this could also be used as validation requirements for any
+existing Vulkan loaders.
+
+To review the particular policy sections, please refer to one or both of the
+sections listed below:
+ * [Loader And Driver Policy](LoaderDriverInterface.md#loader-and-driver-policy)
+ * [Loader And Layer Policy](LoaderLayerInterface.md#loader-and-layer-policy)
+<br/>
+<br/>
+
+
 ## Table of Debug Environment Variables
 
 The following are all the Debug Environment Variables available for use with the
@@ -744,7 +766,7 @@ discovery.
         These files contain specific information for either a
         <a href="LoaderLayerInterface.md#layer-manifest-file-format">Layer</a>
         or a
-        <a href="LoaderDriverInterface.md#icd-manifest-file-format">Driver</a>
+        <a href="LoaderDriverInterface.md#driver-manifest-file-format">Driver</a>
         and define necessary information such as where to find files and default
         settings.
     </td>
index feb37015af11cf3a4c3aa01c43ca3e99f6f462c0..bda906f7a60d62fed9ea2c4ed9f43d01eafcad50 100644 (file)
@@ -48,6 +48,9 @@
   * [Layer Interface Version 2](#layer-interface-api-version-2)
   * [Layer Interface Version 1](#layer-interface-api-version-1)
   * [Layer Interface Version 0](#layer-interface-api-version-0)
+* [Loader and Layer Interface Policy](#loader-and-layer-interface-policy)
+  * [Requirements of Well-Behaved Layers](#requirements-of-well-behaved-layers)
+  * [Requirements of a Well-Behaved Loader](#requirements-of-a-well-behaved-loader)
 
 
 ## Overview
@@ -1746,6 +1749,609 @@ They do not need to implement functions that they do not intercept.
 They are recommended not to export any functions.
 
 
+## Loader and Layer Interface Policy
+
+This section is intended to define proper behavior expected between the loader
+and layers.
+Much of this section is additive to the Vulkan spec, and necessary for
+maintaining consistency across platforms.
+In fact, much of the language can be found throughout this document, but is
+summarized here for convenience.
+Additionally, there should be a way to identify bad or non-conformant behavior
+in a layer and remedy it as soon as possible.
+Therefore, a policy numbering system is provided to clearly identify each
+policy statement in a unique way.
+
+Finally, based on the goal of making the loader efficient and performant,
+some of these policy statements defining proper layer behavior may not be
+testable (and therefore aren't enforceable by the loader).
+However, that should not detract from the requirement in order to provide the
+best experience to end-users and developers.
+
+
+### Number Format
+
+Loader/Layer policy items start with the prefix `LLP_` (short for
+Loader/Layer Policy) which is followed by an identifier based on what
+component the policy is targeted against.
+In this case there are only two possible components:
+ - Layers: which will have the string `LAYER_` as part of the policy number.
+ - The Loader: which will have the string `LOADER_` as part of the policy
+   number.
+
+
+### Android Differences
+
+As stated before, the Android Loader is actually separate from the Khronos
+Loader.
+Because of this and other platform requirements, not all of these policy
+statements apply to Android.
+Each table also has a column titled "Applicable to Android?"
+which indicates which policy statements apply to layers that are focused
+only on Android support.
+Further information on the Android loader can be found in the
+<a href="https://source.android.com/devices/graphics/implement-vulkan">
+Android Vulkan documentation</a>.
+
+
+### Requirements of Well-Behaved Layers
+
+<table style="width:100%">
+  <tr>
+    <th>Requirement Number</th>
+    <th>Requirement Description</th>
+    <th>Result of Non-Compliance</th>
+    <th>Applicable to Android?</th>
+    <th>Enforceable by Loader?</th>
+    <th>Reference Section</th>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_1</b></small></td>
+    <td>A layer, when inserted into an otherwise compliant Vulkan
+        environment, <b>must</b> still result in a compliant Vulkan environment
+        unless it intends to mimic non-compliant behavior (such as a device
+        simulation layer).
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td>No<br/>
+        It is not a simple task for the loader to find the cause of failure
+        in a layer chain.</td>
+    <td><small>
+        <a href="#layer-conventions-and-rules">Layer Conventions and Rules</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_2</b></small></td>
+    <td>A layer <b>must not</b> cause other layers or drivers to fail, crash, or
+        otherwise misbehave.<br/>
+        It <b>must not</b> make invalid calls to, or rely on undefined behaviors
+        of the layers or drivers below it.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td>No<br/>
+        It is not a simple task for the loader to find the cause of failure
+        in a layer chain.</td>
+    <td><small>
+        <a href="#layer-conventions-and-rules">Layer Conventions and Rules</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_3</b></small></td>
+    <td>Any new layer developed <b>should</b> adhere to the naming rules defined
+        in the "Layer Conventions and Rules" section which also correspond to
+        the naming rules defined in the Vulkan Style Guide section 3.4 on
+        "Version, Extension, and Layer Naming Conventions".
+    </td>
+    <td>Layer developers could produce conflicting names causing unexpected
+        behavior if more than one layer with the same name is available on a
+        user's platform.
+    </td>
+    <td>Yes</td>
+    <td>Yes<br/>
+        Can not immediately enforce since it will cause some shipping layers
+        to stop working.</td>
+    <td><small>
+        <a href="https://www.khronos.org/registry/vulkan/specs/1.2/styleguide.html#extensions-naming-conventions">
+            Vulkan Style Guide section 3.4</a> <br/>
+        <a href="#layer-conventions-and-rules">Layer Conventions and Rules</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_4</b></small></td>
+    <td>A layer <b>should</b> export the
+        <i>vkNegotiateLoaderLayerInterfaceVersion</i> entry-point to negotiate
+        an interface version.<br/>
+        A layer using interface 2 or newer <b>must</b> export this function.<br/>
+    </td>
+    <td>The layer will not be loaded.</td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#layer-version-negotiation">Layer Version Negotiation</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_5</b></small></td>
+    <td>A layer <b>must</b> be able to negotiate a supported version of the
+        loader/layer interface with the loader in accordance with the stated
+        negotiation process.
+    </td>
+    <td>The layer will not be loaded.</td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#loader-and-layer-interface-negotiation">
+        Interface Negotiation</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_6</b></small></td>
+    <td>A layer <b>must</b> have a valid JSON manifest file for the
+        loader to process that ends with the ".json" suffix.
+        It is recommended validating the layer manifest file against
+        <a href="https://github.com/LunarG/VulkanTools/blob/master/vkconfig_core/layers/layers_schema.json">
+        the layer schema</a> prior to publication.</br>
+        The <b>only</b> exception is on Android which determines layer
+        functionality through the introspection functions defined in
+        <a href="#layer-library-api-version-0">Layer Library API Version 0</a>
+        section and in the
+        <a href="#layer-manifest-file-format">Layer Manifest File Format</a>
+        table.
+    </td>
+    <td>The layer will not be loaded.</td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#layer-manifest-file-usage">Manifest File Usage</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_7</b></small></td>
+    <td>If a layer is a Meta-layer, each component layer in its manifest file
+        <b>must</b> be present on the system.
+    </td>
+    <td>The layer will not be loaded.</td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#meta-layers">Meta-Layers</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_8</b></small></td>
+    <td>If a layer is a Meta-layer, each component layer in its manifest file
+        <b>must</b> report the same or a newer Vulkan API major and minor
+        version than the meta-layer.
+    </td>
+    <td>The layer will not be loaded.</td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#meta-layers">Meta-Layers</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_9</b></small></td>
+    <td>A layer installed as an Implicit Layer <b>must</b> define a disable
+        environment variable so it can be disabled globally.
+    </td>
+    <td>The layer will not be loaded if it does not define the environment
+        variable.
+    </td>
+    <td>Yes</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#layer-manifest-file-format">Manifest File Format</a>, see
+        "disable_environment" variable</small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_10</b></small></td>
+    <td>If a layer wraps individual object handles, it <b>must</b> unwrap those
+        handles when passing the handles down the chain to the next layer.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    </td>
+    <td>Yes</td>
+    <td>No</td>
+    <td><small>
+      <a href="#cautions-about-wrapping">Cautions About Wrapping</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_11</b></small></td>
+    <td>Any layer shipped with a driver <b>must</b> be validated against
+        conformance with the corresponding driver.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td>No</td>
+    <td><small>
+        <a href="https://github.com/KhronosGroup/VK-GL-CTS/blob/master/external/openglcts/README.md">
+        Vulkan CTS Documentation</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_12</b></small></td>
+    <td> During <i>vkCreateInstance</i>, a layer <b>must</b> process the
+         <i>VkLayerInstanceCreateInfo</i> chain links appropriately.<br/>
+         This includes getting the next layer's <i>vkGetInstanceProcAddr</i>
+         function for building a dispatch table as well as updating the
+         <i>VkLayerInstanceCreateInfo</i> chain link to point to the next
+         structure in the chain for the next layer prior to calling down to the
+         next layer's <i>vkCreateInstance</i> function. <br/>
+         An example of such usage is shown in detail in the
+         <a href=#example-code-for-createinstance>Example Code for
+         CreateInstance</a> section.
+    </td>
+    <td>The behavior will result in crashes or corruption as any following
+        layers will access incorrect content.</td>
+    <td>Yes</td>
+    <td>No<br/>
+        With the current loader/layer design, it is difficult for the loader
+        to diagnose this without adding additional overhead that could impact
+        performance.<br/>
+        This is because the loader calls all layers at once and has no data on
+        the intermediate state of the <i>pNext</i> chain contents.
+        This could be done in the future, but requires re-designing the layer
+        initialization process.
+    </td>
+    <td><small>
+        <a href=""#layer-dispatch-initialization">
+           Layer Dispatch Initialization</a>
+        </small>
+    </td>
+  </tr>
+    <td><small><b>LLP_LAYER_13</b></small></td>
+    <td> During <i>vkCreateDevice</i>, a layer <b>must</b> process the
+         <i>VkLayerDeviceCreateInfo</i> chain links appropriately.<br/>
+         This includes updating the <i>VkLayerDeviceCreateInfo</i> chain link to
+         point to the next structure in the chain for the next layer prior to
+         calling down to the next layer's <i>vkCreateDevice</i> function. <br/>
+         An example of such usage is shown in detail in the
+         <a href="#example-code-for-createdevice">Example Code for
+         CreateDevice</a> section.
+    </td>
+    <td>The behavior will result in crashes or corruption as any following
+        layers will access incorrect content.</td>
+    <td>Yes</td>
+    <td>No<br/>
+        With the current loader/layer design, it is difficult for the loader
+        to diagnose this without adding additional overhead that could impact
+        performance.</td>
+    <td><small>
+        <a href="#layer-dispatch-initialization">
+           Layer Dispatch Initialization</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_14</b></small></td>
+    <td>A layer <b>should</b> use the application provided memory allocator
+        functions when they are provided so that applications can keep track of
+        allocated memory.
+    </td>
+    <td>The allocator functions may be provided for the purpose of limiting
+        or tracking the memory used by the Vulkan components.
+        Because of this, if a layer ignores these allocators, it may result in
+        undefined behavior possibly including crashes or corruption.
+    </td>
+    <td>Yes</td>
+    <td>No</td>
+    <td><small>
+        <a href="#layer-conventions-and-rules">Layer Conventions and Rules</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_15</b></small></td>
+    <td>A layer <b>must</b> enumerate only its own extension properties during a
+        call of <i>vkEnumerateInstanceExtensionProperties</i> when
+        <i>pLayerName</i> refers to itself.<br/>
+        Otherwise, it <b>must</b> return <i>VK_ERROR_LAYER_NOT_PRESENT</i>,
+        including when <i>pLayerName</i> is <b>NULL</b>.
+    </td>
+    <td>The loader could become confused on what support is present in a
+        specific layer which will result in undefined behavior possibly
+        including crashes or corruption.
+    </td>
+    <td>Yes</td>
+    <td>No</td>
+    <td><small>
+        <a href="#layer-conventions-and-rules">Layer Conventions and Rules</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_16</b></small></td>
+    <td>A layer <b>must</b> enumerate only its own extension properties during a
+        call of <i>vkEnumerateDeviceExtensionProperties</i> when
+        <i>pLayerName</i> refers to itself.<br/>
+        Otherwise, it <b>must</b> ignore the call other than passing it down
+        the standard call chain.
+    </td>
+    <td>The loader could become confused on what support is present in a
+        specific layer which will result in undefined behavior possibly
+        including crashes or corruption.
+    </td>
+    <td>Yes</td>
+    <td>No</td>
+    <td><small>
+        <a href="#layer-conventions-and-rules">Layer Conventions and Rules</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_17</b></small></td>
+    <td>A layer's <i>vkCreateInstance</i> <b>must not</b> generate an error for
+        unrecognized extension names as the extension could be implemented by
+        a lower layer or driver.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#layer-conventions-and-rules">Layer Conventions and Rules</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_18</b></small></td>
+    <td>A layer <b>must</b> return <b>NULL</b> from <i>vkGetInstanceProcAddr</i>
+        or <i>vkGetDeviceProcAddr</i> for entry-points that it does not support
+        or that have not been enabled properly (for example not enabling the
+        extension certain entry-points are associated with should result in
+        <i>vkGetInstanceProcAddr</i> returning <b>NULL</b> when requesting
+        them).
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td>No<br/>
+        With the current loader/layer design, it is difficult for the loader
+        to determine this without adding additional overhead that could impact
+        performance.</td>
+    <td><small>
+        <a href="#layer-conventions-and-rules">Layer Conventions and Rules</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_19</b></small></td>
+    <td>If a layer creates dispatchable objects, either because it is
+        wrapping objects or implementing an extension not supported by
+        the loader or underlying drivers, it <b>must</b> create the dispatch
+        table appropriately for all created dispatchable objects.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td>No</td>
+    <td><small>
+        <a href="#creating-new-dispatchable-objects">
+          Creating New Dispatchable Objects</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_20</b></small></td>
+    <td>A layer <b>must</b> remove all manifest files and references
+        to those files (i.e. Registry entries on Windows) when uninstalling.
+        <br/>
+        Similarly, on updating the layer files, the old files <b>must</b> be all
+        updated or removed.
+    </td>
+    <td>The loader ignores duplicate attempts to load the same manifest file,
+        but if an old file is left pointing to an incorrect library, it will
+        result in undefined behavior which may include crashes or corruption.
+    </td>
+    <td>No</td>
+    <td>No<br/>
+        The loader has no idea what layer files are new, old, or incorrect.
+        Any type of layer file verification would quickly become very complex
+        since it would require the loader to maintain an internal database
+        tracking badly behaving layers based on the layer name, version,
+        targeted platform(s), and possibly other criteria.
+    <td><small>N/A</small></td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LAYER_21</b></small></td>
+    <td>During <i>vkCreateInstance</i>, a layer <b>must not</b> modify the
+        <i>pInstance</i> pointer during prior to calling down to the lower
+        layers.<br/>
+        This is because the loader passes information in this pointer that is
+        necessary for the initialization code in the loader's terminator
+        function.<br/>
+        Instead, if the layer is overriding the <i>pInstance</i> pointer, it
+        <b>must</b> do so only after the call to the lower layers returns.
+    </td>
+    <td>The loader will likely crash.</td>
+    <td>No</td>
+    <td>Yes</td>
+    <td><small>N/A</small></td>
+  </tr>
+</table>
+
+
+### Requirements of a Well-Behaved Loader
+
+<table style="width:100%">
+  <tr>
+    <th>Requirement Number</th>
+    <th>Requirement Description</th>
+    <th>Result of Non-Compliance</th>
+    <th>Applicable to Android?</th>
+    <th>Reference Section</th>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_1</b></small></td>
+    <td>A loader <b>must</b> support Vulkan layers.</td>
+    <td>Users will not have access to critical parts of the Vulkan ecosystem
+        such as Validation Layers, GfxReconstruct, or RenderDoc.</td>
+    <td>Yes</td>
+    <td><small>N/A</small></td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_2</b></small></td>
+    <td>A loader <b>must</b> support a mechanism to load layers in one or
+        more non-standard locations.<br/>
+        This is to allow application/engine-specific layers as well as
+        evaluating in-development layers without global installation.
+    </td>
+    <td>It will be more difficult to use a Vulkan loader by certain
+        tools and driver developers.</td>
+    <td>No</td>
+    <td><small><a href="#layer-discovery">Layer Discovery</a></small></td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_3</b></small></td>
+    <td>A loader <b>must</b> filter out duplicate layer names in the various
+        enable lists, keeping only the first occurrence.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td><small><a href="#layer-discovery">Layer Discovery</a></small></td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_4</b></small></td>
+    <td>A loader <b>must not</b> load a Vulkan layer which defines an
+        API version that is incompatible with itself.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>Yes</td>
+    <td><small><a href="#layer-discovery">Layer Discovery</a></small></td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_5</b></small></td>
+    <td>A loader <b>must</b> ignore any layer for which a compatible interface
+        version can not be negotiated.
+    </td>
+    <td>The loader would load a layer improperly resulting in undefined behavior
+        which may include crashes or corruption.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#loader-and-layer-interface-negotiation">
+        Interface Negotiation</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_6</b></small></td>
+    <td>If a layer is implicit, and it has an enable environment variable,
+        then a loader <b>must not</b> consider the layer enabled unless that
+        enable environment variable is defined.<br/>
+        If an implicit layer does not have an enable environment variable,
+        it will be considered enabled by default.
+    </td>
+    <td>Some layers may be used when not intended.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#layer-manifest-file-format">Manifest File Format</a>, see
+        "enable_environment" variable</small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_7</b></small></td>
+    <td>If an implicit layer is enabled, but has been disabled by some other
+        mechanism (such as the defining of the layer's disable environment
+        variable or through the blacklisting mechanism of the Override Layer),
+        then a loader <b>must not</b> load that layer.
+    </td>
+    <td>Some layers may be used when not intended.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#layer-manifest-file-format">Manifest File Format</a>, see
+        "disable_environment" variable</small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_8</b></small></td>
+    <td>A loader <b>must</b> pass a linked list of initialization structures
+        to each layer via the <i>VkLayerInstanceCreateInfo</i> structure in the
+        <i>pNext</i> field of the <i>VkInstanceCreateInfo</i> structure.
+        This contains necessary information for setting up the instance call
+        chain including providing a function pointer to the next links
+        <i>vkGetInstanceProcAddr</i>.
+    </td>
+    <td>Layers will crash as they attempt to load invalid data.</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#layer-dispatch-initialization">
+           Layer Dispatch Initialization</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_9</b></small></td>
+    <td>A loader <b>must</b> pass a linked list of initialization structures
+        to each layer via the <i>VkLayerDeviceCreateInfo</i> structure in the
+        <i>pNext</i> field of the <i>VkDeviceCreateInfo</i> structure.
+        This contains necessary information for setting up the device call chain
+        including providing a function pointer to the next links
+        <i>vkGetDeviceProcAddr</i>.
+    <td>Layers will crash as they attempt to load invalid data.</td>
+    <td>Yes</td>
+    <td><small>
+        <a href="#layer-dispatch-initialization">
+           Layer Dispatch Initialization</a>
+        </small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_10</b></small></td>
+    <td>A loader <b>must</b> verify that all meta-layers contain valid
+        component layers that the loader can find on the system and that also
+        report the same Vulkan API version as the meta-layer itself before it
+        loads the meta-layer.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#meta-layers">Meta-Layers</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_11</b></small></td>
+    <td>If the override meta-layer is present, a loader <b>must</b> load it
+        and corresponding component layers after all other implicit layers have
+        been added to the call chain.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#override-meta-layer">Override Meta-Layer</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_12</b></small></td>
+    <td>If the override meta-layer is present and has a blacklist of layers to
+        remove, a loader <b>must</b> disable all layers listed in the blacklist.
+    </td>
+    <td>The behavior is undefined and may result in crashes or corruption.</td>
+    <td>No</td>
+    <td><small>
+        <a href="#override-meta-layer">Override Meta-Layer</a></small>
+    </td>
+  </tr>
+  <tr>
+    <td><small><b>LLP_LOADER_13</b></small></td>
+    <td>A loader <b>must</b> not load from user-defined paths (including the
+        use of the <i>VK_LAYER_PATH</i> environment variable) when running
+        elevated (Administrator/Super-user) applications.<br/>
+        <b>This is for security reasons.</b>
+    </td>
+    <td>The behavior is undefined and may result in computer security lapses,
+        crashes or corruption.
+    </td>
+    <td>No</td>
+    <td><small><a href="#layer-discovery">Layer Discovery</a></small></td>
+  </tr>
+</table>
+
 <br/>
 
 [Return to the top-level LoaderInterfaceArchitecture.md file.](LoaderInterfaceArchitecture.md)
index 3694ecae6081e7957cf9c3dab17ffad22e2fe3b5..3892aa305907fd963e049c41accba5df8eae7940 100644 (file)
@@ -978,6 +978,8 @@ 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_VERSION_MAJOR(prop->info.specVersion);
+    uint16_t meta_layer_api_minor_version = VK_VERSION_MINOR(prop->info.specVersion);
     for (uint32_t comp_layer = 0; comp_layer < prop->num_component_layers; comp_layer++) {
         bool found_comp = false;
         const struct loader_layer_properties *search_prop =
@@ -985,6 +987,17 @@ bool loader_add_meta_layer(const struct loader_instance *inst, const struct load
         if (search_prop != NULL) {
             found_comp = true;
 
+            uint16_t search_layer_api_major_version = VK_VERSION_MAJOR(search_prop->info.specVersion);
+            uint16_t search_layer_api_minor_version = VK_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_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);
+            }
+
             // If the component layer is itself an implicit layer, we need to do the implicit layer enable
             // checks
             if (0 == (search_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) {
@@ -1002,7 +1015,7 @@ bool loader_add_meta_layer(const struct loader_instance *inst, const struct load
         }
         if (!found_comp) {
             loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
-                       "loader_add_meta_layer: Failed to find layer name %s component layer %s to activate",
+                       "loader_add_meta_layer: Failed to find layer name %s component layer %s to activate (Policy #LLP_LAYER_7)",
                        search_prop->info.layerName, prop->component_layer_names[comp_layer]);
             found = false;
         }
@@ -1455,6 +1468,29 @@ 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_log(inst, VULKAN_LOADER_ERROR_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);
+    }
+    if (interface_vers >= 1) {
+        if ((loader_platform_get_proc_address(handle, "vkEnumerateInstanceExtensionProperties") != NULL) ||
+            (loader_platform_get_proc_address(handle, "vkEnumerateInstanceLayerProperties") != NULL) ||
+            (loader_platform_get_proc_address(handle, "vkEnumerateInstanceVersion") != NULL) ||
+            (loader_platform_get_proc_address(handle, "vkGetInstanceProcAddr") != NULL) ||
+            (loader_platform_get_proc_address(handle, "vkCreateInstance") != NULL) ||
+            (loader_platform_get_proc_address(handle, "vkGetDeviceProcAddr") != NULL) ||
+            (loader_platform_get_proc_address(handle, "vkCreateDevice") != NULL)) {
+            loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
+                       "loader_scanned_icd_add: Driver %s says it supports interface version %u but still exports core "
+                       "entrypoints (Policy #LDP_DRIVER_6)",
+                       filename, interface_vers);
+        }
+    }
+
     new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]);
     new_scanned_icd->handle = handle;
     new_scanned_icd->api_version = api_version;
@@ -2230,6 +2266,10 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
 
     strncpy(props->info.layerName, name, sizeof(props->info.layerName));
     props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
+    if (0 != strncmp(props->info.layerName, "VK_LAYER_", 9)) {
+        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.implementationVersion = atoi(implementation_version);
     strncpy((char *)props->info.description, description, sizeof(props->info.description));
@@ -2237,7 +2277,8 @@ static VkResult loader_read_layer_json(const struct loader_instance *inst, struc
     if (is_implicit) {
         if (!disable_environment || !disable_environment->child) {
             loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
-                       "Didn't find required layer child value disable_environment in manifest JSON file, skipping this layer");
+                       "Didn't find required layer child value disable_environment in manifest JSON file, skipping this layer "
+                       "(Policy #LLP_LAYER_9)");
             goto out;
         }
         strncpy(props->disable_env_var.name, disable_environment->child->string, sizeof(props->disable_env_var.name));
@@ -5376,6 +5417,17 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI
     bool one_icd_successful = false;
 
     struct loader_instance *ptr_instance = (struct loader_instance *)*pInstance;
+    if (NULL == ptr_instance) {
+        loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT, 0,
+                   "terminator_CreateInstance: Loader instance pointer null encountered.  Possibly set by active layer. (Policy "
+                   "#LLP_LAYER_21)");
+    } else if (LOADER_MAGIC_NUMBER != ptr_instance->magic) {
+        loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT, 0,
+                   "terminator_CreateInstance: Instance pointer (%p) has invalid MAGIC value 0x%08x. Instance value possibly "
+                   "corrupted by active layer (Policy #LLP_LAYER_21).  ",
+                   ptr_instance->magic);
+    }
+
     memcpy(&icd_create_info, pCreateInfo, sizeof(icd_create_info));
 
     icd_create_info.enabledLayerCount = 0;
@@ -5511,6 +5563,31 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI
             continue;
         }
 
+        if (ptr_instance->icd_tramp_list.scanned_list[i].interface_version < 3 &&
+            (
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+                NULL != icd_term->dispatch.CreateXlibSurfaceKHR ||
+#endif  // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+                NULL != icd_term->dispatch.CreateXcbSurfaceKHR ||
+#endif  // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+                NULL != icd_term->dispatch.CreateWaylandSurfaceKHR ||
+#endif  // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+                NULL != icd_term->dispatch.CreateAndroidSurfaceKHR ||
+#endif  // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+                NULL != icd_term->dispatch.CreateWin32SurfaceKHR ||
+#endif  // VK_USE_PLATFORM_WIN32_KHR
+                NULL != icd_term->dispatch.DestroySurfaceKHR)) {
+            loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT, 0,
+                       "terminator_CreateInstance: Driver %s supports interface version %u but still exposes VkSurfacekHR"
+                       " create/destroy entrypoints (Policy #LDP_DRIVER_8)",
+                       ptr_instance->icd_tramp_list.scanned_list[i].lib_name,
+                       ptr_instance->icd_tramp_list.scanned_list[i].interface_version);
+        }
+
         // If we made it this far, at least one ICD was successful
         one_icd_successful = true;
     }
@@ -5523,7 +5600,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI
 
 out:
 
+    ptr_instance->create_terminator_invalid_extension = false;
+
     if (VK_SUCCESS != res) {
+        if (VK_ERROR_EXTENSION_NOT_PRESENT == res) {
+            ptr_instance->create_terminator_invalid_extension = true;
+        }
+
         while (NULL != ptr_instance->icd_terms) {
             icd_term = ptr_instance->icd_terms;
             ptr_instance->icd_terms = icd_term->next;
index 72772653aa2b922f8ef47b950cc14aca9b424a91..14921a7447c54d619a751af0ef1ae7cd6c2c2299 100644 (file)
@@ -332,6 +332,7 @@ struct loader_instance {
 #endif
     bool wsi_display_enabled;
     bool wsi_display_props2_enabled;
+    bool create_terminator_invalid_extension;
 };
 
 // VkPhysicalDevice requires special treatment by loader.  Firstly, terminator
index 7305a3af630d698823abb8cb898cd6f892361d59..5dd84c81c0fc42520d53c8b8d22897a6247f0b1d 100644 (file)
@@ -227,4 +227,4 @@ void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t ms
 
     fputs(cmd_line_msg, stderr);
     fputc('\n', stderr);
-}
\ No newline at end of file
+}
index edb1ea59c7ef0a466ab45e1ee388a79012e1160b..25cb407f7134674ab94181e6db62fbea9a7fef45 100644 (file)
@@ -578,7 +578,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
     created_instance = (VkInstance)ptr_instance;
     res = loader_create_instance_chain(&ici, pAllocator, ptr_instance, &created_instance);
 
-    if (res == VK_SUCCESS) {
+    if (VK_SUCCESS == res) {
         // Check for enabled extensions here to setup the loader structures so the loader knows what extensions
         // it needs to worry about.
         // We do it in the terminator and again above the layers here since we may think different extensions
@@ -596,6 +596,9 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCr
         // GetInstanceProcAddr functions to return valid extension functions
         // if enabled.
         loader_activate_instance_layer_extensions(ptr_instance, created_instance);
+    } else if (VK_ERROR_EXTENSION_NOT_PRESENT == res && !ptr_instance->create_terminator_invalid_extension) {
+        loader_log(ptr_instance, VULKAN_LOADER_ERROR_BIT, 0,
+                   "vkCreateInstance: Layer returning invalid extension error not triggered by ICD/Loader (Policy #LLP_LAYER_17).");
     }
 
 out: