summaryrefslogtreecommitdiff
path: root/loader
diff options
context:
space:
mode:
authorMark Young <marky@lunarg.com>2017-01-19 21:10:49 -0700
committerLenny Komow <lenny@lunarg.com>2017-01-24 14:07:22 -0700
commitb5f087aec8b42faee128c5c3dd1cb11b662d85aa (patch)
tree77d57ceca8898265742478a10b051c5505c1bd5e /loader
parent75a442807593315f53092f56527702a7174ee1c2 (diff)
loader: Update the loader to 1.0.39
Add new extensions for 1.0.39. Also, updated layers to include minimal set of functionality for 1.0.39 extensions. Extensions include: - VK_KHR_get_physical_device_properties2 - VK_KHR_shader_draw_parameters - VK_EXT_direct_mode_display - VK_EXT_display_surface_counter - VK_EXT_display_control Also, redo the LoaderAndLayerIf document. Change-Id: I10412086da7a798afe832a3892e18f606259b5af
Diffstat (limited to 'loader')
-rw-r--r--loader/CMakeLists.txt5
-rw-r--r--loader/LoaderAndLayerInterface.md3219
-rw-r--r--loader/chain_skipping_layers.pngbin17793 -> 0 bytes
-rw-r--r--loader/debug_report.c10
-rw-r--r--loader/dev_ext_trampoline.c2507
-rw-r--r--loader/extensions.c502
-rw-r--r--loader/extensions.h66
-rw-r--r--loader/get_proc_addr.pngbin17411 -> 0 bytes
-rw-r--r--loader/gpa_helper.h35
-rw-r--r--loader/images/function_device_chain.pngbin0 -> 115414 bytes
-rw-r--r--loader/images/function_device_chain_white.pngbin0 -> 120563 bytes
-rw-r--r--loader/images/function_instance_chain.pngbin0 -> 133822 bytes
-rw-r--r--loader/images/function_instance_chain_white.pngbin0 -> 141522 bytes
-rw-r--r--loader/images/high_level_loader.pngbin0 -> 92519 bytes
-rw-r--r--loader/images/high_level_loader_white.pngbin0 -> 95728 bytes
-rw-r--r--loader/images/loader_device_chain_app.pngbin0 -> 35095 bytes
-rw-r--r--loader/images/loader_device_chain_app_white.pngbin0 -> 35776 bytes
-rw-r--r--loader/images/loader_device_chain_loader.pngbin0 -> 38797 bytes
-rw-r--r--loader/images/loader_device_chain_loader_white.pngbin0 -> 39680 bytes
-rw-r--r--loader/images/loader_instance_chain.pngbin0 -> 49202 bytes
-rw-r--r--loader/images/loader_instance_chain_white.pngbin0 -> 50324 bytes
-rw-r--r--loader/images/loader_layer_order.pngbin0 -> 57064 bytes
-rw-r--r--loader/images/loader_layer_order_white.pngbin0 -> 59335 bytes
-rw-r--r--loader/instance_call_chain.pngbin18868 -> 0 bytes
-rw-r--r--loader/loader.c1032
-rw-r--r--loader/loader.h105
-rwxr-xr-xloader/loader.rc8
-rw-r--r--loader/phys_dev_ext.c828
-rw-r--r--loader/table_ops.h197
-rw-r--r--loader/trampoline.c26
-rw-r--r--loader/vulkan-1.def6
-rw-r--r--loader/wsi.c91
-rw-r--r--loader/wsi.h5
33 files changed, 4981 insertions, 3661 deletions
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt
index 800e80b3..ba3abad3 100644
--- a/loader/CMakeLists.txt
+++ b/loader/CMakeLists.txt
@@ -13,7 +13,7 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
endif()
if (BUILD_WSI_XLIB_SUPPORT)
- add_definitions(-DVK_USE_PLATFORM_XLIB_KHR)
+ add_definitions(-DVK_USE_PLATFORM_XLIB_KHR -DVK_USE_PLATFORM_XLIB_XRANDR_EXT)
endif()
if (BUILD_WSI_WAYLAND_SUPPORT)
@@ -61,6 +61,7 @@ set(NORMAL_LOADER_SRCS
set (OPT_LOADER_SRCS
dev_ext_trampoline.c
+ phys_dev_ext.c
)
set (LOADER_SRCS ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
@@ -110,7 +111,7 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpointer-arith")
add_library(${API_LOWERCASE} SHARED ${LOADER_SRCS})
- set_target_properties(${API_LOWERCASE} PROPERTIES SOVERSION "1" VERSION "1.0.38")
+ set_target_properties(${API_LOWERCASE} PROPERTIES SOVERSION "1" VERSION "1.0.39")
target_link_libraries(${API_LOWERCASE} -ldl -lpthread -lm)
install(TARGETS ${API_LOWERCASE} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
diff --git a/loader/LoaderAndLayerInterface.md b/loader/LoaderAndLayerInterface.md
index c3492d34..9891b29d 100644
--- a/loader/LoaderAndLayerInterface.md
+++ b/loader/LoaderAndLayerInterface.md
@@ -1,153 +1,381 @@
-# Vulkan Loader Specification and Architecture Overview
+# Architecture of the Vulkan Loader Interfaces
+
+## Table of Contents
+ * [Overview](#overview)
+ * [Who Should Read This Document](#who-should-read-this-document)
+ * [The Loader](#the-loader)
+ * [Layers](#layers)
+ * [Installable Client Drivers](#installable-client-drivers)
+ * [Instance Versus Device](#instance-versus-device)
+ * [Dispatch Tables and Call Chains](#dispatch-tables-and-call-chains)
+
+ * [Application Interface to the Loader](#application-interface-to-the-loader)
+ * [Interfacing with Vulkan Functions](#interfacing-with-vulkan-functions)
+ * [Application Layer Usage](#application-layer-usage)
+ * [Application Usage of Extensions](#application-usage-of-extensions)
+
+ * [Loader and Layer Interface](#loader-and-layer-interface)
+ * [Layer Discovery](#layer-discovery)
+ * [Layer Version Negotiation](#layer-version-negotiation)
+ * [Layer Call Chains and Distributed Dispatch](#layer-call-chains-and-distributed-dispatch)
+ * [Layer Unknown Physical Device Extensions](#layer-unknown-physical-device-extensions)
+ * [Layer Intercept Requirements](#layer-intercept-requirements)
+ * [Distributed Dispatching Requirements](#distributed-dispatching-requirements)
+ * [Layer Conventions and Rules](#layer-conventions-and-rules)
+ * [Layer Dispatch Initialization](#layer-dispatch-initialization)
+ * [Example Code for CreateInstance](#example-code-for-createinstance)
+ * [Example Code for CreateDevice](#example-code-for-createdevice)
+ * [Special Considerations](#special-considerations)
+ * [Layer Manifest File Format](#layer-manifest-file-format)
+ * [Layer Library Versions](#layer-library-versions)
+
+ * [Vulkan Installable Client Driver interface with the loader](#vulkan-installable-client-driver-interface-with-the-loader)
+ * [ICD Discovery](#icd-discovery)
+ * [ICD Manifest File Format](#icd-manifest-file-format)
+ * [ICD Vulkan Entry-Point Discovery](#icd-vulkan-entry-point-discovery)
+ * [ICD Unknown Physical Device Extensions](#icd-unknown-physical-device-extensions)
+ * [ICD Dispatchable Object Creation](#icd-dispatchable-object-creation)
+ * [Handling KHR Surface Objects in WSI Extensions](#handling-khr-surface-objects-in-wsi-extensions)
+ * [Loader and ICD Interface Negotiation](#loader-and-icd-interface-negotiation)
+ * [Glossary of Terms](#glossary-of-terms)
+
+## Overview
+
+Vulkan is a layered architecture, made up of the following elements:
+ * The Vulkan Application
+ * [The Vulkan Loader](#the-loader)
+ * [Vulkan Layers](#layers)
+ * [Installable Client Drivers (ICDs)](#installable-client-drivers)
+
+![High Level View of Loader](./images/high_level_loader.png)
+
+The general concepts in this document are applicable to the loaders available
+for Windows, Linux and Android based systems.
+
+
+#### Who Should Read This Document
+
+While this document is primarily targeted at developers of Vulkan applications,
+drivers and layers, the information contained in it could be useful to anyone
+wanting a better understanding of the Vulkan runtime.
+
+
+#### The Loader
+
+As you can see, the application sits on one end, and interfaces directly to the
+loader. The loader itself can contain some number of [layers](#layers), which
+provide special functionality an application may wish to take advantage of.
+Finally, on the other end of the loader from the application are the ICDs, which
+control the Vulkan-capable hardware. An important point to remember is that
+Vulkan-capable hardware can be graphics-based, compute-based, or both.
-<br/>
+The loader is responsible for working with the various layers as well as
+supporting multiple GPUs and their drivers. Any Vulkan function may
+wind up calling into a diverse set of modules: loader, layers, and ICDs.
+The loader is critical to managing the proper dispatching of Vulkan
+functions to the appropriate set of layers and ICDs. The Vulkan object
+model allows the loader to insert layers into a call chain so that the layers
+can process Vulkan functions prior to the ICD being called.
-## Goals of this document ##
+This document is intended to provide an overview of the necessary interfaces
+between each of these.
-Specify necessary functions and expected behavior of interface between the
-loader library and ICDs and layers for Windows, Linux and Android based
-systems. Also describe the application visible behaviors of the loader.
-<br/>
+##### Goals of the Loader
+
+The loader was designed with the following goals in mind.
+ 1. Support one or more Vulkan-capable ICD on a user's computer system without
+them interfering with one another.
+ 2. Support Vulkan Layers which are optional modules that can be enabled by an
+application, developer, or standard system settings.
+ 3. Impact the overall performance of a Vulkan application in the lowest
+possible fashion.
+
+
+#### Layers
+
+Layers are optional components that augment the Vulkan system. They can
+intercept, evaluate, and modify existing Vulkan functions on their way from the
+application down to the hardware. Layers are implemented as libraries that can
+be enabled in different ways (including by application request) and are loaded
+during CreateInstance. Each layer can choose to hook (intercept) any Vulkan
+functions which in turn can be ignored or augmented. A layer does not need to
+intercept all Vulkan functions. It may choose to intercept all known functions,
+or, it may choose to intercept only one function.
-## Audience ##
+Some examples of features that layers may expose include:
+ * Validating API usage
+ * Adding the ability to perform Vulkan API tracing and debugging
+ * Overlay additional content on the applications surfaces
-This document is primarily targeted at Vulkan application, driver and layer developers.
-However, it can also be used by any developer interested in understanding more about
-how the Vulkan loader and layers interact.
+Because layers are optionally, you may choose to enable layers for debugging
+your application, but then disable any layer usage when you release your
+product.
-<br/>
+#### Installable Client Drivers
-## Loader goals ##
+Vulkan allows multiple Installable Client Drivers (ICDs) each supporting one
+or more devices (represented by a Vulkan `VkPhysicalDevice` object) to be used
+collectively. The loader is responsible for discovering available Vulkan ICDs on
+the system. Given a list of available ICDs, the loader can enumerate all the
+physical devices available for an application and return this information to
+the application.
-- Support multiple ICDs (Installable Client Drivers) to co-exist on a system
-without interfering with each other.
-- Support optional modules (layers) that can be enabled by an application,
-developer or the system and have no impact when not enabled.
+#### Instance Versus Device
-- Negligible performance cost for an application calling through the loader
-to an ICD entry point.
+There is an important concept which you will see brought up repeatedly
+throughout this document. Many functions, extensions, and other things in
+Vulkan are separated into two main groups:
+ * Instance-related Objects
+ * Device-related Objects
-<br/>
-## Architectural overview of layers and loader ##
+##### Instance-related Objects
-Vulkan is a layered architecture placing the Application on one end, the
-ICDs on the other, and the loader and some number of layers in between.
+A Vulkan Instance is a high-level construct used to provide Vulkan system-level
+information, or functionality. Vulkan objects associated directly with an
+instance are:
+ * `VkInstance`
+ * `VkPhysicalDevice`
-Layers are implemented as libraries that can be enabled in different ways
-(including by application request) and loaded during CreateInstance. Each
-layer can chooses to hook (intercept) any Vulkan commands which in turn
-can be ignored, augmented, or simply passed along. A layer may also
-expose functionality not available in the loader or any ICD. Some examples
-of this include: the ability to perform Vulkan API tracing and debugging,
-validate API usage, or overlay additional content on the applications surfaces.
+An Instance function is any Vulkan function which takes as its first parameter
+either an object from the Instance list, or nothing at all. Some Vulkan
+Instance functions are:
+ * `vkEnumerateInstanceExtensionProperties`
+ * `vkEnumeratePhysicalDevices`
+ * `vkCreateInstance`
+ * `vkDestroyInstance`
-The loader is responsible for working with the various layers as well as
-supporting multiple GPUs and their drivers. Any Vulkan command may
-wind up calling into a diverse set of modules: loader, layers, and ICDs.
-The loader is critical to managing the proper dispatching of Vulkan
-commands to the appropriate set of layers and ICDs. The Vulkan object
-model allows the loader to insert layers into a call chain so that the layers
-can process Vulkan commands prior to the ICD being called.
+You query Vulkan Instance functions using `vkGetInstanceProcAddr`.
+`vkGetInstanceProcAddr` can be used to query either device or instance entry-
+points in addition to all core entry-points. The returned function pointer is
+valid for this Instance and any object created under this Instance (including
+all `VkDevice` objects).
+
+Similarly, an Instance extension is a set of Vulkan Instance functions extending
+the Vulkan language. These will be discussed in more detail later.
+
+
+##### Device-related Objects
+
+A Vulkan Device, on the other-hand, is a logical identifier used to associate
+functions with a particular physical device on a user's system. Vulkan
+constructs associated directly with a device include:
+ * `VkDevice`
+ * `VkQueue`
+ * `VkCommandBuffer`
+ * Any dispatchable object that is a child of a one of the above.
+
+A Device function is any Vulkan function which takes any Device Object as its
+first parameter. Some Vulkan Device functions are:
+ * `vkQueueSubmit`
+ * `vkBeginCommandBuffer`
+ * `vkCreateEvent`
+
+You can query Vulkan Device functions using either `vkGetInstanceProcAddr` or
+`vkGetDeviceProcAddr`. If you choose to use `vkGetInstanceProcAddr`, it will
+have an additional level built into the call chain, which will reduce
+performance slightly. However, the function pointer returned can be used for
+any device created later, as long as it is associated with the same Vulkan
+Instance. If, instead you use `vkGetDeviceProcAddr`, the call chain will be more
+optimized to the specific device, but it will **only** work for the device used
+to query the function function pointer. Also, unlike `vkGetInstanceProcAddr`,
+`vkGetDeviceProcAddr` can only be used on core Vulkan Device functions, or
+Device extension functions.
+
+The best solution is to query Instance extension functions using
+`vkGetInstanceProcAddr`, and to query Device extension functions using
+`vkGetDeviceProcAddr`. See
+[Best Application Performance Setup](#best-application-performance-setup) for
+more information on this.
+
+As with Instance extensions, a Device extension is a set of Vulkan Device
+functions extending the Vulkan language. You can read more about these later in
+the document.
+
+
+#### Dispatch Tables and Call Chains
Vulkan uses an object model to control the scope of a particular action /
operation. The object to be acted on is always the first parameter of a Vulkan
call and is a dispatchable object (see Vulkan specification section 2.3 Object
Model). Under the covers, the dispatchable object handle is a pointer to a
structure, which in turn, contains a pointer to a dispatch table maintained by
-the loader. This dispatch table contains pointers to the Vulkan functions appropriate to
-that object.
+the loader. This dispatch table contains pointers to the Vulkan functions
+appropriate to that object.
There are two types of dispatch tables the loader maintains:
-- **Instance Dispatch Table**
- - Contains any function that takes a VkInstance or VkPhysicalDevice as their first parameter
- - vkEnumeratePhysicalDevices
- - vkDestroyInstance
- - vkCreateInstance
- - ...
-- **Device Dispatch Table**
- - Contains any function that takes a VkDevice, VkQueue or VkCommandBuffer as their first parameter
-
-These instance and device dispatch tables are constructed when the application
-calls vkCreateInstance and vkCreateDevice. At that time the application and/or
-system can specify optional layers to be included. The loader will initialize
-the specified layers to create a call chain for each Vulkan function and each
-entry of the dispatch table will point to the first element of that chain.
-Thus, the loader builds an instance call chain for each VkInstance that is
-created and a device call chain for each VkDevice that is created.
+ - Instance Dispatch Table
+ - Created in the loader during the call to `vkCreateInstance`
+ - Device Dispatch Table
+ - Created in the loader during the call to `vkCreateDevice`
-For example, the diagram below represents what happens in the call chain for
-vkCreateInstance. After initializing the chain, the loader will call into the
-first layer's vkCreateInstance which will call the next finally terminating in
-the loader again where this function calls every ICD's vkCreateInstance and
-saves the results. This allows every enabled layer for this chain to set up
-what it needs based on the VkInstanceCreateInfo structure from the application.
-![Instance call chain](instance_call_chain.png)
+At that time the application and/or system can specify optional layers to be
+included. The loader will initialize the specified layers to create a call
+chain for each Vulkan function and each entry of the dispatch table will point
+to the first element of that chain. Thus, the loader builds an instance call
+chain for each `VkInstance` that is created and a device call chain for each
+`VkDevice` that is created.
-This also highlights some of the complexity the loader must manage when using
-instance chains. As shown here, the loader must aggregate information from
-multiple devices when they are present. This means that the loader has to know
-about instance level extensions to aggregate them correctly.
+When an application calls a Vulkan function, this typically will first hit a
+*trampoline* function in the loader. These *trampoline* functions are small,
+simple functions that jump to the appropriate dispatch table entry for the
+object they are given. Additionally, for functions in the instance call chain,
+the loader has an additional function, called a *terminator*, which is called
+after all enabled layers to marshall the appropriate information to all
+available ICDs.
-Device chains are created at vkCreateDevice and are generally simpler because
-they deal with only a single device and the ICD can always be the terminator of
-the chain. The below diagram also illustrates how layers (either device or
-instance) can skip intercepting any given Vulkan entry point.
-![Chain skipping layers](chain_skipping_layers.png)
-<br/>
+##### Instance Call Chain Example
-## Application interface to loader ##
+For example, the diagram below represents what happens in the call chain for
+`vkCreateInstance`. After initializing the chain, the loader will call into the
+first layer's `vkCreateInstance` which will call the next finally terminating in
+the loader again where this function calls every ICD's `vkCreateInstance` and
+saves the results. This allows every enabled layer for this chain to set up
+what it needs based on the `VkInstanceCreateInfo` structure from the
+application.
-In this section we'll discuss how an application interacts with the loader.
+![Instance Call Chain](./images/loader_instance_chain.png)
-- Linking to loader library for core and WSI extension symbols.
+This also highlights some of the complexity the loader must manage when using
+instance call chains. As shown here, the loader's *terminator* must aggregate
+information to and from multiple ICDs when they are present. This implies that
+the loader has to be aware of any instance-level extensions which work on a
+`VkInstance` to aggregate them correctly.
-- Dynamic Vulkan command lookup & application dispatch table.
-- Loader library filenames for linking to different Vulkan ABI versions.
+##### Device Call Chain Example
-- Layers
+Device call chains are created at `vkCreateDevice` and are generally simpler
+because they deal with only a single device and the ICD can always be the
+*terminator* of the chain.
-- Extensions
+![Loader Device Call Chain](./images/loader_device_chain_loader.png)
-- vkGetInstanceProcAddr, vkGetDeviceProcAddr
+<br/>
+<br/>
+
+## Application Interface to the Loader
+
+In this section we'll discuss how an application interacts with the loader,
+including:
+ * [Interfacing with Vulkan Functions](#interfacing-with-vulkan-functions)
+ * [Vulkan Direct Exports](#vulkan-direct-exports)
+ * [Indirectly Linking to the Loader](#indirectly-linking-to-the-loader)
+ * [Best Application Performance Setup](#best-application-performance-setup)
+ * [ABI Versioning](#abi-versioning)
+ * [Application Layer Usage](#application-layer-usage)
+ * [Implicit vs Explicit Layers](#implicit-vs-explicit-layers)
+ * [Forcing Layer Source Folders](#forcing-layer-source-folders)
+ * [Forcing Layers to be Enabled](#forcing-layers-to-be-enabled)
+ * [Overall Layer Ordering](#overall-layer-ordering)
+ * [Application Usage of Extensions](#application-usage-of-extensions)
+ * [Instance and Device Extensions](#instance-and-device-extensions)
+ * [WSI Extensions](#wsi-extensions)
+ * [Unknown Extensions](#unknown-extensions)
+
+
+#### Interfacing with Vulkan Functions
+There are several ways you can interface with Vulkan functions through the
+loader.
+
+
+##### Vulkan Direct Exports
The loader library on Windows, Linux and Android will export all core Vulkan
and all appropriate Window System Interface (WSI) extensions. This is done to
make it simpler to get started with Vulkan development. When an application
links directly to the loader library in this way, the Vulkan calls are simple
-trampoline functions that jump to the appropriate dispatch table entry for the
+*trampoline* functions that jump to the appropriate dispatch table entry for the
object they are given.
+
+##### Indirectly Linking to the Loader
Applications are not required to link directly to the loader library, instead
they can use the appropriate platform specific dynamic symbol lookup on the
loader library to initialize the application's own dispatch table. This allows
-an application to fail gracefully if the loader cannot be found, and it
+an application to fail gracefully if the loader cannot be found. It also
provides the fastest mechanism for the application to call Vulkan functions. An
application will only need to query (via system calls such as dlsym()) the
-address of vkGetInstanceProcAddr from the loader library. Using
-vkGetInstanceProcAddr the application can then discover the address of all
-instance and global functions and extensions, such as vkCreateInstance,
-vkEnumerateInstanceExtensionProperties and vkEnumerateInstanceLayerProperties
-in a platform independent way.
+address of `vkGetInstanceProcAddr` from the loader library. Using
+`vkGetInstanceProcAddr` the application can then discover the address of all
+functions and extensions available, such as `vkCreateInstance`,
+`vkEnumerateInstanceExtensionProperties` and
+`vkEnumerateInstanceLayerProperties` in a platform-independent way.
+
+
+##### Best Application Performance Setup
+
+If you desire the best performance possible, you should setup your own
+dispatch table so that all your Instance functions are queried using
+`vkGetInstanceProcAddr` and all your Device functions are queried using
+`vkGetDeviceProcAddr`.
+
+*Why should you do this?*
+
+The answer comes in how the call chain of Instance functions are implemented
+versus the call chain of a Device functions. Remember, a [Vulkan Instance is a
+high-level construct used to provide Vulkan system-level information](#instance-
+related-objects). Because of this, Instance functions need to be broadcasted to
+every available ICD on the system. The following diagram shows an approximate
+view of an Instance call chain with 3 enabled layers:
+
+![Instance Call Chain](./images/loader_instance_chain.png)
+
+This is also how a Vulkan Device function call chain looks if you query it
+using `vkGetInstanceProcAddr`. On the otherhand, a Device
+function doesn't need to worry about the broadcast becuase it knows specifically
+which associated ICD and which associated Physical Device the call should
+terminate at. Because of this, the loader doesn't need to get involved between
+any enabled layers and the ICD. Thus, if you used a loader-exported Vulkan
+Device function, the call chain in the same scenario as above would look like:
+
+![Loader Device Call Chain](./images/loader_device_chain_loader.png)
+
+An even better solution would be for an application to perform a
+`vkGetDeviceProcAddr` call on all Device functions. This further optimizes the
+call chain by removing the loader all-together under most scenarios:
+
+![Application Device Call Chain](./images/loader_device_chain_app.png)
+
+Also, notice if no layers are enabled, your application function pointer would
+point **directly to the ICD**. If called enough, those fewer calls can add up
+to performance savings.
+
+**NOTE:** There are some Device functions which still require the loader to
+intercept them with a *trampoline* and *terminator*. There are very few of
+these, but they are typically functions which the loader wraps with its own
+data. In those cases, even the Device call chain will continue to look like the
+Instance call chain. One example of a Device function requiring a *terminator*
+is `vkCreateSwapchainKHR`. For that function, the loader needs to potentially
+convert the KHR_surface object into an ICD-specific KHR_surface object prior to
+passing down the rest of the function's information to the ICD.
+
+Remember:
+ * `vkGetInstanceProcAddr` can be used to query
+either device or instance entry-points in addition to all core entry-points.
+ * `vkGetDeviceProcAddr` can only be used to query for device
+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 IHV driver packages. These details are
-beyond the scope of this document. However, the name and versioning of the
-Vulkan loader library is specified so an app can link to the correct Vulkan ABI
-library version. Vulkan versioning is such that ABI backwards compatibility is
-guaranteed for all versions with the same major number (e.g. 1.0 and 1.1). On
-Windows, the loader library encodes the ABI version in its name such that
-multiple ABI incompatible versions of the loader can peacefully coexist on a
-given system. The Vulkan loader library file name is "vulkan-<ABI
-version>.dll". For example, for Vulkan version 1.X on Windows the library
-filename is vulkan-1.dll. And this library file can typically be found in the
-windows/system32 directory (on 64-bit Windows installs, the 32-bit version of
-the loader with the same name can be found in the windows/sysWOW64 directory).
+SDKs, OS package distributions and Independent Hardware Vendor (IHV) driver
+packages. These details are beyond the scope of this document. However, the name
+and versioning of the Vulkan loader library is specified so an app can link to
+the correct Vulkan ABI library version. Vulkan versioning is such that ABI
+backwards compatibility is guaranteed for all versions with the same major
+number (e.g. 1.0 and 1.1). On Windows, the loader library encodes the ABI
+version in its name such that multiple ABI incompatible versions of the loader
+can peacefully coexist on a given system. The Vulkan loader library file name is
+"vulkan-<ABI version>.dll". For example, for Vulkan version 1.X on Windows the
+library filename is vulkan-1.dll. And this library file can typically be found
+in the windows/system32 directory (on 64-bit Windows installs, the 32-bit
+version of the loader with the same name can be found in the windows/sysWOW64
+directory).
For Linux, shared libraries are versioned based on a suffix. Thus, the ABI
number is not encoded in the base of the library filename as on Windows. On
@@ -155,70 +383,99 @@ Linux an application wanting to link to the latest Vulkan ABI version would
just link to the name vulkan (libvulkan.so). A specific Vulkan ABI version can
also be linked to by applications (e.g. libvulkan.so.1).
-#### Layer Usage
-Applications desiring Vulkan functionality beyond what the core API offers may
-use various layers or extensions. A layer cannot introduce new Vulkan API
-entry-points not exposed in Vulkan.h, but may offer extensions that do. A
-common use of layers is for API validation which can be enabled by loading the
-layer during application development, but not loading the layer for application
-release. This eliminates the overhead of validating the application's
-usage of the API, something that wasn't available on some previous graphics
-APIs.
-
-Layers discovered by the loader are reported to the application via
-vkEnumerateInstanceLayerProperties. Layers are enabled at vkCreateInstance
-and are active for all Vulkan commands using the given VkInstance and any
-of it's child objects. For example, the ppEnabledLayerNames array in the
-VkInstanceCreateInfo structure is used by the application to list the layer
-names to be enabled at vkCreateInstance. At vkCreateInstance and
-vkCreateDevice, the loader will construct call chains that include the application
-specified (enabled) layers. Order is important in the
-ppEnabledLayerNames array; array element 0 is the topmost (closest to the
-application) layer inserted in the chain and the last array element is closest
-to the driver.
-
-**NOTE**: vkCreateDevice originally was able to select layers in a
-similar manner to vkCreateInstance. This lead to the concept of "instance
-layers" and "device layers". It was decided by Khronos to deprecate the
-"device layer" functionality and only consider "instance layers".
-Therefore, vkCreateDevice will use the layers specified at vkCreateInstance.
-Additionally, vkEnumerateDeviceLayerProperties has been deprecated.
-
-Developers may want to enable layers that are not enabled by the given
-application they are using. On Linux and Windows, the environment variable
-"VK\_INSTANCE\_LAYERS" can be used to enable
-additional layers which are not specified (enabled) by the application at
-vkCreateInstance. VK\_INSTANCE\_LAYERS is a colon
-(Linux)/semi-colon (Windows) separated list of layer names to enable. Order is
-relevant with the first layer in the list being the topmost layer (closest to
-the application) and the last layer in the list being the bottommost layer
-(closest to the driver).
+#### Application Layer Usage
-Application specified layers and user specified layers (via environment
-variables) are aggregated and duplicates removed by the loader when enabling
-layers. Layers specified via environment variable are topmost (closest to the
-application) while layers specified by the application are bottommost.
-
-An example of using these environment variables to activate the validation
-layer VK\_LAYER\_LUNARG\_parameter\_validation on Windows or Linux is as follows:
+Applications desiring Vulkan functionality beyond what the core API offers may
+use various layers or extensions. A layer cannot introduce new Vulkan core API
+entry-points to an application that are not exposed in Vulkan.h. However,
+layers may offer extensions that introduce new Vulkan commands that can be
+queried through the extension interface.
+
+A common use of layers is for API validation which can be enabled by
+loading the layer during application development, but not loading the layer
+for application release. This eliminates the overhead of validating the
+application's usage of the API, something that wasn't available on some previous
+graphics APIs.
+
+To find out what layers are available to your application, use
+`vkEnumerateInstanceLayerProperties`. This will report all layers
+that have been discovered by the loader. The loader looks in various locations
+to find layers on the system. For more information see the
+[Layer discovery](#layer-discovery) section below.
+
+To enable a layer, or layers, simply pass the name of the layers you wish to
+enable in the `ppEnabledLayerNames` field of the `VkInstanceCreateInfo` during
+a call to `vkCreateInstance`. Once done, the layers you have enabled will be
+active for all Vulkan functions using the created `VkInstance`, and any of
+its child objects.
+
+**NOTE:** Layer ordering is important in several cases since some layers
+interact with each other. Be careful when enabling layers as this may be
+the case. See the [Overall Layer Ordering](#overall-layer-ordering) section
+for more information.
+
+The following code section shows how you would go about enabling the
+VK_LAYER_LUNARG_standard_validation layer.
```
-> $ export VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_parameter_validation
+ char *instance_validation_layers[] = {
+ "VK_LAYER_LUNARG_standard_validation"
+ };
+ const VkApplicationInfo app = {
+ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ .pNext = NULL,
+ .pApplicationName = "TEST_APP",
+ .applicationVersion = 0,
+ .pEngineName = "TEST_ENGINE",
+ .engineVersion = 0,
+ .apiVersion = VK_API_VERSION_1_0,
+ };
+ VkInstanceCreateInfo inst_info = {
+ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ .pNext = NULL,
+ .pApplicationInfo = &app,
+ .enabledLayerCount = 1,
+ .ppEnabledLayerNames = (const char *const *)instance_validation_layers,
+ .enabledExtensionCount = 0,
+ .ppEnabledExtensionNames = NULL,
+ };
+ err = vkCreateInstance(&inst_info, NULL, &demo->inst);
```
-#### Implicit vs Explicit Layers
+At `vkCreateInstance` and `vkCreateDevice`, the loader constructs call chains
+that include the application specified (enabled) layers. Order is important in
+the `ppEnabledLayerNames` array; array element 0 is the topmost (closest to the
+application) layer inserted in the chain and the last array element is closest
+to the driver. See the [Overall Layer Ordering](#overall-layer-ordering)
+section for more information on layer ordering.
+
+**NOTE:** *Device Layers Are Now Deprecated*
+> `vkCreateDevice` originally was able to select layers in a similar manner to
+`vkCreateInstance`. This lead to the concept of "instance
+> layers" and "device layers". It was decided by Khronos to deprecate the
+> "device layer" functionality and only consider "instance layers".
+> Therefore, `vkCreateDevice` will use the layers specified at
+`vkCreateInstance`.
+> Because of this, the following items have been deprecated:
+> * `VkDeviceCreateInfo` fields:
+> * `ppEnabledLayerNames`
+> * `enabledLayerCount`
+> * The `vkEnumerateDeviceLayerProperties` function
+
+
+##### Implicit vs Explicit Layers
+
+Explicit layers are layers which are enabled by an application (e.g. with the
+vkCreateInstance function), or by an environment variable (as mentioned
+previously).
-Some platforms, including Linux and Windows, support layers which are enabled
-automatically by the loader rather than explicitly by the application (or via
-environment variable). Explicit layers are those layers enabled by the
-application (or environment variable) by providing the layer name. Implicit
-layers are those layers enabled by the loader automatically. Any implicit
-layers the loader discovers on the system in the appropriate location will be
-enabled (subject to environment variable overrides described later). Discovery
-of properly installed implicit and explicit layers is described later.
-Explicitly enabling a layer that is implicitly enabled has no additional
-effect: the layer will still be enabled implicitly by the loader.
+Implicit layers are those which are enabled by their existence. For example,
+certain application environments (e.g. Steam or an automotive infotainment
+system) may have layers which they always want enabled for all applications
+that they start. Other implicit layers may be for all applications started on a
+given system (e.g. layers that overlay frames-per-second). Implicit layers are
+enabled automatically, whereas explicit layers must be enabled explicitly.
Implicit layers have an additional requirement over explicit layers in that they
require being able to be disabled by an environmental variable. This is due
@@ -228,645 +485,982 @@ environment variable so the users can deterministicly enable the functionality.
On Desktop platforms (Windows and Linux), these enable/disable settings are
defined in the layer's JSON file.
-Extensions are optional functionality provided by a layer, the loader or an
-ICD. Extensions can modify the behavior of the Vulkan API and need to be
-specified and registered with Khronos.
-
-#### Instance/Device Extensions
-
-Instance extensions can be discovered via
-vkEnumerateInstanceExtensionProperties. Device extensions can be discovered via
-vkEnumerateDeviceExtensionProperties. The loader discovers and aggregates all
-extensions from layers (both explicit and implicit), ICDs and the loader before
-reporting them to the application in vkEnumerate\*ExtensionProperties. The
-pLayerName parameter in these functions is used to select either a single layer
-or the Vulkan platform implementation. If pLayerName is NULL, extensions from
-Vulkan implementation components (including loader, implicit layers, and ICDs)
-are enumerated. If pLayerName is equal to a discovered layer module name then
-any extensions from that layer (which may be implicit or explicit) are
-enumerated. Duplicate extensions (e.g. an implicit layer and ICD might report
-support for the same extension) are eliminated by the loader. For duplicates, the
-ICD version is reported and the layer version is culled. Extensions must
-be enabled (in vkCreateInstance or vkCreateDevice) before they can be used.
-
-Extension command entry points should be queried via vkGetInstanceProcAddr or
-vkGetDeviceProcAddr. vkGetDeviceProcAddr can only be used to query for device
-extension or core device entry points. Device entry points include any command
-that uses a VkDevice as the first parameter or a dispatchable object that is a
-child of a VkDevice (currently this includes VkQueue and VkCommandBuffer).
-vkGetInstanceProcAddr can be used to query either device or instance extension
-entry points in addition to all core entry points.
-
-VkGetDeviceProcAddr is particularly interesting because it will provide the
-most efficient way to call into the ICD. For example, the diagram below shows
-what could happen if the application were to use vkGetDeviceProcAddr for the
-function "vkGetDeviceQueue" and "vkDestroyDevice" but not "vkAllocateMemory".
-The resulting function pointer (fpGetDeviceQueue) would be the ICD's entry
-point if the loader and any enabled layers do not need to see that call. Even
-if an enabled layer intercepts the call (e.g. vkDestroyDevice) the loader
-trampoline code is skipped for function pointers obtained via
-vkGetDeviceProcAddr. This also means that function pointers obtained via
-vkGetDeviceProcAddr will only work with the specific VkDevice it was created
-for, using it with another device has undefined results. For extensions,
-Get\*ProcAddr will often be the only way to access extension API features.
-
-![Get*ProcAddr efficiency](get_proc_addr.png)
+Discovery of system-installed implicit and explicit layers is described later in
+the [Layer Discovery Section](#layer-discovery). For now, simply know that what
+distinguishes a layer as implicit or explicit is dependent on the Operating
+system, as shown in the table below.
-##### WSI Extensions
-
-Khronos approved WSI extensions are available and provide Windows System Integration
-support for various execution environments. It is important to understand that some WSI
-extensions are valid for all targets, but others are particular to a given execution
-environment (and loader). This desktop loader (currently targeting Windows and Linux)
-only enables those WSI extensions that are appropriate to the current environment.
-For the most part, the selection is done in the loader using compile-time preprocessor
-flags. All versions of the desktop loader currently expose at least the following WSI
-extension support:
-- VK_KHR_surface
-- VK_KHR_swapchain
-- VK_KHR_display
+| Operating System | Implicit Layer Identification |
+|----------------|--------------------|
+| Windows | Implicit Layers are located in a different Windows registry location than Explicit Layers. |
+| Linux | Implicit Layers are located in a different directory location than Explicit Layers. |
+| Android | There is **No Support For Implicit Layers** on Android. |
-In addition, each of the following OS targets for the loader support target-specific extensions:
-- **Windows** : VK_KHR_win32_surface
-- **Linux (default)** : VK_KHR_xcb_surface and VK_KHR_xlib_surface
-- **Linux (Wayland build)** : VK_KHR_wayland_surface
-- **Linux (Mir build)** : VK_KHR_mir_surface
-**NOTE:** Wayland and Mir targets are not fully supported at this time and should be considered
-alpha quality.
+##### Forcing Layer Source Folders
-It is important to understand that while the loader may support the various entry-points
-for these extensions, there is a hand-shake required to actually use them:
-* At least one physical device must support the extension(s)
-* The application must select such a physical device
-* The application must request the extension(s) be enabled while creating the instance or logical device (This depends on whether or not the given extension works with an instance or a device).
-* The instance and/or logical device creation must succeed.
+Developers may need to use special, pre-production layers, without modifying the
+system-installed layers. You can direct the loader to look for layers in a
+specific folder by defining the "VK\_LAYER\_PATH" environment variable. This
+will override the mechanism used for finding system-installed layers. Because
+layers of interest may exist in several disinct folders on on a system, this
+environment variable can containis several paths seperated by the operating
+specific path separator. On Windows, each separate folder should be separated
+in the list using a semi-colon. On Linux, each folder name should be separated
+using a colon.
-Only then can you expect to properly use a WSI extension in your Vulkan program.
+If "VK\_LAYER\_PATH" exists, **only** the folders listed in it will be scanned
+for layers. Each directory listed should be the full pathname of a folder
+containing layer manifest files.
-##### New Extensions
-With the ability to expand Vulkan so easily, extensions will be created that the loader knows
-nothing about. If the extension is a device extension, the loader will pass the unknown
-entry-point down the device call chain ending with the appropriate ICD entry-points.
-However, if the extension is an instance extension, the loader will fail to load it.
+##### Forcing Layers to be Enabled on Windows and Linux
-*But why doesn't the loader support unknown instance extensions?*
-<br/>
-Let's look again at the Instance call chain:
-![Instance call chain](instance_call_chain.png)
+Developers may want to enable layers that are not enabled by the given
+application they are using. On Linux and Windows, the environment variable
+"VK\_INSTANCE\_LAYERS" can be used to enable additional layers which are
+not specified (enabled) by the application at `vkCreateInstance`.
+"VK\_INSTANCE\_LAYERS" is a colon (Linux)/semi-colon (Windows) separated
+list of layer names to enable. Order is relevant with the first layer in the
+list being the top-most layer (closest to the application) and the last
+layer in the list being the bottom-most layer (closest to the driver).
+See the [Overall Layer Ordering](#overall-layer-ordering) section
+for more information.
-Notice that for a normal instance function call, the loader has to handle passing along the
-function call to the available ICDs. If the loader has no idea of the parameters or return
-value of the instance call, it can't properly pass information along to the ICDs.
-There may be ways to do this, which will be explored in the future. However, for now, this
-loader does not support any unknown instance extensions.
+Application specified layers and user specified layers (via environment
+variables) are aggregated and duplicates removed by the loader when enabling
+layers. Layers specified via environment variable are top-most (closest to the
+application) while layers specified by the application are bottommost.
-Because the device call-chain does not pass through the loader terminator, this is not
-a problem for device extensions. Instead, device extensions terminate directly in the
-ICD they are associated with.
+An example of using these environment variables to activate the validation
+layer `VK_LAYER_LUNARG_parameter_validation` on Windows or Linux is as follows:
-*Is this a big problem?*
-<br/>
-No! Most extension functionality only affects a device and not an instance or a physical
-device. Thus, the overwhelming majority of extensions will be device extensions rather than
-instance extensions.
+```
+> $ export VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_parameter_validation
+```
-## Vulkan Installable Client Driver interface with the loader ##
+##### Overall Layer Ordering
-### ICD discovery
+The overall ordering of all layers by the loader based on the above looks
+as follows:
-Vulkan allows multiple drivers each with one or more devices (represented by a
-Vulkan VkPhysicalDevice object) to be used collectively. The loader is
-responsible for discovering available Vulkan ICDs on the system. Given a list
-of available ICDs, the loader can enumerate all the physical devices available
-for an application and return this information to the application. The process
-in which the loader discovers the available Installable Client Drivers (ICDs)
-on a system is platform dependent. Windows, Linux and Android ICD discovery
-details are listed below.
+![Loader Layer Ordering](./images/loader_layer_order.png)
-#### Windows
+Ordering may also be important internal to the list of Explicit Layers.
+Some layers may be dependent on other behavior being implemented before
+or after the loader calls it. For example: the VK_LAYER_LUNARG_core_validation
+layer expects the VK_LAYER_LUNARG_parameter_validation to be called first.
+This is because the VK_LAYER_LUNARG_parameter_validation will filter out any
+invalid `NULL` pointer calls prior to the rest of the validation checking
+done by VK_LAYER_LUNARG_core_validation. If not done properly, you may see
+crashes in the VK_LAYER_LUNARG_core_validation layer that would otherwise be
+avoided.
-##### Properly-Installed ICDs
-In order to find properly-installed ICDs, the Vulkan loader will scan the
-values in the following Windows registry key:
+#### Application Usage of Extensions
-HKEY\_LOCAL\_MACHINE\\SOFTWARE\\Khronos\\Vulkan\\Drivers
+Extensions are optional functionality provided by a layer, the loader or an
+ICD. Extensions can modify the behavior of the Vulkan API and need to be
+specified and registered with Khronos. These extensions can be created
+by an Independent Hardware Vendor (IHV) to expose new hardware functionality,
+or by a layer writer to expose some internal feature, or by the loader to
+improve functional behavior. Information about various extensions can be
+found in the Vulkan Spec, and vulkan.h header file.
-On 64-bit Windows, when a 32-bit application is triggered, the loader
-will scan for 32-bit drivers in a separate area of the registry:
-HKEY\_LOCAL\_MACHINE\\SOFTWARE\\WOW6432Node\\Khronos\\Vulkan\\Drivers
+##### Instance and Device Extensions
-For each value in this key which has DWORD data set to 0, the loader opens the
-JSON format text information file (a.k.a. "manifest file") specified by the
-name of the value. Each name must be a full pathname to the text manifest file.
-The Vulkan loader will open each manifest file to obtain the name or pathname
-of an ICD shared library (".dll") file. For example:
+As hinted at in the [Instance Versus Device](#instance-versus-device) section,
+there are really two types of extensions:
+ * Instance Extensions
+ * Device Extensions
- ```
- {
- "file_format_version": "1.0.0",
- "ICD": {
- "library_path": "path to ICD library",
- "api_version": "1.0.5"
- }
- }
- ```
+An Instance extension is an extension which modifies existing behavior or
+implements new behavior on instance-level objects, like a `VkInstance` or
+a `VkPhysicalDevice`. A Device extension is an extension which does the same,
+but for any `VkDevice` object, or any dispatchable object that is a child of a
+`VkDevice` (`VkQueue` and `VkCommandBuffer` are examples of these).
+It is **very** important to know what type of extension you are desiring to
+enable as you will enable Instance extensions during `vkCreateInstance` and
+Device extensions during `vkCreateDevice`.
-The "library\_path" specifies either a filename, a relative pathname, or a full
-pathname to an ICD shared library file, which the loader will attempt to load
-using LoadLibrary(). If the ICD is specified via a filename, the shared library
-lives in the system's DLL search path (e.g. in the "C:\Windows\System32"
-folder). If the ICD is specified via a relative pathname, it is relative to the
-path of the manifest file. Relative pathnames are those that do not start with
-a drive specifier (e.g. "C:"), nor with a directory separator (i.e. the '\\'
-character), but do contain at least one directory separator.
+The loader discovers and aggregates all
+extensions from layers (both explicit and implicit), ICDs and the loader before
+reporting them to the application in `vkEnumerateXXXExtensionProperties`
+(where XXX is either "Instance" or "Device").
+ - Instance extensions are discovered via
+`vkEnumerateInstanceExtensionProperties`.
+ - Device extensions are be discovered via
+`vkEnumerateDeviceExtensionProperties`.
-The "file\_format\_version" specifies a major.minor.patch version number in
-case the format of the text information file changes in the future. If the same
-ICD shared library supports multiple, incompatible versions of text manifest
-file format versions, it must have separate JSON files for each (all of which may
-point to the same shared library).
+Looking at `vulkan.h`, you'll notice that they are both similar. For example,
+`vkEnumerateInstanceExtensionProperties` prototype looks as follows:
-The "api\_version" specifies the major.minor.patch version number of the Vulkan
-API that the shared library (referenced by "library\_path") was built with.
+```
+ VkResult
+ vkEnumerateInstanceExtensionProperties(const char *pLayerName,
+ uint32_t *pPropertyCount,
+ VkExtensionProperties *pProperties);
+```
-There are no rules about the name of the text information files (except the
-.json suffix).
+The "pLayerName" parameter in these functions is used to select either a single
+layer or the Vulkan platform implementation. If "pLayerName" is NULL, extensions
+from Vulkan implementation components (including loader, implicit layers, and
+ICDs) are enumerated. If "pLayerName" is equal to a discovered layer module name
+then only extensions from that layer (which may be implicit or explicit) are
+enumerated. Duplicate extensions (e.g. an implicit layer and ICD might report
+support for the same extension) are eliminated by the loader. For duplicates,
+the ICD version is reported and the layer version is culled.
-There are no rules about the name of the ICD shared library files. For example,
-if the registry contains the following values,
+Also, Extensions *must be enabled* (in `vkCreateInstance` or `vkCreateDevice`)
+before the functions associated with the extensions can be used. If you get an
+Extension function using either `vkGetInstanceProcAddr` or
+`vkGetDeviceProcAddr`, but fail to enable it, you could experience undefined
+behavior. This should actually be flagged if you run with Validation layers
+enabled.
-```
-[HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers\]
-"C:\vendor a\vk_vendora.json"=dword:00000000
+##### WSI Extensions
-"C:\windows\system32\vendorb_vk.json"=dword:00000000
+Khronos approved WSI extensions are available and provide Windows System
+Integration support for various execution environments. It is important to
+understand that some WSI extensions are valid for all targets, but others are
+particular to a given execution environment (and loader). This desktop loader
+(currently targeting Windows and Linux) only enables and directly exports those
+WSI extensions that are appropriate to the current environment. For the most
+part, the selection is done in the loader using compile-time preprocessor flags.
+All versions of the desktop loader currently expose at least the following WSI
+extension support:
+- VK_KHR_surface
+- VK_KHR_swapchain
+- VK_KHR_display
-"C:\windows\system32\vendorc_icd.json"=dword:00000000
-```
-then the loader will open the following text information files, with the
-specified contents:
+In addition, each of the following OS targets for the loader support target-
+specific extensions:
-| Text File Name | Text File Contents |
+| Windowing System | Extensions available |
|----------------|--------------------|
-|vk\_vendora.json | "ICD": { "library\_path": "C:\VENDOR A\vk_vendora.dll", "api_version": "1.0.5" } |
-| vendorb\_vk.json | "ICD": { "library\_path": "vendorb\_vk.dll", "api_version": "1.0.5" } |
-|vendorc\_icd.json | "ICD": { "library\_path": "vedorc\_icd.dll", "api_version": "1.0.5" }|
+| Windows | VK_KHR_win32_surface |
+| Linux (Default) | VK_KHR_xcb_surface and VK_KHR_xlib_surface |
+| Linux (Wayland) | VK_KHR_wayland_surface |
+| Linux (Mir) | VK_KHR_mir_surface |
+
+**NOTE:** Wayland and Mir targets are not fully supported at this time. Wayland
+support is present, but should be considered Beta quality. Mir support is not
+completely implemented at this time.
+
+It is important to understand that while the loader may support the various
+entry-points for these extensions, there is a hand-shake required to actually
+use them:
+* At least one physical device must support the extension(s)
+* The application must select such a physical device
+* The application must request the extension(s) be enabled while creating the
+instance or logical device (This depends on whether or not the given extension
+works with an instance or a device).
+* The instance and/or logical device creation must succeed.
-Then the loader will open the three files mentioned in the "Text File Contents"
-column, and then try to load and use the three shared libraries indicated by
-the ICD.library\_path value.
+Only then can you expect to properly use a WSI extension in your Vulkan program.
-##### Using Pre-Production ICDs
-IHV developers (and sometimes other developers) need to use special,
-pre-production ICDs. In some cases, a pre-production ICD may be in an
-installable package. In other cases, a pre-production ICD may simply be a
-shared library in the developer's build tree. In this latter case, we want to
-allow developers to point to such an ICD without modifying the
-properly-installed ICD(s) on their system.
+##### Unknown Extensions
-This need is met with the use of the "VK\_ICD\_FILENAMES" environment variable,
-which will override the mechanism used for finding properly-installed ICDs. In
-other words, only the ICDs listed in "VK\_ICD\_FILENAMES" will be used. The
-"VK\_ICD\_FILENAMES" environment variable is a semi-colon-separated list of ICD
-text information files (aka manifest files), containing the following:
+With the ability to expand Vulkan so easily, extensions will be created that the
+loader knows nothing about. If the extension is a device extension, the loader
+will pass the unknown entry-point down the device call chain ending with the
+appropriate ICD entry-points. The same thing will happen, if the extension is
+an instance extension which takes a physical device paramater as it's first
+component. However, for all other instance extensions the loader will fail to
+load it.
-- A full pathname (e.g. "C:\\my\_build\\my\_icd.json")
+*But why doesn't the loader support unknown instance extensions?*
+<br/>
+Let's look again at the Instance call chain:
-Typically, "VK\_ICD\_FILENAMES" will only contain a full pathname to one info
-file for a developer-built ICD. A semi-colon is only used if more than one ICD
-is listed.
+![Instance call chain](./images/loader_instance_chain.png)
-For example, if a developer wants to refer to one ICD that they built, they
-could set the "VK\_ICD\_FILENAMES" environment variable to:
+Notice that for a normal instance function call, the loader has to handle
+passing along the function call to the available ICDs. If the loader has no
+idea of the parameters or return value of the instance call, it can't properly
+pass information along to the ICDs. There may be ways to do this, which will be
+explored in the future. However, for now, this loader does not support
+instance extensions which don't take a physical device as their first parameter.
-C:\\my\_build\\my\_icd.json
+Because the device call-chain does not normally pass through the loader
+*terminator*, this is not a problem for device extensions. Additionally,
+since a physical device is associated with one ICD, we can use a generic
+*terminator* pointing to one ICD. This is because both of these extensions
+terminate directly in the ICD they are associated with.
-If a developer wants to refer to two ICDs, one of which is a properly-installed
-ICD, they can use the full pathname of the text file:
+*Is this a big problem?*
+<br/>
+No! Most extension functionality only affects either a physical or logical
+device and not an instance. Thus, the overwhelming majority of extensions
+should be supported with direct loader support.
-C:\\Windows\\System32\\vendorc\_icd.json;C:\\my\_build\\my\_icd.json
-Notice the semi-colon between "C:\\Windows\\System32\\vendorc\_icd.json" and
-"C:\\my\_build\\my\_icd.json".
+<br/>
+<br/>
-#### Linux
+## Loader and Layer Interface
+
+In this section we'll discuss how the loader interacts with layers, including:
+ * [Layer Discovery](#layer-discovery)
+ * [Layer Manifest File Usage](#layer-manifest-file-usage)
+ * [Android Layer Discovery](#android-layer-discovery)
+ * [Windows Layer Discovery](#windows-layer-discovery)
+ * [Linux Layer Discovery](#linux-layer-discovery)
+ * [Layer Version Negotiation](#layer-version-negotiation)
+ * [Layer Call Chains and Distributed Dispatch](#layer-call-chains-and-distributed-dispatch)
+ * [Layer Unknown Physical Device Extensions](#layer-unknown-physical-device-extensions)
+ * [Layer Intercept Requirements](#layer-intercept-requirements)
+ * [Distributed Dispatching Requirements](#distributed-dispatching-requirements)
+ * [Layer Conventions and Rules](#layer-conventions-and-rules)
+ * [Layer Dispatch Initialization](#layer-dispatch-initialization)
+ * [Example Code for CreateInstance](#example-code-for-createinstance)
+ * [Example Code for CreateDevice](#example-code-for-createdevice)
+ * [Special Considerations](#special-considerations)
+ * [Associating Private Data with Vulkan Objects Within a Layer](#associating-private-data-with-vulkan-objects-within-a-layer)
+ * [Wrapping](#wrapping)
+ * [Hash Maps](#hash-maps)
+ * [Creating New Dispatchable Objects](#creating-new-dispatchable-objects)
+ * [Layer Manifest File Format](#layer-manifest-file-format)
+ * [Layer Manifest File Version History](#layer-manifest-file-version-history)
+ * [Layer Library Versions](#layer-library-versions)
+ * [Layer Library API Version 2](#layer-library-api-version-2)
+ * [Layer Library API Version 1](#layer-library-api-version-1)
+ * [Layer Library API Version 0](#layer-library-api-version-0)
+
+
+
+#### Layer Discovery
+
+As mentioned in the
+[Application Interface section](#implicit-vs-explicit-layers),
+layers can be categorized into two categories:
+ * Implicit Layers
+ * Explicit Layers
+
+The main difference between the two is that Implicit Layers are automatically
+enabled, unless overriden, and Explicit Layers must be enabled. Remember,
+Implicit Layers are not present on all Operating Systems (like Android).
+
+On any system, the loader looks in specific areas for information on the
+layers that it can load at a user's request. The process of finding the
+available layers on a system is known as Layer Discovery. During discovery,
+the loader determines what layers are available, the layer name, the layer
+version, and any extensions supported by the layer. This information is
+provided back to an application through `vkEnumerateInstanceLayerProperties`.
+
+The group of layers available to the loader is known as a layer library. This
+section defines an extensible interface to discover what layers are contained in
+the layer library.
+
+This section also specifies the minimal conventions and rules a layer must
+follow, especially with regards to interacting with the loader and other layers.
+
+##### Layer Manifest File Usage
+
+On Windows and Linux systems, JSON formated manifest files are used to store
+layer information. In order to find system-installed layers, the Vulkan loader
+will read the JSON files to identify the names and attributes of layers and
+their extensions. The use of manifest files allows the loader to avoid loading
+any shared library files when the application does not query nor request any
+extensions. The format of [Layer Manifest File](#layer-manifest-file-format)
+is detailed below.
-##### Properly-Installed ICDs
+The Android loader does not use manifest files. Instead, the loader queries the
+layer properties using special functions known as "introspection" functions.
+The intent of these functions is to determine the same required information
+gathered from reading the manifest files. These introspection functions are
+not used by the desktop loader but should be present in layers to maintain
+consistency. The specific "introspection" functions are called out in
+the [Layer Manifest File Format](#layer-manifest-file-format) table.
-In order to find properly-installed ICDs, the Vulkan loader will scan the files
-in the following Linux directories:
-```
- /usr/local/etc/vulkan/icd.d
- /usr/local/share/vulkan/icd.d
- /etc/vulkan/icd.d
- /usr/share/vulkan/icd.d
- $HOME/.local/share/vulkan/icd.d
-```
+##### Android Layer Discovery
-The "/usr/local/*" directories can be configured to be other directories at build time.
+On Android, the loader looks for layers to enumerate in the
+/data/local/debug/vulkan folder. An application enabled for debug has the
+ability to enumerate and enable any layers in that location.
-Where $HOME is the current home directory of the application's user id; this
-path will be ignored for suid programs.
-These directories will contain text information files (a.k.a. "manifest
-files"), that use a JSON format.
+##### Windows Layer Discovery
-The Vulkan loader will open each manifest file found to obtain the name or
-pathname of an ICD shared library (".so") file. For example:
+In order to find system-installed layers, the Vulkan loader will scan the
+values in the following Windows registry keys:
```
-{
- "file_format_version": "1.0.0",
- "ICD": {
- "library_path": "path to ICD library",
- "api_version": "1.0.5"
- }
-}
+ HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\ExplicitLayers
+ HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\ImplicitLayers
```
-The "library\_path" specifies either a filename, a relative pathname, or a full
-pathname to an ICD shared library file. If the ICD is specified via a filename,
-the loader will attempt to open that file as a shared object using dlopen(),
-and the file must be in a directory that dlopen is configured to look in (Note:
-various distributions are configured differently). A distribution is free to
-create Vulkan-specific system directories (e.g. ".../vulkan/icd"), but is not
-required to do so. If the ICD is specified via a relative pathname, it is
-relative to the path of the info file. Relative pathnames are those that do not
-start with, but do contain at least one directory separator (i.e. the '/'
-character). For example, "lib/vendora.so" and "./vendora.so" are examples of
-relative pathnames.
-
-The "file\_format\_version" provides a major.minor.patch version number in case
-the format of the manifest file changes in the future. If the same ICD shared
-library supports multiple, incompatible versions of manifest file format
-versions, it must have multiple manifest files (all of which may point to the
-same shared library).
-
-The "api\_version" specifies the major.minor.patch version number of the Vulkan
-API that the shared library (referenced by "library\_path") was built with.
-
-The "/usr/local/etc/vulkan/icd.d" and "/usr/local/share/vulkan/icd.d"
-directories are for locally-built ICDs.
-
-The "/etc/vulkan/icd.d" directory is for
-ICDs that are installed from non-Linux-distribution-provided packages.
-
-The "/usr/share/vulkan/icd.d" directory is for ICDs that are installed from
-Linux-distribution-provided packages.
-
-There are no rules about the name of the text files (except the .json suffix).
-
-There are no rules about the name of the ICD shared library files. For example,
-if the "/usr/share/vulkan/icd.d" directory contain the following files, with
-the specified contents:
-
-| Text File Name | Text File Contents |
-|-------------------|------------------------|
-| vk\_vendora.json | "ICD": { "library\_path": "vendora.so", "api_version": "1.0.5" } |
-| vendorb\_vk.json | "ICD": { "library\_path": "vendorb\_vulkan\_icd.so", "api_version": "1.0.5" } |
-| vendorc\_icd.json | "ICD": { "library\_path": "/usr/lib/VENDORC/icd.so", "api_version": "1.0.5" } |
-then the loader will open the three files mentioned in the "Text File Contents"
-column, and then try to load and use the three shared libraries indicated by
-the ICD.library\_path value.
-
-##### Using Pre-Production ICDs
-
-IHV developers (and sometimes other developers) need to use special,
-pre-production ICDs. In some cases, a pre-production ICD may be in an
-installable package. In other cases, a pre-production ICD may simply be a
-shared library in the developer's build tree. In this latter case, we want to
-allow developers to point to such an ICD without modifying the
-properly-installed ICD(s) on their system.
-
-This need is met with the use of the "VK\_ICD\_FILENAMES" environment variable,
-which will override the mechanism used for finding properly-installed ICDs. In
-other words, only the ICDs listed in "VK\_ICD\_FILENAMES" will be used.
-
-The "VK\_ICD\_FILENAMES" environment variable is a colon-separated list of ICD
-manifest files, containing the following:
-
-- A filename (e.g. "libvkicd.json") in the
-"/usr/local/etc/vulkan/icd.d",
-"/usr/local/share/vulkan/icd.d",
-"/etc/vulkan/icd.d",
-"/usr/share/vulkan/icd.d",
-"$HOME/.local/share/vulkan/icd.d"
-directories
-
-- A full pathname (e.g. "/my\_build/my\_icd.json")
-
-Typically, "VK\_ICD\_FILENAMES" will only contain a full pathname to one info
-file for a developer-built ICD. A colon is only used if more than one ICD is
-listed.
+For each value in these keys which has DWORD data set to 0, the loader opens
+the JSON manifest file specified by the name of the value. Each name must be a
+full pathname to the manifest file. The Vulkan loader will open each info file
+to obtain information about the layer, including the name or pathname of a
+shared library (".dll") file. However, if VK\_LAYER\_PATH is defined, then the
+loader will instead look at the paths defined by that variable instead of using
+the information provided by these registry keys. See
+[Forcing Layer Source Folders](#forcing-layer-source-folders) for more
+information on this.
-For example, if a developer wants to refer to one ICD that they built, they
-could set the "VK\_ICD\_FILENAMES" environment variable to:
-/my\_build/my\_icd.json
+##### Linux Layer Discovery
-If a developer wants to refer to two ICDs, one of which is a properly-installed
-ICD, they can use the name of the text file in the system directory:
+On Linux, the Vulkan loader will scan the files in the following Linux
+directories:
-vendorc\_vulkan.json:/my\_build/my\_icd.json
+ /usr/local/etc/vulkan/explicit_layer.d
+ /usr/local/etc/vulkan/implicit_layer.d
+ /usr/local/share/vulkan/explicit_layer.d
+ /usr/local/share/vulkan/implicit_layer.d
+ /etc/vulkan/explicit_layer.d
+ /etc/vulkan/implicit_layer.d
+ /usr/share/vulkan/explicit_layer.d
+ /usr/share/vulkan/implicit_layer.d
+ $HOME/.local/share/vulkan/explicit_layer.d
+ $HOME/.local/share/vulkan/implicit_layer.d
-Notice the colon between "vendorc\_vulkan.json" and "/my\_build/my\_icd.json".
+Of course, ther are some things you have to know about the above folders:
+ 1. The "/usr/local/*" directories can be configured to be other directories at
+build time.
+ 2. $HOME is the current home directory of the application's user id; this path
+will be ignored for suid programs.
+ 3. The "/usr/local/etc/vulkan/\*\_layer.d" and
+"/usr/local/share/vulkan/\*\_layer.d" directories are for layers that are
+installed from locally-built sources.
+ 4. The "/usr/share/vulkan/\*\_layer.d" directories are for layers that are
+installed from Linux-distribution-provided packages.
-NOTE: this environment variable will be ignored for suid programs.
+As on Windows, if VK\_LAYER\_PATH is defined, then the
+loader will instead look at the paths defined by that variable instead of using
+the information provided by these default paths. However, these
+environment variables are only used for non-suid programs. See
+[Forcing Layer Source Folders](#forcing-layer-source-folders) for more
+information on this.
-#### Android
-The Android loader lives in the system library folder. The location cannot be
-changed. The loader will load the driver/ICD via hw_get_module with the ID
-of "vulkan". Due to security policies in Android none of this can be modified
-under normal use.
+#### Layer Version Negotiation
-<br/>
+Now that a layer has been discovered, an application can choose to load it (or
+it is loaded by default if it is an Implicit layer). When the loader attempts
+to load the layer, the first thing it does is attempt to negotiate the version
+of the loader to layer interface. In order to negotiate the loader/layer
+interface version, the layer must implement the
+`vkNegotiateLoaderLayerInterfaceVersion` function. The following information is
+provided for this interface in include/vulkan/vk_layer.h:
-## ICD interface requirements ##
+```cpp
+ typedef enum VkNegotiateLayerStructType {
+ LAYER_NEGOTIATE_INTERFACE_STRUCT = 1,
+ } VkNegotiateLayerStructType;
+
+ typedef struct VkNegotiateLayerInterface {
+ VkNegotiateLayerStructType sType;
+ void *pNext;
+ uint32_t loaderLayerInterfaceVersion;
+ PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr;
+ PFN_GetPhysicalDeviceProcAddr pfnGetPhysicalDeviceProcAddr;
+ } VkNegotiateLayerInterface;
+
+ VkResult vkNegotiateLoaderLayerInterfaceVersion(
+ VkNegotiateLayerInterface *pVersionStruct);
+```
-Generally, for all Vulkan commands issued by an application, the loader can be
-viewed as a pass through. That is, the loader generally doesn't modify the
-commands or their parameters, but simply calls the ICDs entry point for that
-command. There are specific additional interface requirements an ICD needs to comply with that
-are over and above any requirements from the Vulkan specification including WSI extension specification.
-These addtional requirements are versioned to allow flexibility in the future.
-These interface requirements will be set forth in the following sections: 1) describing
-which "loader-ICD" interface version is available, 2) detailing the most recent interface version;
-3) the supported, older interface requirements will be described as differences
-from the most recent interface version.
+You'll notice the `VkNegotiateLayerInterface` structure is similar to other
+Vulkan structures. The "sType" field, in this case takes a new enum defined
+just for internal loader/layer interfacing use. The valid values for "sType"
+could grow in the future, but right only havs the one value
+"LAYER_NEGOTIATE_INTERFACE_STRUCT".
+
+This function (`vkNegotiateLoaderLayerInterfaceVersion`) should be exported by
+the layer so that using "GetProcAddress" on Windows or "dlsym" on Linux, should
+return a valid function pointer to it. Once the loader has grabbed a valid
+address to the layers function, the loader will create a variable of type
+`VkNegotiateLayerInterface` and initialize it in the following ways:
+ 1. Set the structure "sType" to "LAYER_NEGOTIATE_INTERFACE_STRUCT"
+ 2. Set pNext to NULL.
+ - This is for future growth
+ 3. Set "loaderLayerInterfaceVersion" to the current version the loader desires
+to set the interface to.
+ - The minimum value sent by the loader will be 2 since it is the first
+version supporting this function.
+
+The loader will then individually call each layer’s
+`vkNegotiateLoaderLayerInterfaceVersion` function with the filled out
+“VkNegotiateLayerInterface”. The layer will either accept the loader's version
+set in "loaderLayerInterfaceVersion", or modify it to the closest value version
+of the interface that the layer can support. The value should not be higher
+than the version requested by the loader. If the layer can't support at a
+minimum the version requested, then the layer should return an error like
+"VK_ERROR_INITIALIZATION_FAILED". If a layer can support some version, then
+the layer should do the following:
+ 1. Adjust the version to the layer's desired version.
+ 2. The layer should fill in the function pointer values to its internal
+functions:
+ - "pfnGetInstanceProcAddr" should be set to the layer’s internal
+`GetInstanceProcAddr` function.
+ - "pfnGetDeviceProcAddr" should be set to the layer’s internal
+`GetDeviceProcAddr` function.
+ - "pfnGetPhysicalDeviceProcAddr" should be set to the layer’s internal
+`GetPhysicalDeviceProcAddr` function.
+ - If the layer supports no physical device extensions, it may set the
+value to NULL.
+ - More on this function later
+ 3. The layer should return "VK_SUCCESS"
+
+This function **SHOULD NOT CALL DOWN** the layer chain to the next layer.
+The loader will work with each layer individually.
+
+If the layer supports the new interface and reports version 2 or greater, then
+the loader will use the “fpGetInstanceProcAddr” and “fpGetDeviceProcAddr”
+functions from the “VkNegotiateLayerInterface” structure. Prior to these
+changes, the loader would query each of those functions using "GetProcAddress"
+on Windows or "dlsym" on Linux.
+
+
+#### Layer Call Chains and Distributed Dispatch
-#### Windows and Linux
+There are two key architectural features that drive the loader to layer library
+interface:
+ 1. Separate and distinct instance and device call chains
+ 2. Distributed dispatch.
-##### Version Negotiation Between Loader and ICDs
+You can read an overview of dispatch tables and call chains above in the
+[Dispatch Tables and Call Chains](#dispatch-tables-and-call-chains) section.
-All ICDs (supporting interface version 2 or higher) must export the following
-function that is used for determination of the interface version that will be used.
-This entry point is not a part of the Vulkan API itself, only a private interface
-between the loader and ICDs.
+What's important to note here is that a layer can intercept Vulkan
+instance functions, device functions or both. For a layer to intercept instance
+functions, it must participate in the instance call chain. For a layer to
+intercept device functions, it must participate in the device call chain.
-VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
+Remember, a layer does not need to intercept all instance or device functions,
+instead, it can choose to intercept only a subset of those functions.
-This entry point reports the "loader-ICD" interface version supported by both the loader and the ICD.
-The loader informs the ICD of it's desired interface version (typically the latest) via the
-pSupportedVersion parameter.
-This call is the first call made by the loader into the ICD (prior to any calls to
-vk\_icdGetInstanceProcAddr).
+Normally, when a layer intercepts a given Vulkan function, it will call down the
+instance or device call chain as needed. The loader and all layer libraries that
+participate in a call chain cooperate to ensure the correct sequencing of calls
+from one entity to the next. This group effort for call chain sequencing is
+hereinafter referred to as **distributed dispatch**.
+
+In distributed dispatch each layer is responsible for properly calling the next
+entity in the call chain. This means that a dispatch mechanism is required for
+all Vulkan functions that a layer intercepts. If a Vulkan function is not
+intercepted by a layer, or if a layer chooses to terminate the function by not
+calling down the chain, then no dispatch is needed for that particular function.
+
+For example, if the enabled layers intercepted only certain instance functions,
+the call chain would look as follows:
+![Instance Function Chain](./images/function_instance_chain.png)
+
+Likewise, if the enabled layers intercepted only a few of the device functions,
+the call chain could look this way:
+![Device Function Chain](./images/function_device_chain.png)
+
+The loader is responsible for dispatching all core and instance extension Vulkan
+functions to the first entity in the call chain.
+
+
+#### Layer Unknown Physical Device Extensions
+
+Originally, if the loader was called with `vkGetInstanceProcAddr`, it would
+result in the following behavior:
+ 1. The loader would check if core function:
+ - If it was, it would return the function pointer
+ 2. The loader would check if known extension function:
+ - If it was, it would return the function pointer
+ 3. If the loader knew nothing about it, it would call down using
+`GetInstanceProcAddr`
+ - If it returned non-NULL, treat it as an unknown logical device command.
+ - This meant setting up a generic trampoline function that takes in a
+VkDevice as the first parameter and adjusting the dispatch table to call the
+ICD/Layers function after getting the dispatch table from the VkDevice.
+ 4. If all the above failed, the loader would return NULL to the application.
+
+This caused problems when a layer attempted to expose new physical device
+extensions the loader knew nothing about, but an application did. Because the
+loader knew nothing about it, the loader would get to step 3 in the above
+process and would treat the function as an unknown logical device command. The
+problem is, this would create a generic VkDevice trampoline function which, on
+the first call, would attempt to dereference the VkPhysicalDevice as a VkDevice.
+This would lead to a crash or corruption.
+
+In order to identify the extension entry-points specific to physical device
+extensions, the following function can be added to a layer:
-If a loader sees that an ICD does not export this symbol it knows that it's dealing
-with a legacy ICD supporting either interface version 0 or 1.
-Similarly, if an ICD sees a call to vk\_icdGetInstanceProcAddr before a call to
-vk_icdGetLoaderICDInterfaceVersion then it knows that it's dealing with a legacy loader
-supporting version 0 or 1.
-**Note** if the loader calls vk\_icdGetInstanceProcAddr first it supports at least version 1,
-otherwise the loader only supports version 0.
+```cpp
+PFN_vkVoidFunction vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
+ const char* pName);
+```
-The pSupportedVersion parameter is both an input and output parameter.
-It is filled in by the loader before the call with the desired latest interface version supported by the loader.
+This function behaves similar to `vkGetInstanceProcAddr` and
+`vkGetDeviceProcAddr` except it should only return values for physical device
+extension entry-points. In this way, it compares "pName" to every physical
+device function supported in the layer.
+
+The following rules apply:
+ * If it is the name of a physical device function supported by the layer, the
+pointer to the layer's corresponding function should be returned.
+ * If it is the name of a valid function which is **not** a physical device
+function (i.e. an Instance, Device, or other function implemented by the layer),
+then the value of NULL should be returned.
+ * We don’t call down since we know the command is not a physical device
+extension).
+ * If the layer has no idea what this function is, it should call down the layer
+chain to the next `vk_layerGetPhysicalDeviceProcAddr` call.
+ * This can be retrieved in one of two ways:
+ * During `vkCreateInstance`, it is passed to a layer in the
+chain information passed to a layer in the `VkLayerInstanceCreateInfo`
+structure.
+ * Use `get_chain_info()` to get the pointer to the
+`VkLayerInstanceCreateInfo` structure. Let's call it chain_info.
+ * The address is then under
+chain_info->u.pLayerInfo->pfnNextGetPhysicalDeviceProcAddr
+ * See
+[Example Code for CreateInstance](#example-code-for-createinstance)
+ * Using the next layer’s `GetInstanceProcAddr` function to query for
+`vk_layerGetPhysicalDeviceProcAddr`.
+
+This support is optional and should not be considered a requirement. This is
+only required if a layer intends to support some functionality not directly
+supported by loaders released in the public. If a layer does implent this
+support, it should return the address of its `vk_layerGetPhysicalDeviceProcAddr`
+function in the "pfnGetPhysicalDeviceProcAddr" member of the
+`VkNegotiateLayerInterface` structure during
+[Layer Version Negotiation](#layer-version-negotiation). Additionally, the
+layer should also make sure `vkGetInstanceProcAddr` returns a valid function
+pointer to a query of `vk_layerGetPhysicalDeviceProcAddr`.
+
+The new behavior of the loader's `vkGetInstanceProcAddr` with support for the
+`vk_layerGetPhysicalDeviceProcAddr` function is as follows:
+ 1. Check if core function:
+ - If it is, return the function pointer
+ 2. Check if known instance or device extension function:
+ - If it is, return the function pointer
+ 3. Call the layer/ICD `GetPhysicalDeviceProcAddr`
+ - If it returns non-NULL, return a trampoline to a generic physical device
+function, and setup a generic terminator which will pass it to the proper ICD.
+ 4. Call down using `GetInstanceProcAddr`
+ - If it returns non-NULL, treat it as an unknown logical device command.
+This means setting up a generic trampoline function that takes in a VkDevice as
+the first parameter and adjusting the dispatch table to call the ICD/Layers
+function after getting the dispatch table from the VkDevice. Then, return the
+pointer to corresponding trampoline function.
+ 5. Return NULL
+
+You can see now, that, if the command gets promoted to core later, it will no
+longer be setup using `vk_layerGetPhysicalDeviceProcAddr`. Additionally, if the
+loader adds direct support for the extension, it will no longer get to step 3,
+because step 2 will return a valid function pointer. However, the layer should
+continue to support the command query via `vk_layerGetPhysicalDeviceProcAddr`,
+until at least a Vulkan version bump, because an older loader may still be
+attempting to use the commands.
+
+
+#### Layer Intercept Requirements
+
+ * Layers intercept a Vulkan function by defining a C/C++ function with
+signature **identical** to the Vulkan API for that function.
+ * A layer **must intercept at least** `vkGetInstanceProcAddr` and
+`vkCreateInstance` to participate in the instance call chain.
+ * A layer **may also intercept** `vkGetDeviceProcAddr` and `vkCreateDevice`
+to participate in the device call chain.
+ * For any Vulkan function a layer intercepts which has a non-void return value,
+**an appropriate value must be returned** by the layer intercept function.
+ * Most functions a layer intercepts **should call down the chain** to the
+corresponding Vulkan function in the next entity.
+ * The common behavior for a layer is to intercept a call, perform some
+behavior, then pass it down to the next entity.
+ * If you don't pass the information down, undefined behavior may occur.
+ * This is because the function will not be received by layers further down
+the chain, or any ICDs.
+ * One function that **must never call down the chain** is:
+ * `vkNegotiateLoaderLayerInterfaceVersion`
+ * Three common functions that **may not call down the chain** are:
+ * `vkGetInstanceProcAddr`
+ * `vkGetDeviceProcAddr`
+ * `vk_layerGetPhysicalDeviceProcAddr`
+ * These functions only call down the chain for Vulkan functions that they
+do not intercept.
+ * Layer intercept functions **may insert extra calls** to Vulkan functions in
+addition to the intercept.
+ * For example, a layer intercepting `vkQueueSubmit` may want to add a call to
+`vkQueueWaitIdle` after calling down the chain for `vkQueueSubmit`.
+ * This would result in two calls down the chain: First a call down the
+`vkQueueSubmit` chain, followed by a call down the `vkQueueWaitIdle` chain.
+ * Any additional calls inserted by a layer must be on the same chain
+ * If the function is a device function, only other device functions should
+be added.
+ * Likewise, if the function is an instance function, only other instance
+functions should be added.
+
+
+#### Distributed Dispatching Requirements
+
+- For each entry-point a layer intercepts, it must keep track of the entry
+point residing in the next entity in the chain it will call down into.
+ * In other words, the layer must have a list of pointers to functions of the
+appropriate type to call into the next entity.
+ * This can be implemented in various ways but
+for clarity, will be referred to as a dispatch table.
+- A layer can use the `VkLayerDispatchTable` structure as a device dispatch
+table (see include/vulkan/vk_layer.h).
+- A layer can use the `VkLayerInstanceDispatchTable` structure as a instance
+dispatch table (see include/vulkan/vk_layer.h).
+- A Layer's `vkGetInstanceProcAddr` function uses the next entity's
+`vkGetInstanceProcAddr` to call down the chain for unknown (i.e.
+non-intercepted) functions.
+- A Layer's `vkGetDeviceProcAddr` function uses the next entity's
+`vkGetDeviceProcAddr` to call down the chain for unknown (i.e. non-intercepted)
+functions.
+- A Layer's `vk_layerGetPhysicalDeviceProcAddr` function uses the next entity's
+`vk_layerGetPhysicalDeviceProcAddr` to call down the chain for unknown (i.e.
+non-intercepted) functions.
-If the ICD receiving the call no longer supports the interface version provided
-by the loader (due to deprecation) then it can report VK_ERROR_INCOMPATIBLE_DRIVER error,
-otherwise it sets the value pointed by pSupportedVersion to the latest interface
-version supported by both the ICD and the loader and returns VK_SUCCESS.
-The ICD should report VK_SUCCESS in case the loader provided interface version
-is newer than that supported by the ICD, as it's the loader's responsibility to
-determine whether it can support the older interface version supported by the ICD.
-The ICD should also report VK_SUCCESS in the case it's interface version is greater
-than the loader's, but return the loader's version. Thus, upon return of VK_SUCCESS
-the pSupportedVersion will contain the desired interface version to be used by the ICD.
-
-If the loader receives back an interface version from the ICD that the loader no longer
-supports (due to deprecation) or it receives a VK_ERROR_INCOMPATIBLE_DRIVER error
-instead of VK_SUCCESS then the loader will treat the ICD as incompatible
-and will not load it for use. In this case the application will not see the ICDs vkPhysicalDevice
-during enumeration.
-
-##### Loader Version 3 Interface Changes
-
-The primary change occuring in version 3 of the loader/ICD interface is to allow an ICD to
-handle Creation/Destruction of their own KHR_surfaces. Up until this point, the loader created
-a surface object that was used by all ICDs. However, some ICDs may want to provide their
-own surface handles. If an ICD chooses to enable this support, they must export support for
-version 3 of the Loader/ICD interface as well as any Vulkan command that uses a KHR_surface handle,
-such as:
-- vkCreateXXXSurfaceKHR (where XXX is the platform specific identifier [i.e.CreateWin32SurfaceKHR for Windows])
-- vkDestroySurfaceKHR
-- vkCreateSwapchainKHR
-- vkGetPhysicalDeviceSurfaceSupportKHR
-- vkGetPhysicalDeviceSurfaceCapabilitiesKHR
-- vkGetPhysicalDeviceSurfaceFormatsKHR
-- vkGetPhysicalDeviceSurfacePresentModesKHR
-
-An ICD can still choose to not take advantage of this functionality by simply not exposing the
-above the vkCreateXXXSurfaceKHR and vkDestroySurfaceKHR commands.
-##### Loader Version 2 Interface Requirements
+#### Layer Conventions and Rules
-Version 2 interface has requirements in three areas:
- 1. ICD Vulkan entry point discovery,
- 2. KHR_surface related requirements in the WSI extensions,
- 3. Vulkan dispatchable object creation requirements.
+A layer, when inserted into an otherwise compliant Vulkan implementation, must
+still result in a compliant Vulkan implementation. The intention is for layers
+to have a well-defined baseline behavior. Therefore, it must follow some
+conventions and rules defined below.
-###### ICD Vulkan entry point discovery
-All ICDs must export the following function that is used for discovery of ICD Vulkan entry points.
-This entry point is not a part of the Vulkan API itself, only a private interface between the loader and ICDs for version 1 and higher interfaces.
-
-VKAPI\_ATTR PFN\_vkVoidFunction VKAPI\_CALL vk\_icdGetInstanceProcAddr(VkInstance instance, const char* pName);
-
-This function has very similar semantics to the Vulkan command vkGetInstanceProcAddr.
-vk\_icdGetInstanceProcAddr returns valid function pointers for all the global level
-and instance level Vulkan commands, and also for vkGetDeviceProcAddr.
-Global level commands are those
-which contain no dispatchable object as the first parameter, such as
-vkCreateInstance and vkEnumerateInstanceExtensionProperties. The ICD must
-support querying global level entry points by calling
-vk\_icdGetInstanceProcAddr with a NULL VkInstance parameter. Instance level
-commands are those that have either VkInstance, or VkPhysicalDevice as the
-first parameter dispatchable object. Both core entry points and any instance
-extension entry points the ICD supports should be available via
-vk\_icdGetInstanceProcAddr. Future Vulkan instance extensions may define and
-use new instance level dispatchable objects other than VkInstance and
-VkPhysicalDevice, in which case extension entry points using these newly
-defined dispatchable objects must be queryable via vk\_icdGetInstanceProcAddr.
-
-All other Vulkan entry points must either NOT be exported from the ICD
-library or else NOT use the official Vulkan function names if they are
-exported. This requirement is for ICD libraries that include other
-functionality (such as OpenGL library) and thus could be loaded by the
-application prior to when the Vulkan loader library is loaded by the
-application. In other words, the ICD library exported Vulkan symbols must not
-clash with the loader's exported Vulkan symbols.
+A layer is always chained with other layers. It must not make invalid calls
+to, or rely on undefined behaviors of, its lower layers. When it changes the
+behavior of a function, it must make sure its upper layers do not make invalid
+calls to or rely on undefined behaviors of its lower layers because of the
+changed behavior. For example, when a layer intercepts an object creation
+function to wrap the objects created by its lower layers, it must make sure its
+lower layers never see the wrapping objects, directly from itself or
+indirectly from its upper layers.
-Beware of interposing by dynamic OS library loaders if the official Vulkan
-names are used. On Linux, if official names are used, the ICD library must be
-linked with -Bsymbolic.
+When a layer requires host memory, it may ignore the provided allocators. It
+should use memory allocators if the layer is intended to run in a production
+environment. For example, this usually applies to implicit layers that are
+always enabled. That will allow applications to include the layer's memory
+usage.
+
+Additional rules include:
+ - `vkEnumerateInstanceLayerProperties` **must** enumerate and **only**
+enumerate the layer itself.
+ - `vkEnumerateInstanceExtensionProperties` **must** handle the case where
+`pLayerName` is itself.
+ - It **must** return `VK_ERROR_LAYER_NOT_PRESENT` otherwise, including when
+`pLayerName` is `NULL`.
+ - `vkEnumerateDeviceLayerProperties` **is deprecated and may be omitted**.
+ - Using this will result in undefined behavior.
+ - `vkEnumerateDeviceExtensionProperties` **must** handle the case where
+`pLayerName` is itself.
+ - In other cases, it should normally chain to other layers.
+ - `vkCreateInstance` **must not** generate an error for unrecognized layer
+names and extension names.
+ - It may assume the layer names and extension names have been validated.
+ - `vkGetInstanceProcAddr` intercepts a Vulkan function by returning a local
+entry-point
+ - Otherwise it returns the value obtained by calling down the instance call
+chain.
+ - `vkGetDeviceProcAddr` intercepts a Vulkan function by returning a local
+entry-point
+ - Otherwise it returns the value obtained by calling down the device call
+chain.
+ - These additional functions must be intercepted if the layer implements
+device-level call chaining:
+ - `vkGetDeviceProcAddr`
+ - `vkCreateDevice`(only required for any device-level chaining)
+ - **NOTE:** older layer libraries may expect that `vkGetInstanceProcAddr`
+ignore `instance` when `pName` is `vkCreateDevice`.
+ - The specification **requires** `NULL` to be returned from
+`vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` for disabled functions.
+ - A layer may return `NULL` itself or rely on the following layers to do so.
+
+
+#### Layer Dispatch Initialization
+
+- A layer initializes its instance dispatch table within its `vkCreateInstance`
+function.
+- A layer initializes its device dispatch table within its `vkCreateDevice`
+function.
+- The loader passes a linked list of initialization structures to layers via
+the "pNext" field in the VkInstanceCreateInfo and `VkDeviceCreateInfo`
+structures for `vkCreateInstance` and `VkCreateDevice` respectively.
+- The head node in this linked list is of type `VkLayerInstanceCreateInfo` for
+instance and VkLayerDeviceCreateInfo for device. See file
+`include/vulkan/vk_layer.h` for details.
+- A VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO is used by the loader for the
+"sType" field in VkLayerInstanceCreateInfo.
+- A VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO is used by the loader for the
+"sType" field in VkLayerDeviceCreateInfo.
+- The "function" field indicates how the union field "u" should be interpreted
+within `VkLayer*CreateInfo`. The loader will set the "function" field to
+VK_LAYER_LINK_INFO. This indicates "u" field should be `VkLayerInstanceLink` or
+`VkLayerDeviceLink`.
+- The `VkLayerInstanceLink` and `VkLayerDeviceLink` structures are the list
+nodes.
+- The `VkLayerInstanceLink` contains the next entity's `vkGetInstanceProcAddr`
+used by a layer.
+- The `VkLayerDeviceLink` contains the next entity's `vkGetInstanceProcAddr` and
+`vkGetDeviceProcAddr` used by a layer.
+- Given the above structures set up by the loader, layer must initialize their
+dispatch table as follows:
+ - Find the `VkLayerInstanceCreateInfo`/`VkLayerDeviceCreateInfo` structure in
+the VkInstanceCreateInfo/VkDeviceCreateInfo structure.
+ - Get the next entity's vkGet*ProcAddr from the "pLayerInfo" field.
+ - For CreateInstance get the next entity's `vkCreateInstance` by calling the
+"pfnNextGetInstanceProcAddr":
+ pfnNextGetInstanceProcAddr(NULL, "vkCreateInstance").
+ - For CreateDevice get the next entity's `vkCreateDevice` by calling the
+"pfnNextGetInstanceProcAddr":
+ pfnNextGetInstanceProcAddr(NULL, "vkCreateDevice").
+ - Advanced the linked list to the next node: pLayerInfo = pLayerInfo->pNext.
+ - Call down the chain either `vkCreateDevice` or `vkCreateInstance`
+ - Initialize your layer dispatch table by calling the next entity's
+Get*ProcAddr function once for each Vulkan function needed in your dispatch
+table
-###### Handling KHR_surface objects in the WSI extensions
-Normally, ICDs handle object creation and destruction for various Vulkan
-objects. The WSI surface extensions for Linux and Windows
-(VK\_KHR\_win32\_surface, VK\_KHR\_xcb\_surface, VK\_KHR\_xlib\_surface,
-VK\_KHR\_mir\_surface, VK\_KHR\_wayland\_surface, and VK\_KHR\_surface) are
-handled differently. For these extensions, the VkSurfaceKHR object creation and
-destruction is handled by the loader as follows:
+#### Example Code for CreateInstance
-1. Loader handles the vkCreate\*SurfaceKHR() and vkDestroySurfaceKHR()
- functions including creating/destroying the VkSurfaceKHR object.
+```cpp
+VkResult vkCreateInstance(
+ const VkInstanceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkInstance *pInstance)
+{
+ VkLayerInstanceCreateInfo *chain_info =
+ get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
-2. VkSurfaceKHR objects have the underlying structure (VkIcdSurface\*) as
- defined in include/vulkan/vk\_icd.h.
+ assert(chain_info->u.pLayerInfo);
+ PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr =
+ chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+ PFN_vkCreateInstance fpCreateInstance =
+ (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
+ if (fpCreateInstance == NULL) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
-3. ICDs can cast any VkSurfaceKHR object to a pointer to the appropriate
- VkIcdSurface\* structure.
+ // Advance the link info for the next element of the chain
+ chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
-4. VkIcdSurface\* structures include VkIcdSurfaceWin32, VkIcdSurfaceXcb,
- VkIcdSurfaceXlib, VkIcdSurfaceMir, and VkIcdSurfaceWayland. The first field
- in the structure is a VkIcdSurfaceBase enumerant that indicates whether the
- surface object is Win32, Xcb, Xlib, Mir, or Wayland.
+ // Continue call down the chain
+ VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
+ if (result != VK_SUCCESS)
+ return result;
-###### ICD dispatchable object creation
-As previously covered, the loader requires dispatch tables to be accessible
-within Vulkan dispatchable objects, which include VkInstance, VkPhysicalDevice,
-VkDevice, VkQueue, and VkCommandBuffer. The specific requirements on all
-dispatchable objects created by ICDs are as follows:
+ // Init layer's dispatch table using GetInstanceProcAddr of
+ // next layer in the chain.
+ instance_dispatch_table = new VkLayerInstanceDispatchTable;
+ layer_init_instance_dispatch_table(
+ *pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
-- All dispatchable objects created by an ICD can be cast to void \*\*
+ // Other layer initialization
+ ...
-- The loader will replace the first entry with a pointer to the dispatch table
- which is owned by the loader. This implies three things for ICD drivers:
+ return VK_SUCCESS;
+}
+```
-1. The ICD must return a pointer for the opaque dispatchable object handle.
+#### Example Code for CreateDevice
-2. This pointer points to a regular C structure with the first entry being a
- pointer. Note: for any C\++ ICD's that implement VK objects directly as C\++
- classes. The C\++ compiler may put a vtable at offset zero if your class is
- non-POD due to the use of a virtual function. In this case use a regular C
- structure (see below).
+```cpp
+VkResult
+vkCreateDevice(
+ VkPhysicalDevice gpu,
+ const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkDevice *pDevice)
+{
+ VkLayerDeviceCreateInfo *chain_info =
+ get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
-3. The loader checks for a magic value (ICD\_LOADER\_MAGIC) in all the created
- dispatchable objects, as follows (see include/vulkan/vk\_icd.h):
+ PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr =
+ chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr =
+ chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
+ PFN_vkCreateDevice fpCreateDevice =
+ (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+ if (fpCreateDevice == NULL) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
-```
+ // Advance the link info for the next element on the chain
+ chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
-#include "vk_icd.h"
+ VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
+ if (result != VK_SUCCESS) {
+ return result;
+ }
-union _VK_LOADER_DATA {
- uintptr loadermagic;
- void *loaderData;
-} VK_LOADER_DATA;
+ // initialize layer's dispatch table
+ device_dispatch_table = new VkLayerDispatchTable;
+ layer_init_device_dispatch_table(
+ *pDevice, device_dispatch_table, fpGetDeviceProcAddr);
-vkObj alloc_icd_obj()
-{
- vkObj *newObj = alloc_obj();
+ // Other layer initialization
...
- // Initialize pointer to loader's dispatch table with ICD_LOADER_MAGIC
- set_loader_magic_value(newObj);
- ...
- return newObj;
+ return VK_SUCCESS;
}
```
-##### Loader Version 0 and 1 Interface Differences
-Version 0 and 1 interfaces do not support version negotiation via vk\_icdNegotiateLoaderICDInterfaceVersion.
-ICDs can distinguish version 0 and version 1 interfaces as follows:
-if the loader calls vk\_icdGetInstanceProcAddr first it supports version 1,
-otherwise the loader only supports version 0.
+#### Special Considerations
-Version 0 interface does not support vk\_icdGetInstanceProcAddr. Version 0 interface requirements for
-obtaining ICD Vulkan entry points are as follows:
-- vkGetInstanceProcAddr exported in the ICD library and returns valid function
- pointers for all the Vulkan API entry points;
+##### Associating Private Data with Vulkan Objects Within a Layer
-- vkCreateInstance exported in the ICD library;
+A layer may want to associate it's own private data with one or more Vulkan
+objects. Two common methods to do this are hash maps and object wrapping.
-- vkEnumerateInstanceExtensionProperties exported in the ICD library;
+###### Wrapping
-Additional Notes:
+The loader supports layers wrapping any Vulkan object, including dispatchable
+objects. For functions that return object handles, each layer does not touch
+the value passed down the call chain. This is because lower items may need to
+use the original value. However, when the value is returned from a
+lower-level layer (possibly the ICD), the layer saves the handle and returns
+its own handle to the layer above it (possibly the application). When a layer
+receives a Vulkan function using something that it previously returned a handle
+for, the layer is required to unwrap the handle and pass along the saved handle
+to the layer below it. This means that the layer **must intercept every Vulkan
+function which uses the object in question**, and wrap or unwrap the object, as
+appropriate. This includes adding support for all extensions with functions
+using any object the layer wraps.
-- The loader will filter out extensions requested in vkCreateInstance and
-vkCreateDevice before calling into the ICD; Filtering will be of extensions
-advertised by entities (e.g. layers) different from the ICD in question.
-- The loader will not call the ICD for vkEnumerate\*LayerProperties() as layer
-properties are obtained from the layer libraries and layer JSON files.
-- If an ICD library wants to implement a layer it can do so by having the
-appropriate layer JSON manifest file refer to the ICD library file.
-- The loader will not call the ICD for
- vkEnumerate\*ExtensionProperties(pLayerName != NULL).
-- ICDs creating new dispatchable objects via device extensions need to initialize
-the created dispatchable object. The loader has generic trampoline code for unknown
-device extensions. This generic trampoline code doesn't initialize the dispatch table within
-the newly created object. See the section for more information on how to initialize created
-dispatchable objects for extensions non known by the loader. [layer link](#creating-new-dispatchable-objects)
+Layers above the object wrapping layer will see the wrapped object. Layers
+which wrap dispatchable objects must ensure that the first field in the wrapping
+structure is a pointer to a dispatch table as defined in `vk_layer.h`.
+Specifically, an instance wrapped dispatchable object could be as follows:
+```
+struct my_wrapped_instance_obj_ {
+ VkLayerInstanceDispatchTable *disp;
+ // whatever data layer wants to add to this object
+};
+```
+A device wrapped dispatchable object could be as follows:
+```
+struct my_wrapped_instance_obj_ {
+ VkLayerDispatchTable *disp;
+ // whatever data layer wants to add to this object
+};
+```
-#### Android
+Layers that wrap dispatchable objects must follow the guidelines for creating
+new dispatchable objects (below).
-The Android loader uses the same protocol for initializing the dispatch
-table as described above. 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 and Linux loaders.
+<u>Cautions About Wrapping</u>
-<br/>
+Layers are generally discouraged from wrapping objects, because of the
+potential for incompatibilities with new extensions. For example, let's say
+that a layer wraps `VkImage` objects, and properly wraps and unwraps `VkImage`
+object handles for all core functions. If a new extension is created which has
+functions that take `VkImage` objects as parameters, and if the layer does not
+support those new functions, an application that uses both the layer and the new
+extension will have undefined behavior when those new functions are called (e.g.
+the application may crash). This is becaues the lower-level layers and ICD
+won't receive the handle that they generated. Instead, they will receive a
+handle that is only known by the layer that is wrapping the object.
-## Vulkan layer interface with the loader ##
+Because of the potential for incompatibilities with unsupported extensions,
+layers that wrap objects must check which extensions are being used by the
+application, and take appropriate action if the layer is used with unsupported
+extensions (e.g. disable layer functionality, stop wrapping objects, issue a
+message to the user).
-### Layer discovery
+The reason that the validation layers wrap objects, is to track the proper use
+and destruction of each object. They issue a validation error if used with
+unsupported extensions, alerting the user to the potential for undefined
+behavior.
-#### Windows
-<a name="ManifestFileExample"></a>
-##### Properly-Installed Layers
+###### Hash Maps
-In order to find properly-installed layers, the Vulkan loader will use a
-similar mechanism as used for ICDs. Text information files (aka manifest
-files), that use a JSON format, are read in order to identify the names and
-attributes of layers and their extensions. The use of manifest files allows the
-loader to avoid loading any shared library files when the application does not
-query nor request any extensions. Layers and extensions have additional
-complexity, and so their manifest files contain more information than ICD info
-files. For example, a layer shared library file may contain multiple
-layers/extensions (perhaps even an ICD).
+Alternatively, a layer may want to use a hash map to associate data with a
+given object. The key to the map could be the object. Alternatively, for
+dispatchable objects at a given level (eg device or instance) the layer may
+want data associated with the `VkDevice` or `VkInstance` objects. Since
+there are multiple dispatchable objects for a given `VkInstance` or `VkDevice`,
+the `VkDevice` or `VkInstance` object is not a great map key. Instead the layer
+should use the dispatch table pointer within the `VkDevice` or `VkInstance`
+since that will be unique for a given `VkInstance` or `VkDevice`.
-In order to find properly-installed layers, the Vulkan loader will scan the
-values in the following Windows registry keys:
-HKEY\_LOCAL\_MACHINE\\SOFTWARE\\Khronos\\Vulkan\\ExplicitLayers
+##### Creating New Dispatchable Objects
-HKEY\_LOCAL\_MACHINE\\SOFTWARE\\Khronos\\Vulkan\\ImplicitLayers
+Layers which create dispatchable objects must take special care. Remember that
+loader *trampoline* code normally fills in the dispatch table pointer in the
+newly created object. Thus, the layer must fill in the dispatch table pointer if
+the loader *trampoline* will not do so. Common cases where a layer (or ICD) may
+create a dispatchable object without loader *trampoline* code is as follows:
+- layers that wrap dispatchable objects
+- layers which add extensions that create dispatchable objects
+- layers which insert extra Vulkan funnctions in the stream of functions they
+intercept from the application
+- ICDs which add extensions that create dispatchable objects
-Explicit layers are those which are enabled by an application (e.g. with the
-vkCreateInstance function), or by an environment variable (as mentioned
-previously).
+The desktop loader provides a callback that can be used for initializing
+a dispatchable object. The callback is passed as an extension structure via the
+pNext field in the create info structure when creating an instance
+(`VkInstanceCreateInfo`) or device (`VkDeviceCreateInfo`). The callback
+prototype is defined as follows for instance and device callbacks respectively
+(see `vk_layer.h`):
-Implicit layers are those which are enabled by their existence. For example,
-certain application environments (e.g. Steam or an automotive infotainment
-system) may have layers which they always want enabled for all applications
-that they start. Other implicit layers may be for all applications started on a
-given system (e.g. layers that overlay frames-per-second). Implicit layers are
-enabled automatically, whereas explicit layers must be enabled explicitly. What
-distinguishes a layer as implicit or explicit is by which registry key its
-layer information file is referenced by.
+```cpp
+VKAPI_ATTR VkResult VKAPI_CALL vkSetInstanceLoaderData(VkInstance instance,
+ void *object);
+VKAPI_ATTR VkResult VKAPI_CALL vkSetDeviceLoaderData(VkDevice device,
+ void *object);
+```
-For each value in these keys which has DWORD data set to 0, the loader opens
-the JSON manifest file specified by the name of the value. Each name must be a
-full pathname to the manifest file.
+To obtain these callbacks the layer must search through the list of structures
+pointed to by the "pNext" field in the `VkInstanceCreateInfo` and
+`VkDeviceCreateInfo` parameters to find any callback structures inserted by the
+loader. The salient details are as follows:
+- For `VkInstanceCreateInfo` the callback structure pointed to by "pNext" is
+`VkLayerInstanceCreateInfo` as defined in `include/vulkan/vk_layer.h`.
+- A "sType" field in of VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO within
+`VkInstanceCreateInfo` parameter indicates a loader structure.
+- Within `VkLayerInstanceCreateInfo`, the "function" field indicates how the
+union field "u" should be interpreted.
+- A "function" equal to VK_LOADER_DATA_CALLBACK indicates the "u" field will
+contain the callback in "pfnSetInstanceLoaderData".
+- For `VkDeviceCreateInfo` the callback structure pointed to by "pNext" is
+`VkLayerDeviceCreateInfo` as defined in `include/vulkan/vk_layer.h`.
+- A "sType" field in of VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO within
+`VkDeviceCreateInfo` parameter indicates a loader structure.
+- Within `VkLayerDeviceCreateInfo`, the "function" field indicates how the union
+field "u" should be interpreted.
+- A "function" equal to VK_LOADER_DATA_CALLBACK indicates the "u" field will
+contain the callback in "pfnSetDeviceLoaderData".
+
+Alternatively, if an older loader is being used that doesn't provide these
+callbacks, the layer may manually initialize the newly created dispatchable
+object. To fill in the dispatch table pointer in newly created dispatchable
+object, the layer should copy the dispatch pointer, which is always the first
+entry in the structure, from an existing parent object of the same level
+(instance versus device).
+
+For example, if there is a newly created `VkCommandBuffer` object, then the
+dispatch pointer from the `VkDevice` object, which is the parent of the
+`VkCommandBuffer` object, should be copied into the newly created object.
+
+
+#### Layer Manifest File Format
+
+On Windows and Linux (desktop), the loader uses manifest files to discover
+layer libraries and layers. The desktop loader doesn't directly query the
+layer library except during chaining. This is to reduce the likelihood of
+loading a malicious layer into memory. Instead, details are read from the
+Manifest file, which are then provided for applications to determine what
+layers should actually be loaded.
-The Vulkan loader will open each info file to obtain information about the
-layer, including the name or pathname of a shared library (".dll") file.
+The following section discusses the details of the Layer Manifest JSON file
+format. The JSON file itself does not have any requirements for naming. The
+only requirement is that the extension suffix of the file ends with ".json".
-This manifest file is in the JSON format as shown in the following example.
-See the section [Layer Library Manifest File](#LayerLibraryManifestFile) for more information about each of the nodes in the JSON file.
+Here is an example layer JSON Manifest file with a single layer:
```
{
@@ -879,8 +1473,8 @@ See the section [Layer Library Manifest File](#LayerLibraryManifestFile) for mor
"implementation_version" : "2",
"description" : "LunarG HUD layer",
"functions": {
- "vkGetInstanceProcAddr": "OverlayLayer_GetInstanceProcAddr",
- "vkGetDeviceProcAddr": "OverlayLayer_GetDeviceProcAddr"
+ "vkNegotiateLoaderLayerInterfaceVersion":
+ "OverlayLayer_NegotiateLoaderLayerInterfaceVersion"
},
"instance_extensions": [
{
@@ -909,21 +1503,8 @@ See the section [Layer Library Manifest File](#LayerLibraryManifestFile) for mor
}
```
-The "library\_path" specifies either a filename, a relative pathname, or a full
-pathname to a layer shared library (".dll") file, which the loader will attempt
-to load using LoadLibrary(). If the layer is specified via a relative pathname,
-it is relative to the path of the info file (e.g. for cases when an application
-provides a layer that is in the same folder hierarchy as the rest of the
-application files). If the layer is specified via a filename, the shared
-library lives in the system's DLL search path (e.g. in the
-"C:\\Windows\\System32" folder).
-
-If defining multiple layers in a single JSON file prior to "file\_format\_version"
-1.0.1, you would simply define multiple "layer" objects. However, this is not
-valid JSON syntax. Instead, you should now define "file\_format\_version"
-1.0.1 (or newer) and use the new "layers" array object as seen in the
-following example:
-
+Here's a snippet with the changes required to support multiple layers per
+manifest file:
```
{
"file_format_version" : "1.0.1",
@@ -942,691 +1523,755 @@ following example:
}
```
-You could use the "layers" array object to define a single layer, as long as
-your "file\_format\_version" is defined to at least 1.0.1. It is functionally the
-same as using a single "layer" object.
+| JSON Node | Description and Notes | Introspection Query |
+|:----------------:|--------------------|:----------------:
+| "file\_format\_version" | Manifest format major.minor.patch version number. | N/A |
+| | Supported versions are: 1.0.0, 1.0.1, and 1.1.0. | |
+| "layer" | The identifier used to group a single layer's information together. | vkEnumerateInstanceLayerProperties |
+| "layers" | The identifier used to group multiple layers' information together. This requires a minimum Manifest file format version of 1.0.1.| vkEnumerateInstanceLayerProperties |
+| "name" | The string used to uniquely identify this layer to applications. | vkEnumerateInstanceLayerProperties |
+| "type" | This field indicates the type of layer. The values can be: GLOBAL, or INSTANCE | vkEnumerate*LayerProperties |
+| | **NOTES:** Prior to deprecation, the "type" node was used to indicate which layer chain(s) to activate the layer upon: instance, device, or both. Distinct instance and device layers are deprecated; there are now just layers. Allowable values for type (both before and after deprecation) are "INSTANCE", "GLOBAL" and, "DEVICE." "DEVICE" layers are skipped over by the loader as if they were not found. | |
+| "library\_path" | The "library\_path" specifies either a filename, a relative pathname, or a full pathname to a layer shared library file. If "library\_path" specifies a relative pathname, it is relative to the path of the JSON manifest file (e.g. for cases when an application provides a layer that is in the same folder hierarchy as the rest of the application files). If "library\_path" specifies a filename, the library must live in the system's shared object search path. There are no rules about the name of the layer shared library files other than it should end with the appropriate suffix (".DLL" on Windows, and ".so" on Linux). | N/A |
+| "api\_version" | The major.minor.patch version number of the Vulkan API that the shared library file for the library was built against. For example: 1.0.33. | vkEnumerateInstanceLayerProperties |
+| "implementation_version" | The version of the layer implemented. If the layer itself has any major changes, this number should change so the loader and/or application can identify it properly. | vkEnumerateInstanceLayerProperties |
+| "description" | A high-level description of the layer and it's intended use. | vkEnumerateInstanceLayerProperties |
+| "functions" | **OPTIONAL:** This section can be used to identify a different function name for the loader to use in place of standard layer interface functions. The "functions" node is required if the layer is using an alternative name for `vkNegotiateLoaderLayerInterfaceVersion`. | vkGet*ProcAddr |
+| "instance\_extensions" | **OPTIONAL:** Contains the list of instance extension names supported by this layer. One "instance\_extensions" node with an array of one or more elements is required if any instance extensions are supported by a layer, otherwise the node is optional. Each element of the array must have the nodes "name" and "spec_version" which correspond to `VkExtensionProperties` "extensionName" and "specVersion" respectively. | vkEnumerateInstanceExtensionProperties |
+| "device\_extensions" | **OPTIONAL:** Contains the list of device extension names supported by this layer. One "device_\extensions" node with an array of one or more elements is required if any device extensions are supported by a layer, otherwise the node is optional. Each element of the array must have the nodes "name" and "spec_version" which correspond to `VkExtensionProperties` "extensionName" and "specVersion" respectively. Additionally, each element of the array of device extensions must have the node "entrypoints" if the device extension adds Vulkan API functions, otherwise this node is not required. The "entrypoint" node is an array of the names of all entrypoints added by the supported extension. | vkEnumerateDeviceExtensionProperties |
+| "enable\_environment" | **Implicit Layers Only** - **OPTIONAL:** Indicates an environment variable used to enable the Implicit Layer (w/ value of 1). This environment variable (which should vary with each "version" of the layer) must be set to the given value or else the implicit layer is not loaded. This is for application environments (e.g. Steam) which want to enable a layer(s) only for applications that they launch, and allows for applications run outside of an application environment to not get that implicit layer(s).| N/A |
+| "disable\_environment" | **Implicit Layers Only** - **REQUIRED:**Indicates an environment variable used to disable the Implicit Layer (w/ value of 1). In rare cases of an application not working with an implicit layer, the application can set this environment variable (before calling Vulkan functions) in order to "blacklist" the layer. This environment variable (which should vary with each "version" of the layer) must be set (not particularly to any value). If both the "enable_environment" and "disable_environment" variables are set, the implicit layer is disabled. | N/A |
+
+
+##### Layer Manifest File Version History
+
+The current highest supported Layer Manifest file format supported is 1.1.0.
+Information about each version is detailed in the following sub-sections:
+
+###### Layer Manifest File Version 1.1.0
+
+Layer Manifest File Version 1.1.0 is tied to changes exposed by the Loader/Layer
+interface version 2.
+ 1. Renaming "vkGetInstanceProcAddr" in the "functions" section is
+ deprecated since the loader no longer needs to query the layer about
+ "vkGetInstanceProcAddr" directly. It is now returned during the layer
+ negotiation, so this field will be ignored.
+ 2. Renaming "vkGetDeviceProcAddr" in the "functions" section is
+ deprecated since the loader no longer needs to query the layer about
+ "vkGetDeviceProcAddr" directly. It too is now returned during the layer
+ negotiation, so this field will be ignored.
+ 3. Renaming the "vkNegotiateLoaderLayerInterfaceVersion" function is
+ being added to the "functions" section, since this is now the only
+ function the loader needs to query using OS-specific calls.
+ - NOTE: This is an optional field and, as the two previous fields, only
+needed if the layer requires changing the name of the function for some reason.
+
+You do not need to update your layer manifest file if you don't change the
+names of any of the listed functions.
+
+###### Layer Manifest File Version 1.0.1
+
+The ability to define multiple layers using the "layers" array was added. This
+JSON array field can be used when defining a single layer or multiple layers.
+The "layer" field is still present and valid for a single layer definition.
+
+###### Layer Manifest File Version 1.0.0
+
+The initial version of the layer manifest file specified the basic format and
+fields of a layer JSON file. The fields of the 1.0.0 file format include:
+ * "file\_format\_version"
+ * "layer"
+ * "name"
+ * "type"
+ * "library\_path"
+ * "api\_version"
+ * "implementation\_version"
+ * "description"
+ * "functions"
+ * "instance\_extensions"
+ * "device\_extensions"
+ * "enable\_environment"
+ * "disable\_environment"
+
+It was also during this time that the value of "DEVICE" was deprecated from
+the "type" field.
+
+
+#### Layer Library Versions
+
+The current Layer Library interface is at version 2. The following sections
+detail the differences between the various versions.
+
+##### Layer Library API Version 2
+
+Introduced the concept of
+[loader and layer interface](#layer-version-negotiation) using the new
+`vkNegotiateLoaderLayerInterfaceVersion` function. Additionally, it introduced
+the concept of
+[Layer Unknown Physical Device Extensions](#layer-unknown-physical-device-
+extensions)
+and the associated `vk_layerGetPhysicalDeviceProcAddr` function. Finally, it
+changed the manifest file defition to 1.1.0.
+
+##### Layer Library API Version 1
+
+A layer library supporting interface version 1 had the following behavior:
+ 1. `GetInstanceProcAddr` and `GetDeviceProcAddr` were directly exported
+ 2. The layer manifest file was able to override the names of the
+`GetInstanceProcAddr` and `GetDeviceProcAddr`functions.
-There are no rules about the name of the text files (except the .json suffix).
+##### Layer Library API Version 0
-There are no rules about the name of the layer shared library files.
+A layer library supporting interface version 0 must define and export these
+introspection functions, unrelated to any Vulkan function despite the names,
+signatures, and other similarities:
-##### Using Pre-Production Layers
+ - `vkEnumerateInstanceLayerProperties` enumerates all layers in a layer
+library.
+ - This function never fails.
+ - When a layer library contains only one layer, this function may be an alias
+ to the layer's `vkEnumerateInstanceLayerProperties`.
+ - `vkEnumerateInstanceExtensionProperties` enumerates instance extensions of
+ layers in a layer library.
+ - "pLayerName" is always a valid layer name.
+ - This function never fails.
+ - When a layer library contains only one layer, this function may be an alias
+ to the layer's `vkEnumerateInstanceExtensionProperties`.
+ - `vkEnumerateDeviceLayerProperties` enumerates a subset (can be full,
+ proper, or empty subset) of layers in a layer library.
+ - "physicalDevice" is always `VK_NULL_HANDLE`.
+ - This function never fails.
+ - If a layer is not enumerated by this function, it will not participate in
+ device function interception.
+ - `vkEnumerateDeviceExtensionProperties` enumerates device extensions of
+ layers in a layer library.
+ - "physicalDevice" is always `VK_NULL_HANDLE`.
+ - "pLayerName" is always a valid layer name.
+ - This function never fails.
-As with ICDs, developers may need to use special, pre-production layers,
-without modifying the properly-installed layers. This need is met with the use
-of the "VK\_LAYER\_PATH" environment variable, which will override the
-mechanism using for finding properly-installed layers. Because many layers may
-exist on a system, this environment variable is a semi-colon-separated list of
-folders that contain layer info files. Only the folder listed in
-"VK\_LAYER\_PATH" will be scanned for info files. Each semi-colon-separated
-entry is:
+It must also define and export these functions once for each layer in the
+library:
-- The full pathname of a folder containing layer info files
+ - `<layerName>GetInstanceProcAddr(instance, pName)` behaves identically to a
+layer's vkGetInstanceProcAddr except it is exported.
-#### Linux
+ When a layer library contains only one layer, this function may
+ alternatively be named `vkGetInstanceProcAddr`.
-##### Properly-Installed Layers
+ - `<layerName>GetDeviceProcAddr` behaves identically to a layer's
+vkGetDeviceProcAddr except it is exported.
-In order to find properly-installed layers, the Vulkan loader will use a
-similar mechanism as used for ICDs. Text information files, that use a JSON
-format, are read in order to identify the names and attributes of layers and
-their extensions. The use of text info files allows the loader to avoid loading
-any shared library files when the application does not query nor request any
-extensions. Layers and extensions have additional complexity, and so their info
-files contain more information than ICD info files. For example, a layer shared
-library file may contain multiple layers/extensions (perhaps even an ICD).
+ When a layer library contains only one layer, this function may
+ alternatively be named `vkGetDeviceProcAddr`.
-The Vulkan loader will scan the files in the following Linux directories:
+All layers contained within a library must support `vk_layer.h`. They do not
+need to implement functions that they do not intercept. They are recommended
+not to export any functions.
- /usr/local/etc/vulkan/explicit_layer.d
- /usr/local/etc/vulkan/implicit_layer.d
- /usr/local/share/vulkan/explicit_layer.d
- /usr/local/share/vulkan/implicit_layer.d
- /etc/vulkan/explicit_layer.d
- /etc/vulkan/implicit_layer.d
- /usr/share/vulkan/explicit_layer.d
- /usr/share/vulkan/implicit_layer.d
- $HOME/.local/share/vulkan/explicit_layer.d
- $HOME/.local/share/vulkan/implicit_layer.d
-The "/usr/local/*" directories can be configured to be other directories at build time.
+<br/>
+<br/>
-Where $HOME is the current home directory of the application's user id; this
-path will be ignored for suid programs.
+## Vulkan Installable Client Driver Interface With the Loader
+
+This section discusses the various requirements for the loader and a Vulkan
+ICD to properly hand-shake.
+
+ * [ICD Discovery](#icd-discovery)
+ * [ICD Manifest File Usage](#icd-manifest-file-usage)
+ * [ICD Discovery on Windows](#icd-discovery-on-windows)
+ * [ICD Discovery on Linux](#icd-discovery-on-linux)
+ * [Using Pre-Production ICDs on Windows and Linux](#using-pre-production-icds-on-windows-and-linux)
+ * [ICD Discovery on Android](#icd-discovery-on-android)
+ * [ICD Manifest File Format](#icd-manifest-file-format)
+ * [ICD Manifest File Versions](#icd-manifest-file-versions)
+ * [ICD Manifest File Version 1.0.0](#icd-manifest-file-version-1.0.0)
+ * [ICD Vulkan Entry-Point Discovery](#icd-vulkan-entry-point-discovery)
+ * [ICD Unknown Physical Device Extensions](#icd-unknown-physical-device-extensions)
+ * [ICD Dispatchable Object Creation](#icd-dispatchable-object-creation)
+ * [Handling KHR Surface Objects in WSI Extensions](#handling-khr-surface-objects-in-wsi-extensions)
+ * [Loader and ICD Interface Negotiation](#loader-and-icd-interface-negotiation)
+ * [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 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)
+ * [Loader Versions 0 and 1 Interface Requirements](#loader-versions-0-and-1-interface-requirements)
+ * [Android ICD Negotiation](#android-icd-negotiation)
+
+
+### ICD Discovery
+
+Vulkan allows multiple drivers each with one or more devices (represented by a
+Vulkan `VkPhysicalDevice` object) to be used collectively. The loader is
+responsible for discovering available Vulkan ICDs on the system. Given a list
+of available ICDs, the loader can enumerate all the physical devices available
+for an application and return this information to the application. The process
+in which the loader discovers the available Installable Client Drivers (ICDs)
+on a system is platform dependent. Windows, Linux and Android ICD discovery
+details are listed below.
+
+#### ICD Manifest File Usage
+
+As with layers, on Windows and Linux systems, JSON formated manifest files are
+used to store ICD information. In order to find system-installed drivers, the
+Vulkan loader will read the JSON files to identify the names and attributes of
+each driver. One thing you will notice is that ICD Manifest files are much
+simpler than the corresponding layer Manifest files.
+
+See the [Current ICD Manifest File Format](#icd-manifest-file-format) section
+for more details.
-Explicit layers are those which are enabled by an application (e.g. with the
-vkCreateInstance function), or by an environment variable (as mentioned
-previously). Implicit layers are those which are enabled by their existence.
-For example, certain application environments (e.g. Steam or an automotive
-infotainment system) may have layers which they always want enabled for all
-applications that they start. Other implicit layers may be for all applications
-started on a given system (e.g. layers that overlay frames-per-second).
-Implicit layers are enabled automatically, whereas explicit layers must be
-enabled explicitly. What distinguishes a layer as implicit or explicit is by
-which directory its layer information file exists in.
-
-The "/usr/local/etc/vulkan/\*\_layer.d" and "/usr/local/share/vulkan/\*\_layer.d"
-directories are for layers that are installed from locally-built sources.
-
-The "/etc/vulkan/\*\_layer.d" directories are for layers that are installed from
-non-Linux-distribution-provided packages.
-
-The "/usr/share/vulkan/\*\_layer.d" directories are for layers that are
-installed from Linux-distribution-provided packages.
-This manifest file is in the JSON format as shown in the following example.
-See the section [Layer Library Manifest File](#LayerLibraryManifestFile) for more information about each of the nodes in the JSON file.
+#### ICD Discovery on Windows
+
+In order to find installed ICDs, the Vulkan loader will scan the
+values in the following Windows registry key:
```
-{
- "file_format_version" : "1.0.0",
- "layer": {
- "name": "VK_LAYER_LUNARG_overlay",
- "type": "INSTANCE",
- "library_path": "libvkOverlayLayer.so"
- "api_version" : "1.0.5",
- "implementation_version" : "2",
- "description" : "LunarG HUD layer",
- "functions": {
- "vkGetInstanceProcAddr": "OverlayLayer_GetInstanceProcAddr",
- "vkGetDeviceProcAddr": "OverlayLayer_GetDeviceProcAddr"
- },
- "instance_extensions": [
- {
- "name": "VK_EXT_debug_report",
- "spec_version": "1"
- },
- {
- "name": "VK_VENDOR_ext_x",
- "spec_version": "3"
- }
- ],
- "device_extensions": [
- {
- "name": "VK_EXT_debug_marker",
- "spec_version": "1",
- "entrypoints": ["vkCmdDbgMarkerBegin", "vkCmdDbgMarkerEnd"]
- }
- ],
- "enable_environment": {
- "ENABLE_LAYER_OVERLAY_1": "1"
- },
- "disable_environment": {
- "DISABLE_LAYER_OVERLAY_1": ""
- }
- }
-}
+ HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers
```
-The "library\_path" specifies either a filename, a relative pathname, or a full
-pathname to a layer shared library (".so") file, which the loader will attempt
-to load using dlopen(). If the layer is specified via a filename, the loader
-will attempt to open that file as a shared object using dlopen(), and the file
-must be in a directory that dlopen is configured to look in (Note: various
-distributions are configured differently). A distribution is free to create
-Vulkan-specific system directories (e.g. ".../vulkan/layers"), but is not
-required to do so. If the layer is specified via a relative pathname, it is
-relative to the path of the info file (e.g. for cases when an application
-provides a layer that is in the same directory hierarchy as the rest of the
-application files).
-
-There are no rules about the name of the text files (except the .json suffix).
-
-There are no rules about the name of the layer shared library files.
-
-##### Using Pre-Production Layers
-
-As with ICDs, developers may need to use special, pre-production layers,
-without modifying the properly-installed layers. This need is met with the use
-of the "VK\_LAYER\_PATH" environment variable, which will override the
-mechanism using for finding properly-installed layers. Because many layers may
-exist on a system, this environment variable is a colon-separated list of
-directories that contain layer info files. Only the directories listed in
-"VK\_LAYER\_PATH" will be scanned for info files. Each colon-separated entry
-is:
-
-- The full pathname of a directory containing layer info files
-
-NOTE: these environment variables will be ignored for suid programs.
-
-#### Android
-
-The recommended way to enable layers is for applications
-to programatically enable them. The layers are provided by the application
-and must live in the application's library folder. The application
-enables the layers at vkCreateInstance as any Vulkan
-application would.
-An application enabled for debug has more options. It can enumerate and enable
-layers located in /data/local/debug/vulkan.
-<br/>
+For 32-bit applications on 64-bit Windows, the loader scan's the 32-bit
+registry location:
-## Layer interface requirements ##
+```
+ HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\Vulkan\Drivers
+```
-#### Architectural interface overview
+The loader will look at the appropriate registry location and check each value
+listed. If the key is of type DWORD, and it has a value of 0, the loader will
+open the JSON manifest file specified by the name. Each name must be a full
+pathname to a text manifest file. The Vulkan loader will attempt to open each
+manifest file to obtain the information about an ICD's shared library (".dll")
+file.
-There are two key architectural features that drive the loader to layer library
-interface: 1) separate and distinct instance and device call chains, and 2)
-distributed dispatch. First these architectural features will be described and
-then the detailed interface will be specified.
-
-Call chains are the links of calls for a given Vulkan command from layer module
-to layer module with the loader and or the ICD being the bottom most command.
-Call chains are constructed at both the instance level and the device level by
-the loader with cooperation from the layer libraries. Instance call chains are
-constructed by the loader when layers are enabled at vkCreateInstance. Device
-call chains are constructed by the loader when layers are enabled, by the loader, at
-vkCreateDevice. A layer can intercept Vulkan instance commands, device commands
-or both. For a layer to intercept instance commands, it must participate in the
-instance call chain. For a layer to intercept device commands, it must
-participate in the device chain.
-
-Normally, when a layer intercepts a given Vulkan command, it will call down the
-instance or device chain as needed. The loader and all layer libraries that
-participate in a call chain cooperate to ensure the correct sequencing of calls
-from one entity to the next. This group effort for call chain sequencing is
-hereinafter referred to as distributed dispatch. In distributed dispatch, since
-each layer is responsible for properly calling the next entity in the device or
-instance chain, a dispatch mechanism is required for all Vulkan commands a
-layer intercepts. For Vulkan commands that are not intercepted by a layer, or
-if the layer chooses to terminate a given Vulkan command by not calling down
-the chain, then no dispatch mechanism is needed for that particular Vulkan
-command. Only for those Vulkan commands, which may be a subset of all Vulkan
-commands, that a layer intercepts is a dispatching mechanism by the layer
-needed. The loader is responsible for dispatching all core and instance
-extension Vulkan commands to the first entity in the chain.
-
-Instance level Vulkan commands are those that have the dispatchable objects
-VkInstance, or VkPhysicalDevice as the first parameter and also includes
-vkCreateInstance.
-
-Device level Vulkan commands are those that use VkDevice, VkQueue or
-VkCommandBuffer as the first parameter and also include vkCreateDevice. Future
-extensions may introduce new instance or device level dispatchable objects, so
-the above lists may be extended in the future.
-
-#### Layer Library Interface
-
-A layer library is a container of layers. This section defines an extensible
-interface to discover layers contained in layer libraries.
-The extensible programming interface is used on Android only. For Windows and Linux,
-the layer manifest JSON files are used.
-
-It also specifies the minimal conventions
-and rules a layer must follow. Other sections might have other guidelines that layers should follow.
-
-##### Layer Conventions and Rules
+For example, let us assume the registry contains the following data:
-A layer, when inserted into an otherwise compliant Vulkan implementation, must
-still result in a compliant Vulkan implementation[\*]. It must additionally
-follow some conventions and rules.
+```
+[HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers\]
-A layer is always chained with other layers. It must not make invalid calls
-to or rely on undefined behaviors of its lower layers. When it changes the
-behavior of a command, it must make sure its upper layers do not make invalid
-calls to or rely on undefined behaviors of its lower layers because of the
-changed behavior. For example, when a layer intercepts an object creation
-command to wrap the objects created by its lower layers, it must make sure its
-lower layers never see the wrapping objects, directly from itself or
-indirectly from its upper layers.
+"C:\vendor a\vk_vendora.json"=dword:00000000
+"C:\windows\system32\vendorb_vk.json"=dword:00000001
+"C:\windows\system32\vendorc_icd.json"=dword:00000000
+```
-When a layer requires host memory, it may ignore the provided allocators. It
-should use memory allocators if the layer is intended to run in a production
-environment, such as an implicit layer that is always enabled. That will
-allow applications to include the layer's memory usage.
+In this case, the loader will step through each entry, and check the value. If
+the value is 0, then the loader will attempt to load the file. In this case,
+the loader will will open the first and last listings, but not the middle. This
+is because the value of 1 for vendorb_vk.json disables the driver.
-`vkEnumerateInstanceLayerProperties` must enumerate and only enumerate the
-layer itself.
+The Vulkan loader will open each enabled manifest file found to obtain the name
+or pathname of an ICD shared library (".DLL") file.
-`vkEnumerateInstanceExtensionProperties` must handle the case where
-`pLayerName` is itself. It must return `VK_ERROR_LAYER_NOT_PRESENT`
-otherwise, including when `pLayerName` is `NULL`.
+See the [ICD Manifest File Format](#icd-manifest-file-format) section for more
+details.
-`vkEnumerateDeviceLayerProperties` is deprecated and may be omitted. The
-behavior is undefined.
-`vkEnumerateDeviceExtensionProperties` must handle the case where `pLayerName`
-is itself. In other cases, it should normally chain to other layers.
+#### ICD Discovery on Linux
-`vkCreateInstance` must not generate an error for unrecognized layer names and
-extension names. It may assume the layer names and extension names have been
-validated.
+In order to find installed ICDs, the Vulkan loader will scan the files
+in the following Linux directories:
-`vkGetInstanceProcAddr` intercepts a Vulkan command by returning a local entry point,
-otherwise it returns the value obtained by calling down the instance chain.
- These commands must be intercepted
- - vkGetInstanceProcAddr
- - vkCreateInstance
- - vkCreateDevice (only required for any device-level chaining)
+```
+ /usr/local/etc/vulkan/icd.d
+ /usr/local/share/vulkan/icd.d
+ /etc/vulkan/icd.d
+ /usr/share/vulkan/icd.d
+ $HOME/.local/share/vulkan/icd.d
+```
- For compatibility with older layer libraries,
- - when `pName` is `vkCreateDevice`, it ignores `instance`.
+The "/usr/local/*" directories can be configured to be other directories at
+build time.
-`vkGetDeviceProcAddr` intercepts a Vulkan command by returning a local entry point,
-otherwise it returns the value obtained by calling down the device chain.
+The typical usage of the directories is indicated in the table below.
-The specification requires `NULL` to be returned from `vkGetInstanceProcAddr` and
-`vkGetDeviceProcAddr` for disabled commands. A layer may return `NULL` itself or
-rely on the following layers to do so.
+| Location | Details |
+|-------------------|------------------------|
+| $HOME/.local/share/vulkan/icd.d | $HOME is the current home directory of the application's user id; this path will be ignored for suid programs |
+| "/usr/local/etc/vulkan/icd.d" | Directory for locally built ICDs |
+| "/usr/local/share/vulkan/icd.d" | Directory for locally built ICDs |
+| "/etc/vulkan/icd.d" | Location of ICDs installed from non-Linux-distribution-provided packages |
+| "/usr/share/vulkan/icd.d" | Location of ICDs installed from Linux-distribution-provided packages |
-[\*]: The intention is for layers to have a well-defined baseline behavior.
-Some of the conventions or rules, for example, may be considered abuses of the
-specification.
+The Vulkan loader will open each manifest file found to obtain the name or
+pathname of an ICD shared library (".so") file.
-##### Layer Library API Version 0
+See the [ICD Manifest File Format](#icd-manifest-file-format) section for more
+details.
-A layer library supporting interface version 0 must define and export these
-introspection functions, unrelated to any Vulkan command despite the names,
-signatures, and other similarities:
+#### Using Pre-Production ICDs on Windows and Linux
- - `vkEnumerateInstanceLayerProperties` enumerates all layers in a layer
- library. This function never fails.
+Independent Hardware Vendor (IHV) pre-production ICDs. In some cases, a
+pre-production ICD may be in an installable package. In other cases, a
+pre-production ICD may simply be a shared library in the developer's build tree.
+In this latter case, we want to allow developers to point to such an ICD without
+modifying the system-installed ICD(s) on their system.
- When a layer library contains only one layer, this function may be an alias
- to the layer's `vkEnumerateInstanceLayerProperties`.
+This need is met with the use of the "VK\_ICD\_FILENAMES" environment variable,
+which will override the mechanism used for finding system-installed ICDs. In
+other words, only the ICDs listed in "VK\_ICD\_FILENAMES" will be used.
- - `vkEnumerateInstanceExtensionProperties` enumerates instance extensions of
- layers in a layer library. `pLayerName` is always a valid layer name.
- This function never fails.
+The "VK\_ICD\_FILENAMES" environment variable is a list of ICD
+manifest files, containing the full path to the ICD JSON Manifest file. This
+list is colon-separated on Linux, and semi-colon separated on Windows.
- When a layer library contains only one layer, this function may be an alias
- to the layer's `vkEnumerateInstanceExtensionProperties`.
+Typically, "VK\_ICD\_FILENAMES" will only contain a full pathname to one info
+file for a developer-built ICD. A separator (colon or semi-colon) is only used
+if more than one ICD is listed.
- - `vkEnumerateDeviceLayerProperties` enumerates a subset (can be full,
- proper, or empty subset) of layers in a layer library. `physicalDevice` is
- always `VK_NULL_HANDLE`. This function never fails.
+**NOTE:** On Linux, this environment variable will be ignored for suid programs.
- If a layer is not enumerated by this function, it will not participate in
- device command interception.
- - `vkEnumerateDeviceExtensionProperties` enumerates device extensions of
- layers in a layer library. `physicalDevice` is always `VK_NULL_HANDLE`.
- `pLayerName` is always a valid layer name. This function never fails.
+#### ICD Discovery on Android
-The introspection functions are not used by the desktop loader.
+The Android loader lives in the system library folder. The location cannot be
+changed. The loader will load the driver/ICD via hw\_get\_module with the ID
+of "vulkan". **Due to security policies in Android, none of this can be modified
+under normal use.**
-It must also define and export these functions one for each layer in the library:
- - `<layerName>GetInstanceProcAddr(instance, pName)` behaves identically to a layer's vkGetInstanceProcAddr except it is exported.
+### ICD Manifest File Format
- When a layer library contains only one layer, this function may
- alternatively be named `vkGetInstanceProcAddr`.
+The following section discusses the details of the ICD Manifest JSON file
+format. The JSON file itself does not have any requirements for naming. The
+only requirement is that the extension suffix of the file ends with ".json".
- - `<layerName>GetDeviceProcAddr` behaves identically to a layer's vkGetDeviceProcAddr except it is exported.
+Here is an example layer JSON Manifest file:
- When a layer library contains only one layer, this function may
- alternatively be named `vkGetDeviceProcAddr`.
+```
+{
+ "file_format_version": "1.0.0",
+ "ICD": {
+ "library_path": "path to ICD library",
+ "api_version": "1.0.5"
+ }
+}
+```
-All layers contained within a library must support [`vk_layer.h`][]. They do not need to
-implement commands that they do not intercept. They are recommended not to export
-any commands.
+| Field Name | Field Value |
+|----------------|--------------------|
+| "file\_format\_version" | The JSON format major.minor.patch version number of this file. Currently supported version is 1.0.0. |
+| "ICD" | The identifier used to group all ICD information together. |
+| "library_path" | The "library\_path" specifies either a filename, a relative pathname, or a full pathname to a layer shared library file. If "library\_path" specifies a relative pathname, it is relative to the path of the JSON manifest file. If "library\_path" specifies a filename, the library must live in the system's shared object search path. There are no rules about the name of the ICD shared library files other than it should end with the appropriate suffix (".DLL" on Windows, and ".so" on Linux). | N/A |
+| "api_version" | The major.minor.patch version number of the Vulkan API that the shared library files for the ICD was built against. For example: 1.0.33. |
-<a name="LayerLibraryManifestFile"></a>
-##### Layer Library Manifest File Version 0
-On Windows and Linux (desktop), the loader uses manifest files to discover
-layer libraries and layers. The desktop loader doesn't directly query the
-layer library except during chaining.
-On Android, the loader queries the layer libraries via the introspection functions as outlined above.
-
-The layer libraries and the manifest files must be kept in sync.
-
-The following table associates the desktop JSON nodes with the layer library introspection queries. It also indicates requirements.
-
-| Property | JSON node | Introspection query | Notes |
-|----------|-----------|-----------------------|-------|
-| file version | file_format_version | N/A | one node required per JSON file |
-| layers in library | layer | vkEnumerateInstanceLayerProperties | one node required per layer |
-| layer name | name | vkEnumerateInstanceLayerProperties | one node is required |
-| layer type | type | vkEnumerate*LayerProperties | see Note 1 |
-| library location | library_path | N/A | one node is required |
-| vulkan spec version | api_version | vkEnumerateInstanceLayerProperties | one node is required |
-| layer implementation version | api_version | vkEnumerateInstanceLayerProperties | see Note 2 |
-| layer description | description | vkEnumerateInstanceLayerProperties | one node is required |
-| chaining functions | functions | vkGet*ProcAddr | see Note 3 |
-| instance extensions | instance_extensions | vkEnumerateInstanceExtensionProperties | see Note 4 |
-| device extensions | device_extensions | vkEnumerateDeviceExtensionProperties | see Note 5 |
-| enable implicit | enable_environment | N/A | See Note 6 |
-| disable implicit | enable_environment | N/A | See Note 7 |
-
-"file\_format\_version" is used to indicate the valid JSON syntax of the file.
-As nodes are added or deleted which would change the parsing of this file,
-the file_format_version should change. This version
-is NOT the same as the layer library interface version. The interface version is a superset
-of the "file_format_version" and includes the semantics of the nodes in the JSON file.
-For interface version 0 the file format version must be "1.0.0"
-
-Note 1: Prior to deprecation, the "type" node was used to indicate which layer chain(s)
-to activate the layer upon: instance, device, or both.
-Distinct instance and device layers are deprecated; there are now just layers.
-Allowable values for type (both before and after deprecation) are "INSTANCE", "GLOBAL" and, "DEVICE."
-"DEVICE" layers are skipped over by the loader as if they were not found.
-Thus, layers must have a type of "GLOBAL" or "INSTANCE" for the loader to include the layer in the enumerated instance layer list.
-
-"library\_path" is the filename, full path, or relative path to the library file.
-See [Manifest File Example](#ManifestFileExample) section for more details.
-
-Note 2: One "implementation\_version" node is required per layer. This node gives the layer version, a single number
-increasing with backward uncompatible changes.
-
-Note 3: The "functions" node is required if the layer is using alternative
-names for vkGetInstanceProcAddr or vkGetDeviceProcAddr. vkGetInstanceProcAddr and vkGetDeviceProcAddr
-are required for all layers. See further requirements in the Layer Library API section above.
-
-Note 4: One "instance_extensions" node with an array of one or more elements
-required if any instance
-extensions are supported by a layer, otherwise the node is optional. Each
-element of the array must have the nodes "name" and "spec_version" which
-correspond to VkExtensionProperties "extensionName" and "specVersion"
-respectively.
-
-Note 5: One "device_extensions" node with an array of one or more elements
-required if any device
-extensions are supported by a layer, otherwise the node is optional. Each
-element of the array must have the nodes "name" and "spec_version" which
-correspond to VkExtensionProperties "extensionName" and "specVersion"
-respectively. Additionally, each element of the array of device extensions
-must have the node "entrypoints" if the device extension adds Vulkan API commands,
-otherwise this node is not required.
-The "entrypoint" node is an array of the names of all entrypoints added by the
-supported extension.
+**NOTE:** If the same ICD shared library supports multiple, incompatible
+versions of text manifest file format versions, it must have separate
+JSON files for each (all of which may point to the same shared library).
+
+##### ICD Manifest File Versions
+
+There has only been one version of the ICD manifest files supported. This is
+version 1.0.0.
+
+###### ICD Manifest File Version 1.0.0
+
+The initial version of the ICD Manifest file specified the basic format and
+fields of a layer JSON file. The fields of the 1.0.0 file format include:
+ * "file\_format\_version"
+ * "ICD"
+ * "library\_path"
+ * "api\_version"
+
+
+### ICD Vulkan Entry-Point Discovery
+
+The Vulkan symbols exported by an ICD must not clash with the loader's exported
+Vulkan symbols. This could be for several reasons. Because of this, all ICDs
+must export the following function that is used for discovery of ICD Vulkan
+entry-points. This entry-point is not a part of the Vulkan API itself, only a
+private interface between the loader and ICDs for version 1 and higher
+interfaces.
+
+```cpp
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(
+ VkInstance instance,
+ const char* pName);
```
- "device_extensions": [
- {
- "name": "VK_EXT_debug_marker",
- "spec_version": "1",
- "entrypoints": ["vkCmdDbgMarkerBegin", "vkCmdDbgMarkerEnd"]
- }
- ```
-
-Note 6: The "enable\_environment" node is only for implicit layers only. It is optional for implicit layers.
-This node gives an environment variable and value required to enable an implicit layer. This
-environment variable (which should vary with each "version" of the layer) must be set to the
-given value or else the implicit layer is not loaded. This is for application environments (e.g. Steam) which
-want to enable a layer(s) only for applications that they launch, and allows
-for applications run outside of an application environment to not get that
-implicit layer(s).
-
-Note 7: The "disable\_environment" node is only for implicit layers only. It is required for implicit layers.
-This node gives an environment variable and value required to disable an implicit layer. In
-rare cases of an application not working with an implicit layer, the
-application can set this environment variable (before calling Vulkan commands)
-in order to "blacklist" the layer. This environment variable (which should vary
-with each "version" of the layer) must be set (not particularly to any value).
-If both the "enable\_environment" and
-"disable\_environment" variables are set, the implicit layer is disabled.
-
-#### Layer Dispatch Interface Version 0
-##### Layer intercept requirements
-
-- Layers intercept a Vulkan command by defining a C/C++ function with signature
-identical to the Vulkan API for that command.
-- A layer must intercept at least vkGetInstanceProcAddr and
-vkCreateInstance. Additionally, a layer would also intercept vkGetDeviceProcAddr and vkCreateDevice to participate in the device chain.
-- For any Vulkan command a layer intercepts which has a non-void return value,
-an appropriate value must be returned by the layer intercept function.
-- The layer intercept function must call down the chain to the corresponding
-Vulkan command in the next entity. Undefined results will occur if a layer
-doesn't propagate calls down the chain. The two exceptions to this requirement
-are vkGetInstanceProcAddr and vkGetDeviceProcAddr which only call down the
-chain for Vulkan commands that they do not intercept.
-- Layer intercept functions may insert extra calls to Vulkan commands in
-addition to the intercept. For example, a layer intercepting vkQueueSubmit may
-want to add a call to vkQueueWaitIdle after calling down the chain for
-vkQueueSubmit. Any additional calls inserted by a layer must be on the same
-chain. They should call down the chain.
-
-##### Distributed dispatching requirements
-
-- For each entry point a layer intercepts, it must keep track of the entry
-point residing in the next entity in the chain it will call down into. In other
-words, the layer must have a list of pointers to functions of the appropriate
-type to call into the next entity. This can be implemented in various ways but
-for clarity will be referred to as a dispatch table.
-- A layer can use the VkLayerDispatchTable structure as a device dispatch table
-(see include/vulkan/vk_layer.h).
-- A layer can use the VkLayerInstanceDispatchTable structure as a instance
-dispatch table (see include/vulkan/vk_layer.h).
-- Layers vkGetInstanceProcAddr function uses the next entity's
-vkGetInstanceProcAddr to call down the chain for unknown (i.e. non-intercepted)
-functions.
-- Layers vkGetDeviceProcAddr function uses the next entity's
-vkGetDeviceProcAddr to call down the chain for unknown (i.e. non-intercepted)
-functions.
-##### Layer dispatch initialization
+This function has very similar semantics to `vkGetInstanceProcAddr`.
+`vk_icdGetInstanceProcAddr` returns valid function pointers for all the global-
+level and instance-level Vulkan functions, and also for `vkGetDeviceProcAddr`.
+Global-level functions are those which contain no dispatchable object as the
+first parameter, such as `vkCreateInstance` and
+`vkEnumerateInstanceExtensionProperties`. The ICD must support querying global-
+level entry-points by calling `vk_icdGetInstanceProcAddr` with a NULL
+`VkInstance` parameter. Instance-level functions are those that have either
+`VkInstance`, or `VkPhysicalDevice` as the first parameter dispatchable object.
+Both core entry-points and any instance extension entry-points the ICD supports
+should be available via `vk_icdGetInstanceProcAddr`. Future Vulkan instance
+extensions may define and use new instance-level dispatchable objects other
+than `VkInstance` and `VkPhysicalDevice`, in which case extension entry-points
+using these newly defined dispatchable objects must be queryable via
+`vk_icdGetInstanceProcAddr`.
+
+All other Vulkan entry-points must either:
+ * NOT be exported directly from the ICD library
+ * or NOT use the official Vulkan function names if they are exported
+
+This requirement is for ICD libraries that include other
+functionality (such as OpenGL) and thus could be loaded by the
+application prior to when the Vulkan loader library is loaded by the
+application.
+
+Beware of interposing by dynamic OS library loaders if the official Vulkan
+names are used. On Linux, if official names are used, the ICD library must be
+linked with -Bsymbolic.
-- A layer initializes its instance dispatch table within its vkCreateInstance
-function.
-- A layer initializes its device dispatch table within its vkCreateDevice
-function.
-- The loader passes a linked list of initialization structures to layers via
-the "pNext" field in the VkInstanceCreateInfo and VkDeviceCreateInfo structures
-for vkCreateInstance and VkCreateDevice respectively.
-- The head node in this linked list is of type VkLayerInstanceCreateInfo for
-instance and VkLayerDeviceCreateInfo for device. See file
-include/vulkan/vk_layer.h for details.
-- A VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO is used by the loader for the
-"sType" field in VkLayerInstanceCreateInfo.
-- A VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO is used by the loader for the
-"sType" field in VkLayerDeviceCreateInfo.
-- The "function" field indicates how the union field "u" should be interpreted
-within VkLayer*CreateInfo. The loader will set the "function" field to
-VK_LAYER_LINK_INFO. This indicates "u" field should be VkLayerInstanceLink or
-VkLayerDeviceLink.
-- The VkLayerInstanceLink and VkLayerDeviceLink structures are the list nodes.
-- The VkLayerInstanceLink contains the next entity's vkGetInstanceProcAddr used
-by a layer.
-- The VkLayerDeviceLink contains the next entity's vkGetInstanceProcAddr and
-vkGetDeviceProcAddr used by a layer.
-- Given the above structures set up by the loader, layer must initialize their
-dispatch table as follows:
- - Find the VkLayerInstanceCreateInfo/VkLayerDeviceCreateInfo structure in
-the VkInstanceCreateInfo/VkDeviceCreateInfo structure.
- - Get the next entity's vkGet*ProcAddr from the "pLayerInfo" field.
- - For CreateInstance get the next entity's vkCreateInstance by calling the
-"pfnNextGetInstanceProcAddr":
- pfnNextGetInstanceProcAddr(NULL, "vkCreateInstance").
- - For CreateDevice get the next entity's vkCreateDevice by calling the
-"pfnNextGetInstanceProcAddr":
- pfnNextGetInstanceProcAddr(NULL, "vkCreateDevice").
- - Advanced the linked list to the next node: pLayerInfo = pLayerInfo->pNext.
- - Call down the chain either CreateDevice or CreateInstance
- - Initialize your layer dispatch table by calling the next entity's
-Get*ProcAddr function once for each Vulkan command needed in your dispatch
-table
-##### Example code for CreateInstance
+### ICD Unknown Physical Device Extensions
+
+Originally, if the loader was called with `vkGetInstanceProcAddr`, it would
+result in the following behavior:
+ 1. The loader would check if core function:
+ - If it was, it would return the function pointer
+ 2. The loader would check if known extension function:
+ - If it was, it would return the function pointer
+ 3. If the loader knew nothing about it, it would call down using
+`GetInstanceProcAddr`
+ - If it returned non-NULL, treat it as an unknown logical device command.
+ - This meant setting up a generic trampoline function that takes in a
+VkDevice as the first parameter and adjusting the dispatch table to call the
+ICD/Layers function after getting the dispatch table from the VkDevice.
+ 4. If all the above failed, the loader would return NULL to the application.
+
+This caused problems when an ICD attempted to expose new physical device
+extensions the loader knew nothing about, but an application did. Because the
+loader knew nothing about it, the loader would get to step 3 in the above
+process and would treat the function as an unknown logical device command. The
+problem is, this would create a generic VkDevice trampoline function which, on
+the first call, would attempt to dereference the VkPhysicalDevice as a VkDevice.
+This would lead to a crash or corruption.
+
+In order to identify the extension entry-points specific to physical device
+extensions, the following function can be added to an ICD:
```cpp
-VkResult vkCreateInstance(
- const VkInstanceCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkInstance *pInstance)
-{
- VkLayerInstanceCreateInfo *chain_info =
- get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+PFN_vkVoidFunction vk_icdGetPhysicalDeviceProcAddr(VkInstance instance,
+ const char* pName);
+```
- assert(chain_info->u.pLayerInfo);
- PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr =
- chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
- PFN_vkCreateInstance fpCreateInstance =
- (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
- if (fpCreateInstance == NULL) {
- return VK_ERROR_INITIALIZATION_FAILED;
- }
+This function behaves similar to `vkGetInstanceProcAddr` and
+`vkGetDeviceProcAddr` except it should only return values for physical device
+extension entry-points. In this way, it compares "pName" to every physical
+device function supported in the ICD.
+
+The following rules apply:
+ * If it is the name of a physical device function supported by the ICD, the
+pointer to the ICD's corresponding function should be returned.
+ * If it is the name of a valid function which is **not** a physical device
+function (i.e. an Instance, Device, or other function implemented by the ICD),
+then the value of NULL should be returned.
+ * If the ICD has no idea what this function is, it should return NULL.
+
+This support is optional and should not be considered a requirement. This is
+only required if an ICD intends to support some functionality not directly
+supported by a significant population of loaders in the public. If an ICD
+does implent this support, it should return the address of its
+`vk_icdGetPhysicalDeviceProcAddr` function through the `vkGetInstanceProcAddr`
+function.
- // Advance the link info for the next element of the chain
- chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+The new behavior of the loader's vkGetInstanceProcAddr with support for the
+`vk_icdGetPhysicalDeviceProcAddr` function is as follows:
+ 1. Check if core function:
+ - If it is, return the function pointer
+ 2. Check if known instance or device extension function:
+ - If it is, return the function pointer
+ 3. Call the layer/ICD `GetPhysicalDeviceProcAddr`
+ - If it returns non-NULL, return a trampoline to a generic physical device
+function, and setup a generic terminator which will pass it to the proper ICD.
+ 4. Call down using `GetInstanceProcAddr`
+ - If it returns non-NULL, treat it as an unknown logical device command.
+This means setting up a generic trampoline function that takes in a VkDevice as
+the first parameter and adjusting the dispatch table to call the ICD/Layers
+function after getting the dispatch table from the VkDevice. Then, return the
+pointer to corresponding trampoline function.
+ 5. Return NULL
+
+You can see now, that, if the command gets promoted to core later, it will no
+longer be setup using `vk_icdGetPhysicalDeviceProcAddr`. Additionally, if the
+loader adds direct support for the extension, it will no longer get to step 3,
+because step 2 will return a valid function pointer. However, the ICD should
+continue to support the command query via `vk_icdGetPhysicalDeviceProcAddr`,
+until at least a Vulkan version bump, because an older loader may still be
+attempting to use the commands.
+
+
+### ICD Dispatchable Object Creation
- // Continue call down the chain
- VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
- if (result != VK_SUCCESS)
- return result;
+As previously covered, the loader requires dispatch tables to be accessible
+within Vulkan dispatchable objects, such as: `VkInstance`, `VkPhysicalDevice`,
+`VkDevice`, `VkQueue`, and `VkCommandBuffer`. The specific requirements on all
+dispatchable objects created by ICDs are as follows:
- // Init layer's dispatch table using GetInstanceProcAddr of
- // next layer in the chain.
- instance_dispatch_table = new VkLayerInstanceDispatchTable;
- layer_init_instance_dispatch_table(
- *pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
+- All dispatchable objects created by an ICD can be cast to void \*\*
+- The loader will replace the first entry with a pointer to the dispatch table
+ which is owned by the loader. This implies three things for ICD drivers
+ 1. The ICD must return a pointer for the opaque dispatchable object handle
+ 2. This pointer points to a regular C structure with the first entry being a
+ pointer.
+ * **NOTE:** For any C\++ ICD's that implement VK objects directly as C\++
+classes.
+ * The C\++ compiler may put a vtable at offset zero if your class is non-
+POD due to the use of a virtual function.
+ * In this case use a regular C structure (see below).
+ 3. The loader checks for a magic value (ICD\_LOADER\_MAGIC) in all the created
+ dispatchable objects, as follows (see `include/vulkan/vk_icd.h`):
- // Other layer initialization
+```cpp
+#include "vk_icd.h"
+
+union _VK_LOADER_DATA {
+ uintptr loadermagic;
+ void *loaderData;
+} VK_LOADER_DATA;
+
+vkObj alloc_icd_obj()
+{
+ vkObj *newObj = alloc_obj();
...
+ // Initialize pointer to loader's dispatch table with ICD_LOADER_MAGIC
- return VK_SUCCESS;
+ set_loader_magic_value(newObj);
+ ...
+ return newObj;
}
```
+
-##### Example code for CreateDevice
+### Handling KHR Surface Objects in WSI Extensions
-```cpp
-VkResult
-vkCreateDevice(
- VkPhysicalDevice gpu,
- const VkDeviceCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkDevice *pDevice)
-{
- VkLayerDeviceCreateInfo *chain_info =
- get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
+Normally, ICDs handle object creation and destruction for various Vulkan
+objects. The WSI surface extensions for Linux and Windows
+("VK\_KHR\_win32\_surface", "VK\_KHR\_xcb\_surface", "VK\_KHR\_xlib\_surface",
+"VK\_KHR\_mir\_surface", "VK\_KHR\_wayland\_surface", and "VK\_KHR\_surface")
+are handled differently. For these extensions, the `VkSurfaceKHR` object
+creation and destruction may be handled by either the loader, or an ICD.
+
+If the loader handles the management of the `VkSurfaceKHR` objects:
+ 1. The loader will handle the calls to `vkCreateXXXSurfaceKHR` and
+`vkDestroySurfaceKHR`
+ functions without involving the ICDs.
+ * Where XXX stands for the Windowing System name:
+ * Mir
+ * Wayland
+ * Xcb
+ * Xlib
+ * Windows
+ * Android
+ 2. The loader creates a `VkIcdSurfaceXXX` object for the corresponding
+`vkCreateXXXSurfaceKHR` call.
+ * The `VkIcdSurfaceXXX` structures are defined in `include/vulkan/vk_icd.h`.
+ 3. ICDs can cast any `VkSurfaceKHR` object to a pointer to the appropriate
+ `VkIcdSurfaceXXX` structure.
+ 4. The first field of all the `VkIcdSurfaceXXX` structures is a
+`VkIcdSurfaceBase` enumerant that indicates whether the
+ surface object is Win32, Xcb, Xlib, Mir, or Wayland.
+
+The ICD may choose to handle `VkSurfaceKHR` object creation instead. If an ICD
+desires to handle creating and destroying it must do the following:
+ 1. Support version 3 or newer of the loader/ICD interface.
+ 2. Export and handle all functions that take in a `VkSurfaceKHR` object,
+including:
+ * `vkCreateXXXSurfaceKHR`
+ * `vkGetPhysicalDeviceSurfaceSupportKHR`
+ * `vkGetPhysicalDeviceSurfaceCapabilitiesKHR`
+ * `vkGetPhysicalDeviceSurfaceFormatsKHR`
+ * `vkGetPhysicalDeviceSurfacePresentModesKHR`
+ * `vkCreateSwapchainKHR`
+ * `vkDestroySurfaceKHR`
+
+Because the `VkSurfaceKHR` object is an instance-level object, one object can be
+associated with multiple ICDs. Therefore, when the loader receives the
+`vkCreateXXXSurfaceKHR` call, it still creates an internal `VkSurfaceIcdXXX`
+object. This object acts as a container for each ICD's version of the
+`VkSurfaceKHR` object. If an ICD does not support the creation of its own
+`VkSurfaceKHR` object, the loader's container stores a NULL for that ICD. On
+the otherhand, if the ICD does support `VkSurfaceKHR` creation, the loader will
+make the appropriate `vkCreateXXXSurfaceKHR` call to the ICD, and store the
+returned pointer in it's container object. The loader then returns the
+`VkSurfaceIcdXXX` as a `VkSurfaceKHR` object back up the call chain. Finally,
+when the loader receives the `vkDestroySurfaceKHR` call, it subsequently calls
+`vkDestroySurfaceKHR` for each ICD who's internal `VkSurfaceKHR` object is not
+NULL. Then the loader destroys the container object before returning.
+
+
+### Loader and ICD Interface Negotiation
+
+Generally, for functions issued by an application, the loader can be
+viewed as a pass through. That is, the loader generally doesn't modify the
+functions or their parameters, but simply calls the ICDs entry-point for that
+function. There are specific additional interface requirements an ICD needs to
+comply with that are not part of any requirements from the Vulkan specification.
+These addtional requirements are versioned to allow flexibility in the future.
- PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr =
- chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
- PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr =
- chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
- PFN_vkCreateDevice fpCreateDevice =
- (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
- if (fpCreateDevice == NULL) {
- return VK_ERROR_INITIALIZATION_FAILED;
- }
- // Advance the link info for the next element on the chain
- chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
+#### Windows and Linux ICD Negotiation
- VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
- if (result != VK_SUCCESS) {
- return result;
- }
- // initialize layer's dispatch table
- device_dispatch_table = new VkLayerDispatchTable;
- layer_init_device_dispatch_table(
- *pDevice, device_dispatch_table, fpGetDeviceProcAddr);
+##### Version Negotiation Between Loader and ICDs
- // Other layer initialization
- ...
+All ICDs (supporting interface version 2 or higher) must export the following
+function that is used for determination of the interface version that will be
+used. This entry-point is not a part of the Vulkan API itself, only a private
+interface between the loader and ICDs.
- return VK_SUCCESS;
-}
+```cpp
+ VKAPI_ATTR VkResult VKAPI_CALL
+ vk_icdNegotiateLoaderICDInterfaceVersion(
+ uint32_t* pSupportedVersion);
```
-#### Special Considerations
-##### Associating private data with Vulkan objects within a layer
-A layer may want to associate it's own private data with one or more Vulkan
-objects. Two common methods to do this are hash maps and object wrapping.
+This function allows the loader and ICD to agree on an interface version to use.
+The "pSupportedVersion" parameter is both an input and output parameter.
+"pSupportedVersion" is filled in by the loader with the desired latest interface
+version supported by the loader (typically the latest). The ICD receives this
+and returns back the version it desires in the same field. Because it is
+setting up the interface version between the loader and ICD, this should be
+the first call made by a loader to the ICD (even prior to any calls to
+`vk_icdGetInstanceProcAddr`).
-###### Wrapping:
+If the ICD receiving the call no longer supports the interface version provided
+by the loader (due to deprecation), then it should report
+VK_ERROR_INCOMPATIBLE_DRIVER error. Otherwise it sets the value pointed by
+"pSupportedVersion" to the latest interface version supported by both the ICD
+and the loader and returns VK_SUCCESS.
-The loader supports layers wrapping any Vulkan object including dispatchable
-objects.
-For commands that return object handles, the layer saves the handle that is
-returned from a lower-level layer (possibly the ICD), and returns its own
-handle to the layer above it (possibly the application). For commands that are
-given previously-returned handles, the layer unwraps the handle; that is it
-looks up the saved handle and gives that to the layer below it.
+The ICD should report VK_SUCCESS in case the loader provided interface version
+is newer than that supported by the ICD, as it's the loader's responsibility to
+determine whether it can support the older interface version supported by the
+ICD. The ICD should also report VK_SUCCESS in the case its interface version
+is greater than the loader's, but return the loader's version. Thus, upon
+return of VK_SUCCESS the "pSupportedVersion" will contain the desired interface
+version to be used by the ICD.
+
+If the loader receives an interface version from the ICD that the loader no
+longer supports (due to deprecation), or it receives a
+VK_ERROR_INCOMPATIBLE_DRIVER error instead of VK_SUCCESS, then the loader will
+treat the ICD as incompatible and will not load it for use. In this case, the
+application will not see the ICDs `vkPhysicalDevice` during enumeration.
+
+###### Interfacing With Legacy ICDs or Loader
+
+If a loader sees that an ICD does not export the
+`vk_icdNegotiateLoaderICDInterfaceVersion` function, then the loader assumes the
+corresponding ICD only supports either interface version 0 or 1.
+
+From the other side of the interface, if an ICD sees a call to
+`vk_icdGetInstanceProcAddr` before a call to
+`vk_icdGetLoaderICDInterfaceVersion`, then it knows that loader making the calls
+is a legacy loader supporting version 0 or 1. If the loader calls
+`vk_icdGetInstanceProcAddr` first, it supports at least version 1. Otherwise,
+the loader only supports version 0.
+
+
+##### Loader Version 4 Interface Requirements
+
+The major change to version 4 of the loader/ICD interface is the support of
+[Unknown Physical Device Extensions](#icd-unknown-physical-device-
+extensions] using the `vk_icdGetPhysicalDeviceProcAddr` function. This
+function is purely optional. However, if an ICD supports a Physical Device
+extension, it must provide a `vk_icdGetPhysicalDeviceProcAddr` function.
+Otherwise, the loader will continue to treat any unknown functions as VkDevice
+functions and cause invalid behavior.
+
+
+##### Loader Version 3 Interface Requirements
+
+The primary change that occurred in version 3 of the loader/ICD interface was to
+allow an ICD to handle creation/destruction of their own KHR_surfaces. Up until
+this point, the loader created a surface object that was used by all ICDs.
+However, some ICDs may want to provide their own surface handles. If an ICD
+chooses to enable this support, it must export support for version 3 of the
+loader/ICD interface, as well as any Vulkan function that uses a KHR_surface
+handle, such as:
+- `vkCreateXXXSurfaceKHR` (where XXX is the platform specific identifier [i.e.
+`vkCreateWin32SurfaceKHR` for Windows])
+- `vkDestroySurfaceKHR`
+- `vkCreateSwapchainKHR`
+- `vkGetPhysicalDeviceSurfaceSupportKHR`
+- `vkGetPhysicalDeviceSurfaceCapabilitiesKHR`
+- `vkGetPhysicalDeviceSurfaceFormatsKHR`
+- `vkGetPhysicalDeviceSurfacePresentModesKHR`
+
+An ICD can still choose to not take advantage of this functionality by simply
+not exposing the above the `vkCreateXXXSurfaceKHR` and `vkDestroySurfaceKHR`
+functions.
-Layers which wrap objects must ensure they always unwrap objects before passing
-them down the chain. This means that the layer must intercept every Vulkan
-command which uses the object in question, and wrap or unwrap the object, as
-appropriate. This includes adding support for all extensions with commands
-using any object the layer wraps.
-Layers above the object wrapping layer will see the wrapped object. Layers
-which wrap dispatchable objects must ensure that the first field in the wrapping
-structure is a pointer to a dispatch table as defined in vk_layer.h. Specifically, an
-instance wrapped dispatchable object could be as follows:
-```
-struct my_wrapped_instance_obj_ {
- VkLayerInstanceDispatchTable *disp;
- // whatever data layer wants to add to this object
-};
-```
-A device wrapped dispatchable object could be as follows:
-```
-struct my_wrapped_instance_obj_ {
- VkLayerDispatchTable *disp;
- // whatever data layer wants to add to this object
-};
-```
+##### Loader Version 2 Interface Requirements
-Layers that wrap dispatchable objects must follow the guidelines for creating
-new dispatchable objects (below).
+Version 2 interface has requirements in three areas:
+ 1. ICD Vulkan entry-point discovery,
+ 2. `KHR_surface` related requirements in the WSI extensions,
+ 3. Vulkan dispatchable object creation requirements.
-<u><b>Cautions</b></u>
+##### Loader Versions 0 and 1 Interface Requirements
-Layers are generally discouraged from wrapping objects, because of the
-potential for incompatibilities with new extensions. For example, let's say
-that a layer wraps VkImage objects, and properly wraps and unwraps VkImage
-object handles for all core commands. If a new extension is created which has
-commands that take VkImage objects as parameters, and if the layer does not
-support those new commands, an application that uses both the layer and the new
-extension will have undefined behavior when those new commands are called (e.g.
-the application may crash). This is becaues the lower-level layers and ICD
-won't receive the handle that they generated. Instead, they will receive a
-handle that is only known by the layer that is wrapping the object.
+Version 0 and 1 interfaces do not support version negotiation via
+`vk_icdNegotiateLoaderICDInterfaceVersion`. ICDs can distinguish version 0 and
+version 1 interfaces as follows: if the loader calls `vk_icdGetInstanceProcAddr`
+first it supports version 1; otherwise the loader only supports version 0.
-Because of the potential for incompatibilities with unsupported extensions,
-layers that wrap objects must check which extensions are being used by the
-application, and take appropriate action if the layer is used with unsupported
-extensions (e.g. disable layer functionality, stop wrapping objects, issue a
-message to the user).
+Version 0 interface does not support `vk_icdGetInstanceProcAddr`. Version 0
+interface requirements for obtaining ICD Vulkan entry-points are as follows:
-The reason that the validation layers wrap objects, is to track the proper use
-and destruction of each object. They issue a validation error if used with
-unsupported extensions, alerting the user to the potential for undefined
-behavior.
+- The function `vkGetInstanceProcAddr` **must be exported** in the ICD library
+and returns valid function pointers for all the Vulkan API entry-points.
+- `vkCreateInstance` **must be exported** by the ICD library.
+- `vkEnumerateInstanceExtensionProperties` **must be exported** by the ICD
+library.
-###### Hash Maps:
-Alternatively, a layer may want to use a hash map to associate data with a
-given object. The key to the map could be the object. Alternatively, for
-dispatchable objects at a given level (eg device or instance) the layer may
-want data associated with the VkDevice or VkInstance objects. Since
-there are multiple dispatchable objects for a given VkInstance or VkDevice, the
-VkDevice or VkInstance object is not a great map key. Instead the layer should
-use the dispatch table pointer within the VkDevice or VkInstance since that
-will be unique for a given VkInstance or VkDevice.
-
-##### Creating new dispatchable objects
-Layers which create dispatchable objects take special care. Remember that loader
-trampoline code normally fills in the dispatch table pointer in the newly
-created object. Thus, the layer must fill in the dispatch table pointer if the
-loader trampoline will not do so. Common cases where a layer (or ICD) may create a
-dispatchable object without loader trampoline code is as follows:
-- object wrapping layers that wrap dispatchable objects
-- layers which add extensions that create dispatchable objects
-- layers which insert extra Vulkan commands in the stream of commands they
-intercept from the application
-- ICDs which add extensions that create dispatchable objects
+Additional Notes:
-The Windows/Linux loader provides a callback that can be used for initializing
-a dispatchable object. The callback is passed as an extension structure via the
-pNext field in VkInstanceCreateInfo and VkDeviceCreateInfo. The callback prototype
-is defined as follows for instance and device callbacks respectively (see vk_layer.h):
-```
-VKAPI_ATTR VkResult VKAPI_CALL vkSetInstanceLoaderData(VkInstance instance, void *object);
-VKAPI_ATTR VkResult VKAPI_CALL vkSetDeviceLoaderData)(VkDevice device, void *object);
-```
-To obtain these callbacks the layer must search through the list of structures
-pointed to by the "pNext" field in the VkInstanceCreateInfo and VkDeviceCreateInfo parameters to find any callback structures inserted by the loader. The salient details are as follows:
-- For CreateInstance the callback structure pointed to by "pNext" is VkLayerInstanceCreateInfo as defined in vk_layer.h.
-- A "sType" field in of VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO within VkInstanceCreateInfo parameter indicates a loader structure.
-- Within VkLayerInstanceCreateInfo, the "function" field indicates how the union field "u" should be interpreted.
-- A "function" equal to VK_LOADER_DATA_CALLBACK indicates the "u" field will contain the callback in "pfnSetInstanceLoaderData".
-- For CreateDevice the callback structure pointed to by "pNext" is VkLayerDeviceCreateInfo as defined in include/vulkan/vk_layer.h.
-- A "sType" field in of VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO within VkDeviceCreateInfo parameter indicates a loader structure.
-- Within VkLayerDeviceCreateInfo, the "function" field indicates how the union field "u" should be interpreted.
-- A "function" equal to VK_LOADER_DATA_CALLBACK indicates the "u" field will contain the callback in "pfnSetDeviceLoaderData".
-
-Alternatively, if an older loader is being used that doesn't provide these callbacks, the layer may manually initialize the newly created dispatchable object.
-To fill in the dispatch table pointer in newly created dispatchable object,
-the layer should copy the dispatch pointer, which is always the first entry in the structure, from an existing parent object of the same level (instance versus
-device). For example, if there is a newly created VkCommandBuffer object, then the dispatch pointer from the VkDevice object, which is the parent of the VkCommandBuffer object, should be copied into the newly created object.
+- The loader will filter out extensions requested in `vkCreateInstance` and
+`vkCreateDevice` before calling into the ICD; Filtering will be of extensions
+advertised by entities (e.g. layers) different from the ICD in question.
+- The loader will not call the ICD for `vkEnumerate\*LayerProperties`() as layer
+properties are obtained from the layer libraries and layer JSON files.
+- If an ICD library author wants to implement a layer, it can do so by having
+the appropriate layer JSON manifest file refer to the ICD library file.
+- The loader will not call the ICD for
+ `vkEnumerate\*ExtensionProperties` if "pLayerName" is not equal to `NULL`.
+- ICDs creating new dispatchable objects via device extensions need to
+initialize the created dispatchable object. The loader has generic *trampoline*
+code for unknown device extensions. This generic *trampoline* code doesn't
+initialize the dispatch table within the newly created object. See the
+[Creating New Dispatchable Objects](#creating-new-dispatchable-objects) section
+for more information on how to initialize created dispatchable objects for
+extensions non known by the loader.
+
+#### Android ICD Negotiation
+
+The Android loader uses the same protocol for initializing the dispatch
+table as described above. 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 and Linux loaders.
+
+
+## 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(). |
+| Device Call Chain | The call chain of functions followed for device functions. This call chain for a device function is usually as follows: first the application calls into a loader trampoline, then the loader trampoline calls enabled layers, the final layer calls into the ICD specific to the device. See the [Dispatch Tables and Call Chains](#dispatch-tables-and-call-chains) section for more information |
+| Device Function | A Device function is any Vulkan function which takes a `VkDevice`, `VkQueue`, `VkCommandBuffer`, or any child of these, as its first parameter. Some Vulkan Device functions are: `vkQueueSubmit`, `vkBeginCommandBuffer`, `vkCreateEvent`. See the [Instance Versus Device](#instance-versus-device) section for more information. |
+| Discovery | The process of the loader searching for ICD and Layer files to setup the internal list of Vulkan objects available. On Windows/Linux, the discovery process typically focuses on searching for Manifest files. While on Android, the process focuses on searching for library files. |
+| Dispatch Table | An array of function pointers (including core and possibly extension functions) used to step to the next entity in a call chain. The entity could be the loader, a layer or an ICD. See [Dispatch Tables and Call Chains](#dispatch-tables-and-call-chains) for more information. |
+| Extension | A concept of Vulkan used to expand the core Vulkan functionality. Extensions may be IHV-specific, platform-specific, or more broadly available. You should always query if an extension exists, and enable it during `vkCreateInstance` (if it is an instance extension) or during `vkCreateDevice` (if it is a device extension). |
+| ICD | Acronym for Installable Client Driver. These are drivers that are provided by IHVs to interact with the hardware they provide. See [Installable Client Drivers](#installable-client-drivers) section for more information.
+| IHV | Acronym for an Independent Hardware Vendor. Typically the company that built the underlying hardware technology you are trying to use. A typical examples for a Graphics IHV are: AMD, ARM, Imagination, Intel, Nvidia, Qualcomm, etc. |
+| Instance Call Chain | The call chain of functions followed for instance functions. This call chain for an instance function is usually as follows: first the application calls into a loader trampoline, then the loader trampoline calls enabled layers, the final layer calls a loader terminator, and the loader terminator calls all available ICDs. See the [Dispatch Tables and Call Chains](#dispatch-tables-and-call-chains) section for more information |
+| Instance Function | An Instance function is any Vulkan function which takes as its first parameter either a `VkInstance` or a `VkPhysicalDevice` or nothing at all. Some Vulkan Instance functions are: `vkEnumerateInstanceExtensionProperties`, `vkEnumeratePhysicalDevices`, `vkCreateInstance`, `vkDestroyInstance`. See the [Instance Versus Device](#instance-versus-device) section for more information. |
+| Layer | Layers are optional components that augment the Vulkan system. They can intercept, evaluate, and modify existing Vulkan functions on their way from the application down to the hardware. See the [Layers](#layers) section for more information. |
+| Loader | The middle-ware program which acts as the mediator between Vulkan applications, Vulkan layers and Vulkan drivers. See [The Loader](#the loader) section for more information. |
+| Manifest Files | Data files in JSON format used by the desktop loader. These files contain specific information for either a [Layer](#layer-manifest-file-format) or an [ICD](#icd-manifest-file-format).
+| Terminator Function | The last function in the instance call chain above the ICDs and owned by the loader. This function is required in the instance call chain because all instance functionality must be communicated to all ICDs capable of receiving the call. See [Dispatch Tables and Call Chains](#dispatch-tables-and-call-chains) for more information. |
+| Trampoline Function | The first function in an instance or device call chain owned by the loader which handles the setup and proper call chain walk using the appropriate dispatch table. On device functions (in the device call chain) this function can actually be skipped. See [Dispatch Tables and Call Chains](#dispatch-tables-and-call-chains) for more information. |
+| WSI Extension | Acronym for Windowing System Integration. A Vulkan extension targeting a particular Windowing and designed to interface between the Windowing system and Vulkan. See [WSI Extensions](#wsi-extensions) for more information. |
diff --git a/loader/chain_skipping_layers.png b/loader/chain_skipping_layers.png
deleted file mode 100644
index 0eca54ef..00000000
--- a/loader/chain_skipping_layers.png
+++ /dev/null
Binary files differ
diff --git a/loader/debug_report.c b/loader/debug_report.c
index 15233bc2..bf9ff411 100644
--- a/loader/debug_report.c
+++ b/loader/debug_report.c
@@ -103,7 +103,7 @@ static VKAPI_ATTR VkResult VKAPI_CALL debug_report_CreateDebugReportCallbackEXT(
VkDebugReportCallbackEXT *pCallback) {
struct loader_instance *inst = loader_get_instance(instance);
loader_platform_thread_lock_mutex(&loader_lock);
- VkResult result = inst->disp->CreateDebugReportCallbackEXT(
+ VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(
instance, pCreateInfo, pAllocator, pCallback);
loader_platform_thread_unlock_mutex(&loader_lock);
return result;
@@ -295,7 +295,8 @@ debug_report_DestroyDebugReportCallbackEXT(
struct loader_instance *inst = loader_get_instance(instance);
loader_platform_thread_lock_mutex(&loader_lock);
- inst->disp->DestroyDebugReportCallbackEXT(instance, callback, pAllocator);
+ inst->disp->layer_inst_disp.DestroyDebugReportCallbackEXT(
+ instance, callback, pAllocator);
util_DestroyDebugReportCallback(inst, callback, pAllocator);
@@ -308,8 +309,9 @@ static VKAPI_ATTR void VKAPI_CALL debug_report_DebugReportMessageEXT(
int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
struct loader_instance *inst = loader_get_instance(instance);
- inst->disp->DebugReportMessageEXT(instance, flags, objType, object,
- location, msgCode, pLayerPrefix, pMsg);
+ inst->disp->layer_inst_disp.DebugReportMessageEXT(
+ instance, flags, objType, object, location, msgCode, pLayerPrefix,
+ pMsg);
}
/*
diff --git a/loader/dev_ext_trampoline.c b/loader/dev_ext_trampoline.c
index e1cf6251..e1ffa37c 100644
--- a/loader/dev_ext_trampoline.c
+++ b/loader/dev_ext_trampoline.c
@@ -24,2008 +24,519 @@
#pragma GCC optimize(3) // force gcc to use tail-calls
#endif
-VKAPI_ATTR void VKAPI_CALL vkdev_ext0(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[0](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext1(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[1](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext2(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[2](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext3(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[3](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext4(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[4](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext5(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[5](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext6(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[6](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext7(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[7](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext8(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[8](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext9(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[9](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext10(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[10](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext11(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[11](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext12(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[12](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext13(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[13](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext14(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[14](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext15(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[15](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext16(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[16](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext17(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[17](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext18(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[18](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext19(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[19](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext20(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[20](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext21(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[21](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext22(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[22](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext23(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[23](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext24(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[24](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext25(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[25](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext26(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[26](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext27(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[27](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext28(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[28](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext29(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[29](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext30(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[30](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext31(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[31](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext32(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[32](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext33(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[33](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext34(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[34](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext35(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[35](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext36(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[36](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext37(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[37](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext38(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[38](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext39(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[39](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext40(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[40](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext41(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[41](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext42(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[42](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext43(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[43](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext44(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[44](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext45(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[45](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext46(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[46](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext47(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[47](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext48(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[48](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext49(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[49](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext50(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[50](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext51(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[51](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext52(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[52](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext53(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[53](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext54(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[54](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext55(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[55](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext56(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[56](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext57(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[57](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext58(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[58](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext59(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[59](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext60(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[60](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext61(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[61](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext62(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[62](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext63(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[63](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext64(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[64](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext65(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[65](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext66(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[66](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext67(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[67](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext68(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[68](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext69(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[69](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext70(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[70](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext71(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[71](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext72(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[72](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext73(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[73](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext74(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[74](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext75(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[75](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext76(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[76](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext77(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[77](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext78(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[78](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext79(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[79](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext80(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[80](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext81(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[81](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext82(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[82](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext83(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[83](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext84(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[84](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext85(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[85](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext86(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[86](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext87(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[87](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext88(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[88](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext89(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[89](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext90(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[90](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext91(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[91](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext92(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[92](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext93(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[93](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext94(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[94](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext95(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[95](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext96(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[96](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext97(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[97](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext98(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[98](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext99(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[99](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext100(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[100](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext101(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[101](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext102(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[102](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext103(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[103](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext104(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[104](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext105(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[105](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext106(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[106](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext107(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[107](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext108(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[108](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext109(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[109](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext110(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[110](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext111(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[111](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext112(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[112](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext113(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[113](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext114(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[114](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext115(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[115](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext116(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[116](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext117(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[117](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext118(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[118](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext119(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[119](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext120(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[120](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext121(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[121](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext122(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[122](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext123(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[123](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext124(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[124](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext125(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[125](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext126(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[126](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext127(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[127](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext128(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[128](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext129(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[129](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext130(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[130](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext131(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[131](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext132(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[132](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext133(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[133](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext134(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[134](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext135(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[135](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext136(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[136](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext137(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[137](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext138(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[138](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext139(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[139](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext140(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[140](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext141(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[141](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext142(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[142](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext143(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[143](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext144(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[144](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext145(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[145](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext146(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[146](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext147(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[147](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext148(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[148](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext149(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[149](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext150(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[150](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext151(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[151](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext152(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[152](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext153(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[153](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext154(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[154](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext155(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[155](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext156(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[156](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext157(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[157](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext158(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[158](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext159(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[159](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext160(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[160](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext161(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[161](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext162(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[162](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext163(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[163](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext164(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[164](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext165(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[165](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext166(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[166](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext167(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[167](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext168(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[168](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext169(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[169](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext170(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[170](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext171(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[171](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext172(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[172](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext173(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[173](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext174(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[174](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext175(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[175](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext176(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[176](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext177(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[177](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext178(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[178](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext179(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[179](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext180(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[180](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext181(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[181](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext182(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[182](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext183(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[183](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext184(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[184](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext185(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[185](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext186(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[186](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext187(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[187](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext188(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[188](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext189(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[189](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext190(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[190](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext191(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[191](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext192(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[192](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext193(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[193](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext194(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[194](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext195(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[195](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext196(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[196](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext197(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[197](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext198(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[198](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext199(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[199](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext200(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[200](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext201(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[201](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext202(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[202](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext203(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[203](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext204(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[204](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext205(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[205](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext206(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[206](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext207(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[207](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext208(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[208](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext209(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[209](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext210(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[210](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext211(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[211](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext212(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[212](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext213(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[213](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext214(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[214](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext215(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[215](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext216(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[216](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext217(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[217](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext218(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[218](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext219(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[219](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext220(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[220](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext221(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[221](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext222(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[222](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext223(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[223](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext224(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[224](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext225(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[225](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext226(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[226](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext227(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[227](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext228(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[228](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext229(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[229](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext230(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[230](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext231(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[231](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext232(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[232](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext233(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[233](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext234(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[234](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext235(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[235](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext236(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[236](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext237(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[237](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext238(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[238](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext239(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[239](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext240(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[240](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext241(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[241](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext242(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[242](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext243(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[243](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext244(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[244](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext245(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[245](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext246(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[246](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext247(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[247](device);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkdev_ext248(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[248](device);
-}
+ // Trampoline function macro for unknown physical device extension command.
+#define DevExtTramp(num) \
+VKAPI_ATTR void VKAPI_CALL vkdev_ext##num(VkDevice device) { \
+ const struct loader_dev_dispatch_table *disp; \
+ disp = loader_get_dev_dispatch(device); \
+ disp->ext_dispatch.dev_ext[num](device); \
+ }
-VKAPI_ATTR void VKAPI_CALL vkdev_ext249(VkDevice device) {
- const struct loader_dev_dispatch_table *disp;
- disp = loader_get_dev_dispatch(device);
- disp->ext_dispatch.dev_ext[249](device);
-}
+DevExtTramp(0)
+DevExtTramp(1)
+DevExtTramp(2)
+DevExtTramp(3)
+DevExtTramp(4)
+DevExtTramp(5)
+DevExtTramp(6)
+DevExtTramp(7)
+DevExtTramp(8)
+DevExtTramp(9)
+DevExtTramp(10)
+DevExtTramp(11)
+DevExtTramp(12)
+DevExtTramp(13)
+DevExtTramp(14)
+DevExtTramp(15)
+DevExtTramp(16)
+DevExtTramp(17)
+DevExtTramp(18)
+DevExtTramp(19)
+DevExtTramp(20)
+DevExtTramp(21)
+DevExtTramp(22)
+DevExtTramp(23)
+DevExtTramp(24)
+DevExtTramp(25)
+DevExtTramp(26)
+DevExtTramp(27)
+DevExtTramp(28)
+DevExtTramp(29)
+DevExtTramp(30)
+DevExtTramp(31)
+DevExtTramp(32)
+DevExtTramp(33)
+DevExtTramp(34)
+DevExtTramp(35)
+DevExtTramp(36)
+DevExtTramp(37)
+DevExtTramp(38)
+DevExtTramp(39)
+DevExtTramp(40)
+DevExtTramp(41)
+DevExtTramp(42)
+DevExtTramp(43)
+DevExtTramp(44)
+DevExtTramp(45)
+DevExtTramp(46)
+DevExtTramp(47)
+DevExtTramp(48)
+DevExtTramp(49)
+DevExtTramp(50)
+DevExtTramp(51)
+DevExtTramp(52)
+DevExtTramp(53)
+DevExtTramp(54)
+DevExtTramp(55)
+DevExtTramp(56)
+DevExtTramp(57)
+DevExtTramp(58)
+DevExtTramp(59)
+DevExtTramp(60)
+DevExtTramp(61)
+DevExtTramp(62)
+DevExtTramp(63)
+DevExtTramp(64)
+DevExtTramp(65)
+DevExtTramp(66)
+DevExtTramp(67)
+DevExtTramp(68)
+DevExtTramp(69)
+DevExtTramp(70)
+DevExtTramp(71)
+DevExtTramp(72)
+DevExtTramp(73)
+DevExtTramp(74)
+DevExtTramp(75)
+DevExtTramp(76)
+DevExtTramp(77)
+DevExtTramp(78)
+DevExtTramp(79)
+DevExtTramp(80)
+DevExtTramp(81)
+DevExtTramp(82)
+DevExtTramp(83)
+DevExtTramp(84)
+DevExtTramp(85)
+DevExtTramp(86)
+DevExtTramp(87)
+DevExtTramp(88)
+DevExtTramp(89)
+DevExtTramp(90)
+DevExtTramp(91)
+DevExtTramp(92)
+DevExtTramp(93)
+DevExtTramp(94)
+DevExtTramp(95)
+DevExtTramp(96)
+DevExtTramp(97)
+DevExtTramp(98)
+DevExtTramp(99)
+DevExtTramp(100)
+DevExtTramp(101)
+DevExtTramp(102)
+DevExtTramp(103)
+DevExtTramp(104)
+DevExtTramp(105)
+DevExtTramp(106)
+DevExtTramp(107)
+DevExtTramp(108)
+DevExtTramp(109)
+DevExtTramp(110)
+DevExtTramp(111)
+DevExtTramp(112)
+DevExtTramp(113)
+DevExtTramp(114)
+DevExtTramp(115)
+DevExtTramp(116)
+DevExtTramp(117)
+DevExtTramp(118)
+DevExtTramp(119)
+DevExtTramp(120)
+DevExtTramp(121)
+DevExtTramp(122)
+DevExtTramp(123)
+DevExtTramp(124)
+DevExtTramp(125)
+DevExtTramp(126)
+DevExtTramp(127)
+DevExtTramp(128)
+DevExtTramp(129)
+DevExtTramp(130)
+DevExtTramp(131)
+DevExtTramp(132)
+DevExtTramp(133)
+DevExtTramp(134)
+DevExtTramp(135)
+DevExtTramp(136)
+DevExtTramp(137)
+DevExtTramp(138)
+DevExtTramp(139)
+DevExtTramp(140)
+DevExtTramp(141)
+DevExtTramp(142)
+DevExtTramp(143)
+DevExtTramp(144)
+DevExtTramp(145)
+DevExtTramp(146)
+DevExtTramp(147)
+DevExtTramp(148)
+DevExtTramp(149)
+DevExtTramp(150)
+DevExtTramp(151)
+DevExtTramp(152)
+DevExtTramp(153)
+DevExtTramp(154)
+DevExtTramp(155)
+DevExtTramp(156)
+DevExtTramp(157)
+DevExtTramp(158)
+DevExtTramp(159)
+DevExtTramp(160)
+DevExtTramp(161)
+DevExtTramp(162)
+DevExtTramp(163)
+DevExtTramp(164)
+DevExtTramp(165)
+DevExtTramp(166)
+DevExtTramp(167)
+DevExtTramp(168)
+DevExtTramp(169)
+DevExtTramp(170)
+DevExtTramp(171)
+DevExtTramp(172)
+DevExtTramp(173)
+DevExtTramp(174)
+DevExtTramp(175)
+DevExtTramp(176)
+DevExtTramp(177)
+DevExtTramp(178)
+DevExtTramp(179)
+DevExtTramp(180)
+DevExtTramp(181)
+DevExtTramp(182)
+DevExtTramp(183)
+DevExtTramp(184)
+DevExtTramp(185)
+DevExtTramp(186)
+DevExtTramp(187)
+DevExtTramp(188)
+DevExtTramp(189)
+DevExtTramp(190)
+DevExtTramp(191)
+DevExtTramp(192)
+DevExtTramp(193)
+DevExtTramp(194)
+DevExtTramp(195)
+DevExtTramp(196)
+DevExtTramp(197)
+DevExtTramp(198)
+DevExtTramp(199)
+DevExtTramp(200)
+DevExtTramp(201)
+DevExtTramp(202)
+DevExtTramp(203)
+DevExtTramp(204)
+DevExtTramp(205)
+DevExtTramp(206)
+DevExtTramp(207)
+DevExtTramp(208)
+DevExtTramp(209)
+DevExtTramp(210)
+DevExtTramp(211)
+DevExtTramp(212)
+DevExtTramp(213)
+DevExtTramp(214)
+DevExtTramp(215)
+DevExtTramp(216)
+DevExtTramp(217)
+DevExtTramp(218)
+DevExtTramp(219)
+DevExtTramp(220)
+DevExtTramp(221)
+DevExtTramp(222)
+DevExtTramp(223)
+DevExtTramp(224)
+DevExtTramp(225)
+DevExtTramp(226)
+DevExtTramp(227)
+DevExtTramp(228)
+DevExtTramp(229)
+DevExtTramp(230)
+DevExtTramp(231)
+DevExtTramp(232)
+DevExtTramp(233)
+DevExtTramp(234)
+DevExtTramp(235)
+DevExtTramp(236)
+DevExtTramp(237)
+DevExtTramp(238)
+DevExtTramp(239)
+DevExtTramp(240)
+DevExtTramp(241)
+DevExtTramp(242)
+DevExtTramp(243)
+DevExtTramp(244)
+DevExtTramp(245)
+DevExtTramp(246)
+DevExtTramp(247)
+DevExtTramp(248)
+DevExtTramp(249)
void *loader_get_dev_ext_trampoline(uint32_t index) {
switch (index) {
- case 0:
- return vkdev_ext0;
- case 1:
- return vkdev_ext1;
- case 2:
- return vkdev_ext2;
- case 3:
- return vkdev_ext3;
- case 4:
- return vkdev_ext4;
- case 5:
- return vkdev_ext5;
- case 6:
- return vkdev_ext6;
- case 7:
- return vkdev_ext7;
- case 8:
- return vkdev_ext8;
- case 9:
- return vkdev_ext9;
- case 10:
- return vkdev_ext10;
- case 11:
- return vkdev_ext11;
- case 12:
- return vkdev_ext12;
- case 13:
- return vkdev_ext13;
- case 14:
- return vkdev_ext14;
- case 15:
- return vkdev_ext15;
- case 16:
- return vkdev_ext16;
- case 17:
- return vkdev_ext17;
- case 18:
- return vkdev_ext18;
- case 19:
- return vkdev_ext19;
- case 20:
- return vkdev_ext20;
- case 21:
- return vkdev_ext21;
- case 22:
- return vkdev_ext22;
- case 23:
- return vkdev_ext23;
- case 24:
- return vkdev_ext24;
- case 25:
- return vkdev_ext25;
- case 26:
- return vkdev_ext26;
- case 27:
- return vkdev_ext27;
- case 28:
- return vkdev_ext28;
- case 29:
- return vkdev_ext29;
- case 30:
- return vkdev_ext30;
- case 31:
- return vkdev_ext31;
- case 32:
- return vkdev_ext32;
- case 33:
- return vkdev_ext33;
- case 34:
- return vkdev_ext34;
- case 35:
- return vkdev_ext35;
- case 36:
- return vkdev_ext36;
- case 37:
- return vkdev_ext37;
- case 38:
- return vkdev_ext38;
- case 39:
- return vkdev_ext39;
- case 40:
- return vkdev_ext40;
- case 41:
- return vkdev_ext41;
- case 42:
- return vkdev_ext42;
- case 43:
- return vkdev_ext43;
- case 44:
- return vkdev_ext44;
- case 45:
- return vkdev_ext45;
- case 46:
- return vkdev_ext46;
- case 47:
- return vkdev_ext47;
- case 48:
- return vkdev_ext48;
- case 49:
- return vkdev_ext49;
- case 50:
- return vkdev_ext50;
- case 51:
- return vkdev_ext51;
- case 52:
- return vkdev_ext52;
- case 53:
- return vkdev_ext53;
- case 54:
- return vkdev_ext54;
- case 55:
- return vkdev_ext55;
- case 56:
- return vkdev_ext56;
- case 57:
- return vkdev_ext57;
- case 58:
- return vkdev_ext58;
- case 59:
- return vkdev_ext59;
- case 60:
- return vkdev_ext60;
- case 61:
- return vkdev_ext61;
- case 62:
- return vkdev_ext62;
- case 63:
- return vkdev_ext63;
- case 64:
- return vkdev_ext64;
- case 65:
- return vkdev_ext65;
- case 66:
- return vkdev_ext66;
- case 67:
- return vkdev_ext67;
- case 68:
- return vkdev_ext68;
- case 69:
- return vkdev_ext69;
- case 70:
- return vkdev_ext70;
- case 71:
- return vkdev_ext71;
- case 72:
- return vkdev_ext72;
- case 73:
- return vkdev_ext73;
- case 74:
- return vkdev_ext74;
- case 75:
- return vkdev_ext75;
- case 76:
- return vkdev_ext76;
- case 77:
- return vkdev_ext77;
- case 78:
- return vkdev_ext78;
- case 79:
- return vkdev_ext79;
- case 80:
- return vkdev_ext80;
- case 81:
- return vkdev_ext81;
- case 82:
- return vkdev_ext82;
- case 83:
- return vkdev_ext83;
- case 84:
- return vkdev_ext84;
- case 85:
- return vkdev_ext85;
- case 86:
- return vkdev_ext86;
- case 87:
- return vkdev_ext87;
- case 88:
- return vkdev_ext88;
- case 89:
- return vkdev_ext89;
- case 90:
- return vkdev_ext90;
- case 91:
- return vkdev_ext91;
- case 92:
- return vkdev_ext92;
- case 93:
- return vkdev_ext93;
- case 94:
- return vkdev_ext94;
- case 95:
- return vkdev_ext95;
- case 96:
- return vkdev_ext96;
- case 97:
- return vkdev_ext97;
- case 98:
- return vkdev_ext98;
- case 99:
- return vkdev_ext99;
- case 100:
- return vkdev_ext100;
- case 101:
- return vkdev_ext101;
- case 102:
- return vkdev_ext102;
- case 103:
- return vkdev_ext103;
- case 104:
- return vkdev_ext104;
- case 105:
- return vkdev_ext105;
- case 106:
- return vkdev_ext106;
- case 107:
- return vkdev_ext107;
- case 108:
- return vkdev_ext108;
- case 109:
- return vkdev_ext109;
- case 110:
- return vkdev_ext110;
- case 111:
- return vkdev_ext111;
- case 112:
- return vkdev_ext112;
- case 113:
- return vkdev_ext113;
- case 114:
- return vkdev_ext114;
- case 115:
- return vkdev_ext115;
- case 116:
- return vkdev_ext116;
- case 117:
- return vkdev_ext117;
- case 118:
- return vkdev_ext118;
- case 119:
- return vkdev_ext119;
- case 120:
- return vkdev_ext120;
- case 121:
- return vkdev_ext121;
- case 122:
- return vkdev_ext122;
- case 123:
- return vkdev_ext123;
- case 124:
- return vkdev_ext124;
- case 125:
- return vkdev_ext125;
- case 126:
- return vkdev_ext126;
- case 127:
- return vkdev_ext127;
- case 128:
- return vkdev_ext128;
- case 129:
- return vkdev_ext129;
- case 130:
- return vkdev_ext130;
- case 131:
- return vkdev_ext131;
- case 132:
- return vkdev_ext132;
- case 133:
- return vkdev_ext133;
- case 134:
- return vkdev_ext134;
- case 135:
- return vkdev_ext135;
- case 136:
- return vkdev_ext136;
- case 137:
- return vkdev_ext137;
- case 138:
- return vkdev_ext138;
- case 139:
- return vkdev_ext139;
- case 140:
- return vkdev_ext140;
- case 141:
- return vkdev_ext141;
- case 142:
- return vkdev_ext142;
- case 143:
- return vkdev_ext143;
- case 144:
- return vkdev_ext144;
- case 145:
- return vkdev_ext145;
- case 146:
- return vkdev_ext146;
- case 147:
- return vkdev_ext147;
- case 148:
- return vkdev_ext148;
- case 149:
- return vkdev_ext149;
- case 150:
- return vkdev_ext150;
- case 151:
- return vkdev_ext151;
- case 152:
- return vkdev_ext152;
- case 153:
- return vkdev_ext153;
- case 154:
- return vkdev_ext154;
- case 155:
- return vkdev_ext155;
- case 156:
- return vkdev_ext156;
- case 157:
- return vkdev_ext157;
- case 158:
- return vkdev_ext158;
- case 159:
- return vkdev_ext159;
- case 160:
- return vkdev_ext160;
- case 161:
- return vkdev_ext161;
- case 162:
- return vkdev_ext162;
- case 163:
- return vkdev_ext163;
- case 164:
- return vkdev_ext164;
- case 165:
- return vkdev_ext165;
- case 166:
- return vkdev_ext166;
- case 167:
- return vkdev_ext167;
- case 168:
- return vkdev_ext168;
- case 169:
- return vkdev_ext169;
- case 170:
- return vkdev_ext170;
- case 171:
- return vkdev_ext171;
- case 172:
- return vkdev_ext172;
- case 173:
- return vkdev_ext173;
- case 174:
- return vkdev_ext174;
- case 175:
- return vkdev_ext175;
- case 176:
- return vkdev_ext176;
- case 177:
- return vkdev_ext177;
- case 178:
- return vkdev_ext178;
- case 179:
- return vkdev_ext179;
- case 180:
- return vkdev_ext180;
- case 181:
- return vkdev_ext181;
- case 182:
- return vkdev_ext182;
- case 183:
- return vkdev_ext183;
- case 184:
- return vkdev_ext184;
- case 185:
- return vkdev_ext185;
- case 186:
- return vkdev_ext186;
- case 187:
- return vkdev_ext187;
- case 188:
- return vkdev_ext188;
- case 189:
- return vkdev_ext189;
- case 190:
- return vkdev_ext190;
- case 191:
- return vkdev_ext191;
- case 192:
- return vkdev_ext192;
- case 193:
- return vkdev_ext193;
- case 194:
- return vkdev_ext194;
- case 195:
- return vkdev_ext195;
- case 196:
- return vkdev_ext196;
- case 197:
- return vkdev_ext197;
- case 198:
- return vkdev_ext198;
- case 199:
- return vkdev_ext199;
- case 200:
- return vkdev_ext200;
- case 201:
- return vkdev_ext201;
- case 202:
- return vkdev_ext202;
- case 203:
- return vkdev_ext203;
- case 204:
- return vkdev_ext204;
- case 205:
- return vkdev_ext205;
- case 206:
- return vkdev_ext206;
- case 207:
- return vkdev_ext207;
- case 208:
- return vkdev_ext208;
- case 209:
- return vkdev_ext209;
- case 210:
- return vkdev_ext210;
- case 211:
- return vkdev_ext211;
- case 212:
- return vkdev_ext212;
- case 213:
- return vkdev_ext213;
- case 214:
- return vkdev_ext214;
- case 215:
- return vkdev_ext215;
- case 216:
- return vkdev_ext216;
- case 217:
- return vkdev_ext217;
- case 218:
- return vkdev_ext218;
- case 219:
- return vkdev_ext219;
- case 220:
- return vkdev_ext220;
- case 221:
- return vkdev_ext221;
- case 222:
- return vkdev_ext222;
- case 223:
- return vkdev_ext223;
- case 224:
- return vkdev_ext224;
- case 225:
- return vkdev_ext225;
- case 226:
- return vkdev_ext226;
- case 227:
- return vkdev_ext227;
- case 228:
- return vkdev_ext228;
- case 229:
- return vkdev_ext229;
- case 230:
- return vkdev_ext230;
- case 231:
- return vkdev_ext231;
- case 232:
- return vkdev_ext232;
- case 233:
- return vkdev_ext233;
- case 234:
- return vkdev_ext234;
- case 235:
- return vkdev_ext235;
- case 236:
- return vkdev_ext236;
- case 237:
- return vkdev_ext237;
- case 238:
- return vkdev_ext238;
- case 239:
- return vkdev_ext239;
- case 240:
- return vkdev_ext240;
- case 241:
- return vkdev_ext241;
- case 242:
- return vkdev_ext242;
- case 243:
- return vkdev_ext243;
- case 244:
- return vkdev_ext244;
- case 245:
- return vkdev_ext245;
- case 246:
- return vkdev_ext246;
- case 247:
- return vkdev_ext247;
- case 248:
- return vkdev_ext248;
- case 249:
- return vkdev_ext249;
+#define CASE_HANDLE(num) case num: return vkdev_ext##num
+ CASE_HANDLE(0);
+ CASE_HANDLE(1);
+ CASE_HANDLE(2);
+ CASE_HANDLE(3);
+ CASE_HANDLE(4);
+ CASE_HANDLE(5);
+ CASE_HANDLE(6);
+ CASE_HANDLE(7);
+ CASE_HANDLE(8);
+ CASE_HANDLE(9);
+ CASE_HANDLE(10);
+ CASE_HANDLE(11);
+ CASE_HANDLE(12);
+ CASE_HANDLE(13);
+ CASE_HANDLE(14);
+ CASE_HANDLE(15);
+ CASE_HANDLE(16);
+ CASE_HANDLE(17);
+ CASE_HANDLE(18);
+ CASE_HANDLE(19);
+ CASE_HANDLE(20);
+ CASE_HANDLE(21);
+ CASE_HANDLE(22);
+ CASE_HANDLE(23);
+ CASE_HANDLE(24);
+ CASE_HANDLE(25);
+ CASE_HANDLE(26);
+ CASE_HANDLE(27);
+ CASE_HANDLE(28);
+ CASE_HANDLE(29);
+ CASE_HANDLE(30);
+ CASE_HANDLE(31);
+ CASE_HANDLE(32);
+ CASE_HANDLE(33);
+ CASE_HANDLE(34);
+ CASE_HANDLE(35);
+ CASE_HANDLE(36);
+ CASE_HANDLE(37);
+ CASE_HANDLE(38);
+ CASE_HANDLE(39);
+ CASE_HANDLE(40);
+ CASE_HANDLE(41);
+ CASE_HANDLE(42);
+ CASE_HANDLE(43);
+ CASE_HANDLE(44);
+ CASE_HANDLE(45);
+ CASE_HANDLE(46);
+ CASE_HANDLE(47);
+ CASE_HANDLE(48);
+ CASE_HANDLE(49);
+ CASE_HANDLE(50);
+ CASE_HANDLE(51);
+ CASE_HANDLE(52);
+ CASE_HANDLE(53);
+ CASE_HANDLE(54);
+ CASE_HANDLE(55);
+ CASE_HANDLE(56);
+ CASE_HANDLE(57);
+ CASE_HANDLE(58);
+ CASE_HANDLE(59);
+ CASE_HANDLE(60);
+ CASE_HANDLE(61);
+ CASE_HANDLE(62);
+ CASE_HANDLE(63);
+ CASE_HANDLE(64);
+ CASE_HANDLE(65);
+ CASE_HANDLE(66);
+ CASE_HANDLE(67);
+ CASE_HANDLE(68);
+ CASE_HANDLE(69);
+ CASE_HANDLE(70);
+ CASE_HANDLE(71);
+ CASE_HANDLE(72);
+ CASE_HANDLE(73);
+ CASE_HANDLE(74);
+ CASE_HANDLE(75);
+ CASE_HANDLE(76);
+ CASE_HANDLE(77);
+ CASE_HANDLE(78);
+ CASE_HANDLE(79);
+ CASE_HANDLE(80);
+ CASE_HANDLE(81);
+ CASE_HANDLE(82);
+ CASE_HANDLE(83);
+ CASE_HANDLE(84);
+ CASE_HANDLE(85);
+ CASE_HANDLE(86);
+ CASE_HANDLE(87);
+ CASE_HANDLE(88);
+ CASE_HANDLE(89);
+ CASE_HANDLE(90);
+ CASE_HANDLE(91);
+ CASE_HANDLE(92);
+ CASE_HANDLE(93);
+ CASE_HANDLE(94);
+ CASE_HANDLE(95);
+ CASE_HANDLE(96);
+ CASE_HANDLE(97);
+ CASE_HANDLE(98);
+ CASE_HANDLE(99);
+ CASE_HANDLE(100);
+ CASE_HANDLE(101);
+ CASE_HANDLE(102);
+ CASE_HANDLE(103);
+ CASE_HANDLE(104);
+ CASE_HANDLE(105);
+ CASE_HANDLE(106);
+ CASE_HANDLE(107);
+ CASE_HANDLE(108);
+ CASE_HANDLE(109);
+ CASE_HANDLE(110);
+ CASE_HANDLE(111);
+ CASE_HANDLE(112);
+ CASE_HANDLE(113);
+ CASE_HANDLE(114);
+ CASE_HANDLE(115);
+ CASE_HANDLE(116);
+ CASE_HANDLE(117);
+ CASE_HANDLE(118);
+ CASE_HANDLE(119);
+ CASE_HANDLE(120);
+ CASE_HANDLE(121);
+ CASE_HANDLE(122);
+ CASE_HANDLE(123);
+ CASE_HANDLE(124);
+ CASE_HANDLE(125);
+ CASE_HANDLE(126);
+ CASE_HANDLE(127);
+ CASE_HANDLE(128);
+ CASE_HANDLE(129);
+ CASE_HANDLE(130);
+ CASE_HANDLE(131);
+ CASE_HANDLE(132);
+ CASE_HANDLE(133);
+ CASE_HANDLE(134);
+ CASE_HANDLE(135);
+ CASE_HANDLE(136);
+ CASE_HANDLE(137);
+ CASE_HANDLE(138);
+ CASE_HANDLE(139);
+ CASE_HANDLE(140);
+ CASE_HANDLE(141);
+ CASE_HANDLE(142);
+ CASE_HANDLE(143);
+ CASE_HANDLE(144);
+ CASE_HANDLE(145);
+ CASE_HANDLE(146);
+ CASE_HANDLE(147);
+ CASE_HANDLE(148);
+ CASE_HANDLE(149);
+ CASE_HANDLE(150);
+ CASE_HANDLE(151);
+ CASE_HANDLE(152);
+ CASE_HANDLE(153);
+ CASE_HANDLE(154);
+ CASE_HANDLE(155);
+ CASE_HANDLE(156);
+ CASE_HANDLE(157);
+ CASE_HANDLE(158);
+ CASE_HANDLE(159);
+ CASE_HANDLE(160);
+ CASE_HANDLE(161);
+ CASE_HANDLE(162);
+ CASE_HANDLE(163);
+ CASE_HANDLE(164);
+ CASE_HANDLE(165);
+ CASE_HANDLE(166);
+ CASE_HANDLE(167);
+ CASE_HANDLE(168);
+ CASE_HANDLE(169);
+ CASE_HANDLE(170);
+ CASE_HANDLE(171);
+ CASE_HANDLE(172);
+ CASE_HANDLE(173);
+ CASE_HANDLE(174);
+ CASE_HANDLE(175);
+ CASE_HANDLE(176);
+ CASE_HANDLE(177);
+ CASE_HANDLE(178);
+ CASE_HANDLE(179);
+ CASE_HANDLE(180);
+ CASE_HANDLE(181);
+ CASE_HANDLE(182);
+ CASE_HANDLE(183);
+ CASE_HANDLE(184);
+ CASE_HANDLE(185);
+ CASE_HANDLE(186);
+ CASE_HANDLE(187);
+ CASE_HANDLE(188);
+ CASE_HANDLE(189);
+ CASE_HANDLE(190);
+ CASE_HANDLE(191);
+ CASE_HANDLE(192);
+ CASE_HANDLE(193);
+ CASE_HANDLE(194);
+ CASE_HANDLE(195);
+ CASE_HANDLE(196);
+ CASE_HANDLE(197);
+ CASE_HANDLE(198);
+ CASE_HANDLE(199);
+ CASE_HANDLE(200);
+ CASE_HANDLE(201);
+ CASE_HANDLE(202);
+ CASE_HANDLE(203);
+ CASE_HANDLE(204);
+ CASE_HANDLE(205);
+ CASE_HANDLE(206);
+ CASE_HANDLE(207);
+ CASE_HANDLE(208);
+ CASE_HANDLE(209);
+ CASE_HANDLE(210);
+ CASE_HANDLE(211);
+ CASE_HANDLE(212);
+ CASE_HANDLE(213);
+ CASE_HANDLE(214);
+ CASE_HANDLE(215);
+ CASE_HANDLE(216);
+ CASE_HANDLE(217);
+ CASE_HANDLE(218);
+ CASE_HANDLE(219);
+ CASE_HANDLE(220);
+ CASE_HANDLE(221);
+ CASE_HANDLE(222);
+ CASE_HANDLE(223);
+ CASE_HANDLE(224);
+ CASE_HANDLE(225);
+ CASE_HANDLE(226);
+ CASE_HANDLE(227);
+ CASE_HANDLE(228);
+ CASE_HANDLE(229);
+ CASE_HANDLE(230);
+ CASE_HANDLE(231);
+ CASE_HANDLE(232);
+ CASE_HANDLE(233);
+ CASE_HANDLE(234);
+ CASE_HANDLE(235);
+ CASE_HANDLE(236);
+ CASE_HANDLE(237);
+ CASE_HANDLE(238);
+ CASE_HANDLE(239);
+ CASE_HANDLE(240);
+ CASE_HANDLE(241);
+ CASE_HANDLE(242);
+ CASE_HANDLE(243);
+ CASE_HANDLE(244);
+ CASE_HANDLE(245);
+ CASE_HANDLE(246);
+ CASE_HANDLE(247);
+ CASE_HANDLE(248);
+ CASE_HANDLE(249);
}
+
return NULL;
}
diff --git a/loader/extensions.c b/loader/extensions.c
index e135644e..221924a9 100644
--- a/loader/extensions.c
+++ b/loader/extensions.c
@@ -25,9 +25,258 @@
#include "vk_loader_platform.h"
#include "loader.h"
#include "extensions.h"
+#include "table_ops.h"
#include <vulkan/vk_icd.h>
#include "wsi.h"
+// Definitions for the VK_KHR_get_physical_device_properties2 extension
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures2KHR(
+ VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR *pFeatures) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceFeatures2KHR(unwrapped_phys_dev, pFeatures);
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures2KHR(
+ VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR *pFeatures) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->GetPhysicalDeviceFeatures2KHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkGetPhysicalDeviceFeatures2KHR");
+ }
+ icd_term->GetPhysicalDeviceFeatures2KHR(phys_dev_term->phys_dev, pFeatures);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2KHR *pProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceProperties2KHR(unwrapped_phys_dev, pProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2KHR *pProperties) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->GetPhysicalDeviceProperties2KHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkGetPhysicalDeviceProperties2KHR");
+ }
+ icd_term->GetPhysicalDeviceProperties2KHR(phys_dev_term->phys_dev,
+ pProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice, VkFormat format,
+ VkFormatProperties2KHR *pFormatProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceFormatProperties2KHR(unwrapped_phys_dev, format,
+ pFormatProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice, VkFormat format,
+ VkFormatProperties2KHR *pFormatProperties) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->GetPhysicalDeviceFormatProperties2KHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkGetPhysicalDeviceFormatProperties2KHR");
+ }
+ icd_term->GetPhysicalDeviceFormatProperties2KHR(phys_dev_term->phys_dev,
+ format, pFormatProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
+ VkImageFormatProperties2KHR *pImageFormatProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceImageFormatProperties2KHR(
+ unwrapped_phys_dev, pImageFormatInfo, pImageFormatProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_GetPhysicalDeviceImageFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
+ VkImageFormatProperties2KHR *pImageFormatProperties) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->GetPhysicalDeviceImageFormatProperties2KHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkGetPhysicalDeviceImageFormatProperties2KHR");
+ }
+ return icd_term->GetPhysicalDeviceImageFormatProperties2KHR(
+ phys_dev_term->phys_dev, pImageFormatInfo, pImageFormatProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties2KHR(
+ VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceQueueFamilyProperties2KHR(
+ unwrapped_phys_dev, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+terminator_GetPhysicalDeviceQueueFamilyProperties2KHR(
+ VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->GetPhysicalDeviceQueueFamilyProperties2KHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkGetPhysicalDeviceQueueFamilyProperties2KHR");
+ }
+ icd_term->GetPhysicalDeviceQueueFamilyProperties2KHR(
+ phys_dev_term->phys_dev, pQueueFamilyPropertyCount,
+ pQueueFamilyProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceMemoryProperties2KHR(unwrapped_phys_dev,
+ pMemoryProperties);
+}
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->GetPhysicalDeviceMemoryProperties2KHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkGetPhysicalDeviceMemoryProperties2KHR");
+ }
+ icd_term->GetPhysicalDeviceMemoryProperties2KHR(phys_dev_term->phys_dev,
+ pMemoryProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2KHR *pFormatInfo,
+ uint32_t *pPropertyCount, VkSparseImageFormatProperties2KHR *pProperties) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ disp->GetPhysicalDeviceSparseImageFormatProperties2KHR(
+ unwrapped_phys_dev, pFormatInfo, pPropertyCount, pProperties);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+terminator_GetPhysicalDeviceSparseImageFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2KHR *pFormatInfo,
+ uint32_t *pPropertyCount, VkSparseImageFormatProperties2KHR *pProperties) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->GetPhysicalDeviceSparseImageFormatProperties2KHR) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
+ }
+ icd_term->GetPhysicalDeviceSparseImageFormatProperties2KHR(
+ phys_dev_term->phys_dev, pFormatInfo, pPropertyCount, pProperties);
+}
+
+// Definitions for the VK_KHR_maintenance1 extension
+
+VKAPI_ATTR void VKAPI_CALL
+vkTrimCommandPoolKHR(VkDevice device, VkCommandPool commandPool,
+ VkCommandPoolTrimFlagsKHR flags) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(device);
+ disp->TrimCommandPoolKHR(device, commandPool, flags);
+}
+
+// Definitions for the VK_EXT_acquire_xlib_display extension
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireXlibDisplayEXT(
+ VkPhysicalDevice physicalDevice, Display *dpy, VkDisplayKHR display) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->AcquireXlibDisplayEXT(unwrapped_phys_dev, dpy, display);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_AcquireXlibDisplayEXT(
+ VkPhysicalDevice physicalDevice, Display *dpy, VkDisplayKHR display) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->AcquireXlibDisplayEXT) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkAcquireXlibDisplayEXT");
+ }
+ return icd_term->AcquireXlibDisplayEXT(phys_dev_term->phys_dev, dpy,
+ display);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vkGetRandROutputDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy,
+ RROutput rrOutput, VkDisplayKHR *pDisplay) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetRandROutputDisplayEXT(unwrapped_phys_dev, dpy, rrOutput,
+ pDisplay);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetRandROutputDisplayEXT(
+ VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
+ VkDisplayKHR *pDisplay) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->GetRandROutputDisplayEXT) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkGetRandROutputDisplayEXT");
+ }
+ return icd_term->GetRandROutputDisplayEXT(phys_dev_term->phys_dev, dpy,
+ rrOutput, pDisplay);
+}
+#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
+
// Definitions for the VK_EXT_debug_marker extension commands which
// need to have a terminator function
@@ -130,9 +379,96 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectNameEXT(
}
}
+// Definitions for the VK_EXT_direct_mode_display extension
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vkReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->ReleaseDisplayEXT(unwrapped_phys_dev, display);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(
+ VkPhysicalDevice physicalDevice, VkDisplayKHR display) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL == icd_term->ReleaseDisplayEXT) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkReleaseDisplayEXT");
+ }
+ return icd_term->ReleaseDisplayEXT(phys_dev_term->phys_dev, display);
+}
+
+// Definitions for the VK_EXT_display_surface_counter extension
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilities2EXT(
+ VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
+ VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
+ const VkLayerInstanceDispatchTable *disp;
+ VkPhysicalDevice unwrapped_phys_dev =
+ loader_unwrap_physical_device(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
+ return disp->GetPhysicalDeviceSurfaceCapabilities2EXT(
+ unwrapped_phys_dev, surface, pSurfaceCapabilities);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_GetPhysicalDeviceSurfaceCapabilities2EXT(
+ VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
+ VkSurfaceCapabilities2EXT *pSurfaceCapabilities) {
+ struct loader_physical_device_term *phys_dev_term =
+ (struct loader_physical_device_term *)physicalDevice;
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
+ if (NULL != icd_term) {
+ if (NULL == icd_term->GetPhysicalDeviceSurfaceCapabilities2EXT) {
+ loader_log(icd_term->this_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ 0,
+ "ICD associated with VkPhysicalDevice does not support "
+ "vkGetPhysicalDeviceSurfaceCapabilities2EXT");
+ }
+ VkIcdSurface *icd_surface = (VkIcdSurface *)(surface);
+ uint8_t icd_index = phys_dev_term->icd_index;
+ if (NULL != icd_surface->real_icd_surfaces) {
+ if (NULL != (void *)icd_surface->real_icd_surfaces[icd_index]) {
+ return icd_term->GetPhysicalDeviceSurfaceCapabilities2EXT(
+ phys_dev_term->phys_dev,
+ icd_surface->real_icd_surfaces[icd_index],
+ pSurfaceCapabilities);
+ }
+ }
+ }
+ return icd_term->GetPhysicalDeviceSurfaceCapabilities2EXT(
+ phys_dev_term->phys_dev, surface, pSurfaceCapabilities);
+}
+
+// Definitions for the VK_AMD_draw_indirect_count extension
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD(
+ VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
+ VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
+ uint32_t stride) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawIndirectCountAMD(commandBuffer, buffer, offset, countBuffer,
+ countBufferOffset, maxDrawCount, stride);
+}
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD(
+ VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
+ VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
+ uint32_t stride) {
+ const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
+ disp->CmdDrawIndexedIndirectCountAMD(commandBuffer, buffer, offset,
+ countBuffer, countBufferOffset,
+ maxDrawCount, stride);
+}
+
// Definitions for the VK_NV_external_memory_capabilities extension
-LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+VKAPI_ATTR VkResult VKAPI_CALL
vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
@@ -141,7 +477,7 @@ vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
return disp->GetPhysicalDeviceExternalImageFormatPropertiesNV(
unwrapped_phys_dev, format, type, tiling, usage, flags,
@@ -181,27 +517,6 @@ terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV(
externalHandleType, pExternalImageFormatProperties);
}
-// Definitions for the VK_AMD_draw_indirect_count extension
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirectCountAMD(
- VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
- VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
- uint32_t stride) {
- const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
- disp->CmdDrawIndirectCountAMD(commandBuffer, buffer, offset, countBuffer,
- countBufferOffset, maxDrawCount, stride);
-}
-
-VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirectCountAMD(
- VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset,
- VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount,
- uint32_t stride) {
- const VkLayerDispatchTable *disp = loader_get_dispatch(commandBuffer);
- disp->CmdDrawIndexedIndirectCountAMD(commandBuffer, buffer, offset,
- countBuffer, countBufferOffset,
- maxDrawCount, stride);
-}
-
#ifdef VK_USE_PLATFORM_WIN32_KHR
// Definitions for the VK_NV_external_memory_win32 extension
@@ -288,7 +603,7 @@ VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
disp->GetPhysicalDeviceGeneratedCommandsPropertiesNVX(unwrapped_phys_dev,
pFeatures, pLimits);
}
@@ -311,12 +626,94 @@ terminator_GetPhysicalDeviceGeneratedCommandsPropertiesNVX(
}
}
-// GPA helpers for non-KHR extensions
+// GPA helpers for extensions
bool extension_instance_gpa(struct loader_instance *ptr_instance,
const char *name, void **addr) {
*addr = NULL;
+ // Functions for the VK_KHR_get_physical_device_properties2 extension
+
+ if (!strcmp("vkGetPhysicalDeviceFeatures2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions
+ .khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceFeatures2KHR
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions
+ .khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceProperties2KHR
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceFormatProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions
+ .khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceFormatProperties2KHR
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceImageFormatProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions
+ .khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceImageFormatProperties2KHR
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceQueueFamilyProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions
+ .khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceQueueFamilyProperties2KHR
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceMemoryProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions
+ .khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceMemoryProperties2KHR
+ : NULL;
+ return true;
+ }
+ if (!strcmp("vkGetPhysicalDeviceSparseImageFormatProperties2KHR", name)) {
+ *addr = (ptr_instance->enabled_known_extensions
+ .khr_get_physical_device_properties2 == 1)
+ ? (void *)vkGetPhysicalDeviceSparseImageFormatProperties2KHR
+ : NULL;
+ return true;
+ }
+
+ // Functions for the VK_KHR_maintenance1 extension
+
+ if (!strcmp("vkTrimCommandPoolKHR", name)) {
+ *addr = (void *)vkTrimCommandPoolKHR;
+ return true;
+ }
+
+// Functions for the VK_EXT_acquire_xlib_display extension
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ if (!strcmp("vkAcquireXlibDisplayEXT", name)) {
+ *addr =
+ (ptr_instance->enabled_known_extensions.ext_acquire_xlib_display ==
+ 1)
+ ? (void *)vkAcquireXlibDisplayEXT
+ : NULL;
+ return true;
+ }
+
+ if (!strcmp("vkGetRandROutputDisplayEXT", name)) {
+ *addr =
+ (ptr_instance->enabled_known_extensions.ext_acquire_xlib_display ==
+ 1)
+ ? (void *)vkGetRandROutputDisplayEXT
+ : NULL;
+ return true;
+ }
+
+#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
+
// Definitions for the VK_EXT_debug_marker extension commands which
// need to have a terminator function. Since these are device
// commands, we always need to return a valid value for them.
@@ -330,12 +727,23 @@ bool extension_instance_gpa(struct loader_instance *ptr_instance,
return true;
}
- // Functions for the VK_NV_external_memory_capabilities extension
+ // Functions for the VK_EXT_direct_mode_display extension
- if (!strcmp("vkGetPhysicalDeviceExternalImageFormatPropertiesNV", name)) {
+ if (!strcmp("vkReleaseDisplayEXT", name)) {
+ *addr =
+ (ptr_instance->enabled_known_extensions.ext_direct_mode_display ==
+ 1)
+ ? (void *)vkReleaseDisplayEXT
+ : NULL;
+ return true;
+ }
+
+ // Functions for the VK_EXT_display_surface_counter extension
+
+ if (!strcmp("vkGetPhysicalDeviceSurfaceCapabilities2EXT", name)) {
*addr = (ptr_instance->enabled_known_extensions
- .nv_external_memory_capabilities == 1)
- ? (void *)vkGetPhysicalDeviceExternalImageFormatPropertiesNV
+ .ext_display_surface_counter == 1)
+ ? (void *)vkGetPhysicalDeviceSurfaceCapabilities2EXT
: NULL;
return true;
}
@@ -346,16 +754,23 @@ bool extension_instance_gpa(struct loader_instance *ptr_instance,
*addr = (void *)vkCmdDrawIndirectCountAMD;
return true;
}
-
if (!strcmp("vkCmdDrawIndexedIndirectCountAMD", name)) {
*addr = (void *)vkCmdDrawIndexedIndirectCountAMD;
return true;
}
+ // Functions for the VK_NV_external_memory_capabilities extension
+
+ if (!strcmp("vkGetPhysicalDeviceExternalImageFormatPropertiesNV", name)) {
+ *addr = (ptr_instance->enabled_known_extensions
+ .nv_external_memory_capabilities == 1)
+ ? (void *)vkGetPhysicalDeviceExternalImageFormatPropertiesNV
+ : NULL;
+ return true;
+ }
#ifdef VK_USE_PLATFORM_WIN32_KHR
// Functions for the VK_NV_external_memory_win32 extension
-
if (!strcmp("vkGetMemoryWin32HandleNV", name)) {
*addr = (void *)vkGetMemoryWin32HandleNV;
return true;
@@ -407,14 +822,29 @@ bool extension_instance_gpa(struct loader_instance *ptr_instance,
void extensions_create_instance(struct loader_instance *ptr_instance,
const VkInstanceCreateInfo *pCreateInfo) {
- ptr_instance->enabled_known_extensions.nv_external_memory_capabilities = 0;
-
for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
- if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
- VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME) == 0) {
+ if (0 ==
+ strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+ VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions
+ .khr_get_physical_device_properties2 = 1;
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+ VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.ext_acquire_xlib_display = 1;
+#endif
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+ VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.ext_direct_mode_display = 1;
+ } else if (0 == strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+ VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME)) {
+ ptr_instance->enabled_known_extensions.ext_display_surface_counter =
+ 1;
+ } else if (0 ==
+ strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+ VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
ptr_instance->enabled_known_extensions
.nv_external_memory_capabilities = 1;
- return;
}
}
}
diff --git a/loader/extensions.h b/loader/extensions.h
index 71759650..b94aaf90 100644
--- a/loader/extensions.h
+++ b/loader/extensions.h
@@ -28,8 +28,69 @@ bool extension_instance_gpa(struct loader_instance *ptr_instance,
void extensions_create_instance(struct loader_instance *ptr_instance,
const VkInstanceCreateInfo *pCreateInfo);
-// Definitions for the VK_EXT_debug_marker extension
+// Instance extension terminators for the VK_KHR_get_physical_device_properties2
+// extension
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFeatures2KHR(
+ VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR *pFeatures);
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2KHR *pProperties);
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice, VkFormat format,
+ VkFormatProperties2KHR *pFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_GetPhysicalDeviceImageFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
+ VkImageFormatProperties2KHR *pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL
+terminator_GetPhysicalDeviceQueueFamilyProperties2KHR(
+ VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties2KHR *pQueueFamilyProperties);
+
+VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceMemoryProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties);
+
+VKAPI_ATTR void VKAPI_CALL
+terminator_GetPhysicalDeviceSparseImageFormatProperties2KHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceSparseImageFormatInfo2KHR *pFormatInfo,
+ uint32_t *pPropertyCount, VkSparseImageFormatProperties2KHR *pProperties);
+
+// Instance extension terminators for the VK_EXT_acquire_xlib_display
+// extension
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+VKAPI_ATTR VkResult VKAPI_CALL terminator_AcquireXlibDisplayEXT(
+ VkPhysicalDevice physicalDevice, Display *dpy, VkDisplayKHR display);
+
+VKAPI_ATTR VkResult VKAPI_CALL terminator_GetRandROutputDisplayEXT(
+ VkPhysicalDevice physicalDevice, Display *dpy, RROutput rrOutput,
+ VkDisplayKHR *pDisplay);
+#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
+
+// Instance extension terminators for the VK_EXT_direct_mode_display
+// extension
+VKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(
+ VkPhysicalDevice physicalDevice, VkDisplayKHR display);
+
+// Instance extension terminators for the VK_EXT_display_surface_counter
+// extension
+
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_GetPhysicalDeviceSurfaceCapabilities2EXT(
+ VkPhysicalDevice physicalDevice, VkSurfaceKHR surface,
+ VkSurfaceCapabilities2EXT *pSurfaceCapabilities);
+
+// Device extension terminators for the VK_NV_external_memory_capabilities
+// extension
VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectTagEXT(
VkDevice device, VkDebugMarkerObjectTagInfoEXT *pTagInfo);
@@ -37,7 +98,8 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectTagEXT(
VKAPI_ATTR VkResult VKAPI_CALL terminator_DebugMarkerSetObjectNameEXT(
VkDevice device, VkDebugMarkerObjectNameInfoEXT *pNameInfo);
-// Definitions for the VK_NV_external_memory_capabilities extension
+// Instance extension terminators for the VK_NV_external_memory_capabilities
+// extension
VKAPI_ATTR VkResult VKAPI_CALL
terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV(
diff --git a/loader/get_proc_addr.png b/loader/get_proc_addr.png
deleted file mode 100644
index a11c1648..00000000
--- a/loader/get_proc_addr.png
+++ /dev/null
Binary files differ
diff --git a/loader/gpa_helper.h b/loader/gpa_helper.h
index 5089b592..c7e7ba2d 100644
--- a/loader/gpa_helper.h
+++ b/loader/gpa_helper.h
@@ -308,6 +308,11 @@ static inline void *trampolineGetProcAddr(struct loader_instance *inst,
if (extension_instance_gpa(inst, funcName, &addr))
return addr;
+ // Unknown physical device extensions
+ if (loader_phys_dev_ext_gpa(inst, funcName, true, &addr, NULL))
+ return addr;
+
+ // Unknown device extensions
addr = loader_dev_ext_gpa(inst, funcName);
return addr;
}
@@ -327,36 +332,6 @@ static inline void *globalGetProcAddr(const char *name) {
return NULL;
}
-/* These functions require special handling by the loader.
-* They are not just generic trampoline code entrypoints.
-* Thus GPA must return loader entrypoint for these instead of first function
-* in the chain. */
-static inline void *loader_non_passthrough_gipa(const char *name) {
- if (!name || name[0] != 'v' || name[1] != 'k')
- return NULL;
-
- name += 2;
- if (!strcmp(name, "CreateInstance"))
- return (void *)vkCreateInstance;
- if (!strcmp(name, "DestroyInstance"))
- return (void *)vkDestroyInstance;
- if (!strcmp(name, "GetDeviceProcAddr"))
- return (void *)vkGetDeviceProcAddr;
- // remove once no longer locks
- if (!strcmp(name, "EnumeratePhysicalDevices"))
- return (void *)vkEnumeratePhysicalDevices;
- if (!strcmp(name, "EnumerateDeviceExtensionProperties"))
- return (void *)vkEnumerateDeviceExtensionProperties;
- if (!strcmp(name, "EnumerateDeviceLayerProperties"))
- return (void *)vkEnumerateDeviceLayerProperties;
- if (!strcmp(name, "GetInstanceProcAddr"))
- return (void *)vkGetInstanceProcAddr;
- if (!strcmp(name, "CreateDevice"))
- return (void *)vkCreateDevice;
-
- return NULL;
-}
-
static inline void *loader_non_passthrough_gdpa(const char *name) {
if (!name || name[0] != 'v' || name[1] != 'k')
return NULL;
diff --git a/loader/images/function_device_chain.png b/loader/images/function_device_chain.png
new file mode 100644
index 00000000..62ba7a3d
--- /dev/null
+++ b/loader/images/function_device_chain.png
Binary files differ
diff --git a/loader/images/function_device_chain_white.png b/loader/images/function_device_chain_white.png
new file mode 100644
index 00000000..b6107a89
--- /dev/null
+++ b/loader/images/function_device_chain_white.png
Binary files differ
diff --git a/loader/images/function_instance_chain.png b/loader/images/function_instance_chain.png
new file mode 100644
index 00000000..b79fd969
--- /dev/null
+++ b/loader/images/function_instance_chain.png
Binary files differ
diff --git a/loader/images/function_instance_chain_white.png b/loader/images/function_instance_chain_white.png
new file mode 100644
index 00000000..48705a2a
--- /dev/null
+++ b/loader/images/function_instance_chain_white.png
Binary files differ
diff --git a/loader/images/high_level_loader.png b/loader/images/high_level_loader.png
new file mode 100644
index 00000000..391abb7d
--- /dev/null
+++ b/loader/images/high_level_loader.png
Binary files differ
diff --git a/loader/images/high_level_loader_white.png b/loader/images/high_level_loader_white.png
new file mode 100644
index 00000000..c83cade1
--- /dev/null
+++ b/loader/images/high_level_loader_white.png
Binary files differ
diff --git a/loader/images/loader_device_chain_app.png b/loader/images/loader_device_chain_app.png
new file mode 100644
index 00000000..764fcd6e
--- /dev/null
+++ b/loader/images/loader_device_chain_app.png
Binary files differ
diff --git a/loader/images/loader_device_chain_app_white.png b/loader/images/loader_device_chain_app_white.png
new file mode 100644
index 00000000..8bd28ee0
--- /dev/null
+++ b/loader/images/loader_device_chain_app_white.png
Binary files differ
diff --git a/loader/images/loader_device_chain_loader.png b/loader/images/loader_device_chain_loader.png
new file mode 100644
index 00000000..d226a3e9
--- /dev/null
+++ b/loader/images/loader_device_chain_loader.png
Binary files differ
diff --git a/loader/images/loader_device_chain_loader_white.png b/loader/images/loader_device_chain_loader_white.png
new file mode 100644
index 00000000..993a5551
--- /dev/null
+++ b/loader/images/loader_device_chain_loader_white.png
Binary files differ
diff --git a/loader/images/loader_instance_chain.png b/loader/images/loader_instance_chain.png
new file mode 100644
index 00000000..8bc06d09
--- /dev/null
+++ b/loader/images/loader_instance_chain.png
Binary files differ
diff --git a/loader/images/loader_instance_chain_white.png b/loader/images/loader_instance_chain_white.png
new file mode 100644
index 00000000..4c3c0664
--- /dev/null
+++ b/loader/images/loader_instance_chain_white.png
Binary files differ
diff --git a/loader/images/loader_layer_order.png b/loader/images/loader_layer_order.png
new file mode 100644
index 00000000..80b9ea4a
--- /dev/null
+++ b/loader/images/loader_layer_order.png
Binary files differ
diff --git a/loader/images/loader_layer_order_white.png b/loader/images/loader_layer_order_white.png
new file mode 100644
index 00000000..ed25dc97
--- /dev/null
+++ b/loader/images/loader_layer_order_white.png
Binary files differ
diff --git a/loader/instance_call_chain.png b/loader/instance_call_chain.png
deleted file mode 100644
index 848b726d..00000000
--- a/loader/instance_call_chain.png
+++ /dev/null
Binary files differ
diff --git a/loader/loader.c b/loader/loader.c
index 351bf2ec..24758f4a 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -1,8 +1,8 @@
/*
*
- * Copyright (c) 2014-2016 The Khronos Group Inc.
- * Copyright (c) 2014-2016 Valve Corporation
- * Copyright (c) 2014-2016 LunarG, Inc.
+ * Copyright (c) 2014-2017 The Khronos Group Inc.
+ * Copyright (c) 2014-2017 Valve Corporation
+ * Copyright (c) 2014-2017 LunarG, Inc.
* Copyright (C) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,6 +20,7 @@
*
* Author: Jon Ashburn <jon@lunarg.com>
* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
+ * Author: Mark Young <marky@lunarg.com>
*
*/
@@ -115,11 +116,6 @@ const VkLayerInstanceDispatchTable instance_disp = {
terminator_GetPhysicalDeviceSurfaceFormatsKHR,
.GetPhysicalDeviceSurfacePresentModesKHR =
terminator_GetPhysicalDeviceSurfacePresentModesKHR,
- .CreateDebugReportCallbackEXT = terminator_CreateDebugReportCallback,
- .DestroyDebugReportCallbackEXT = terminator_DestroyDebugReportCallback,
- .DebugReportMessageEXT = terminator_DebugReportMessage,
- .GetPhysicalDeviceExternalImageFormatPropertiesNV =
- terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV,
#ifdef VK_USE_PLATFORM_MIR_KHR
.CreateMirSurfaceKHR = terminator_CreateMirSurfaceKHR,
.GetPhysicalDeviceMirPresentationSupportKHR =
@@ -159,6 +155,43 @@ const VkLayerInstanceDispatchTable instance_disp = {
.GetDisplayPlaneCapabilitiesKHR = terminator_GetDisplayPlaneCapabilitiesKHR,
.CreateDisplayPlaneSurfaceKHR = terminator_CreateDisplayPlaneSurfaceKHR,
+ // KHR_get_physical_device_properties2
+ .GetPhysicalDeviceFeatures2KHR = terminator_GetPhysicalDeviceFeatures2KHR,
+ .GetPhysicalDeviceProperties2KHR =
+ terminator_GetPhysicalDeviceProperties2KHR,
+ .GetPhysicalDeviceFormatProperties2KHR =
+ terminator_GetPhysicalDeviceFormatProperties2KHR,
+ .GetPhysicalDeviceImageFormatProperties2KHR =
+ terminator_GetPhysicalDeviceImageFormatProperties2KHR,
+ .GetPhysicalDeviceQueueFamilyProperties2KHR =
+ terminator_GetPhysicalDeviceQueueFamilyProperties2KHR,
+ .GetPhysicalDeviceMemoryProperties2KHR =
+ terminator_GetPhysicalDeviceMemoryProperties2KHR,
+ .GetPhysicalDeviceSparseImageFormatProperties2KHR =
+ terminator_GetPhysicalDeviceSparseImageFormatProperties2KHR,
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ // EXT_acquire_xlib_display
+ .AcquireXlibDisplayEXT = terminator_AcquireXlibDisplayEXT,
+ .GetRandROutputDisplayEXT = terminator_GetRandROutputDisplayEXT,
+#endif
+
+ // EXT_debug_report
+ .CreateDebugReportCallbackEXT = terminator_CreateDebugReportCallback,
+ .DestroyDebugReportCallbackEXT = terminator_DestroyDebugReportCallback,
+ .DebugReportMessageEXT = terminator_DebugReportMessage,
+
+ // EXT_direct_mode_display
+ .ReleaseDisplayEXT = terminator_ReleaseDisplayEXT,
+
+ // EXT_display_surface_counter
+ .GetPhysicalDeviceSurfaceCapabilities2EXT =
+ terminator_GetPhysicalDeviceSurfaceCapabilities2EXT,
+
+ // NV_external_memory_capabilities
+ .GetPhysicalDeviceExternalImageFormatPropertiesNV =
+ terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV,
+
// NVX_device_generated_commands
.GetPhysicalDeviceGeneratedCommandsPropertiesNVX =
terminator_GetPhysicalDeviceGeneratedCommandsPropertiesNVX,
@@ -187,9 +220,18 @@ static const char *const LOADER_INSTANCE_EXTENSIONS[] = {
#ifdef VK_USE_PLATFORM_WIN32_KHR
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
#endif
+ VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME,
+#endif
VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
- VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+ VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME,
+ VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME,
VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME,
+#ifdef VK_USE_PLATFORM_VI_NN
+ VK_NN_VI_SURFACE_EXTENSION_NAME,
+#endif
+ VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
NULL};
LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
@@ -844,6 +886,10 @@ static VkResult loader_add_instance_extensions(
}
ext_props = loader_stack_alloc(count * sizeof(VkExtensionProperties));
+ if (NULL == ext_props) {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto out;
+ }
res = fp_get_props(NULL, &count, ext_props);
if (res != VK_SUCCESS) {
@@ -1424,9 +1470,9 @@ loader_get_icd_and_device(const VkDevice device,
dev = dev->next)
// Value comparison of device prevents object wrapping by layers
if (loader_get_dispatch(dev->icd_device) ==
- loader_get_dispatch(device) ||
+ loader_get_dispatch(device) ||
loader_get_dispatch(dev->chain_device) ==
- loader_get_dispatch(device)) {
+ loader_get_dispatch(device)) {
*found_dev = dev;
if (NULL != icd_index) {
*icd_index = index;
@@ -1568,10 +1614,6 @@ loader_icd_add(struct loader_instance *ptr_inst,
* the negotiation API is not supported by the ICD
* @return bool indicating true if the selected interface version is supported
* by the loader, false indicates the version is not supported
- * version 0 doesn't support vk_icdGetInstanceProcAddr nor
- * vk_icdNegotiateLoaderICDInterfaceVersion
- * version 1 supports vk_icdGetInstanceProcAddr
- * version 2 supports vk_icdNegotiateLoaderICDInterfaceVersion
*/
bool loader_get_icd_interface_version(
PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version,
@@ -1645,6 +1687,7 @@ loader_scanned_icd_add(const struct loader_instance *inst,
PFN_vkCreateInstance fp_create_inst;
PFN_vkEnumerateInstanceExtensionProperties fp_get_inst_ext_props;
PFN_vkGetInstanceProcAddr fp_get_proc_addr;
+ PFN_GetPhysicalDeviceProcAddr fp_get_phys_dev_proc_addr = NULL;
PFN_vkNegotiateLoaderICDInterfaceVersion fp_negotiate_icd_version;
struct loader_scanned_icd *new_scanned_icd;
uint32_t interface_vers;
@@ -1715,8 +1758,9 @@ loader_scanned_icd_add(const struct loader_instance *inst,
}
} else {
// Use newer interface version 1 or later
- if (interface_vers == 0)
+ if (interface_vers == 0) {
interface_vers = 1;
+ }
fp_create_inst =
(PFN_vkCreateInstance)fp_get_proc_addr(NULL, "vkCreateInstance");
@@ -1739,6 +1783,8 @@ loader_scanned_icd_add(const struct loader_instance *inst,
filename);
goto out;
}
+ fp_get_phys_dev_proc_addr =
+ loader_platform_get_proc_address(handle, "vk_icdGetPhysicalDeviceProcAddr");
}
// check for enough capacity
@@ -1759,11 +1805,12 @@ loader_scanned_icd_add(const struct loader_instance *inst,
// double capacity
icd_tramp_list->capacity *= 2;
}
- new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]);
+ new_scanned_icd = &(icd_tramp_list->scanned_list[icd_tramp_list->count]);
new_scanned_icd->handle = handle;
new_scanned_icd->api_version = api_version;
new_scanned_icd->GetInstanceProcAddr = fp_get_proc_addr;
+ new_scanned_icd->GetPhysicalDeviceProcAddr = fp_get_phys_dev_proc_addr;
new_scanned_icd->EnumerateInstanceExtensionProperties =
fp_get_inst_ext_props;
new_scanned_icd->CreateInstance = fp_create_inst;
@@ -1814,10 +1861,6 @@ static bool loader_icd_init_entrys(struct loader_icd_term *icd_term,
LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties, true);
LOOKUP_GIPA(EnumerateDeviceExtensionProperties, true);
LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties, true);
- LOOKUP_GIPA(CreateDebugReportCallbackEXT, false);
- LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false);
- LOOKUP_GIPA(DebugMarkerSetObjectTagEXT, false);
- LOOKUP_GIPA(DebugMarkerSetObjectNameEXT, false);
LOOKUP_GIPA(GetPhysicalDeviceSurfaceSupportKHR, false);
LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilitiesKHR, false);
LOOKUP_GIPA(GetPhysicalDeviceSurfaceFormatsKHR, false);
@@ -1851,6 +1894,37 @@ static bool loader_icd_init_entrys(struct loader_icd_term *icd_term,
LOOKUP_GIPA(CreateWaylandSurfaceKHR, false);
LOOKUP_GIPA(GetPhysicalDeviceWaylandPresentationSupportKHR, false);
#endif
+ LOOKUP_GIPA(CreateSharedSwapchainsKHR, false);
+
+ // KHR_get_physical_device_properties2
+ LOOKUP_GIPA(GetPhysicalDeviceFeatures2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceFormatProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceImageFormatProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceQueueFamilyProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceMemoryProperties2KHR, false);
+ LOOKUP_GIPA(GetPhysicalDeviceSparseImageFormatProperties2KHR, false);
+ // EXT_debug_marker (items needing a trampoline/terminator)
+ LOOKUP_GIPA(DebugMarkerSetObjectTagEXT, false);
+ LOOKUP_GIPA(DebugMarkerSetObjectNameEXT, false);
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ // EXT_acquire_xlib_display
+ LOOKUP_GIPA(AcquireXlibDisplayEXT, false);
+ LOOKUP_GIPA(GetRandROutputDisplayEXT, false);
+#endif
+
+ // EXT_debug_report
+ LOOKUP_GIPA(CreateDebugReportCallbackEXT, false);
+ LOOKUP_GIPA(DestroyDebugReportCallbackEXT, false);
+ LOOKUP_GIPA(DebugReportMessageEXT, false);
+
+ // EXT_direct_mode_display
+ LOOKUP_GIPA(ReleaseDisplayEXT, false);
+
+ // EXT_display_surface_counter
+ LOOKUP_GIPA(GetPhysicalDeviceSurfaceCapabilities2EXT, false);
+
// NV_external_memory_capabilities
LOOKUP_GIPA(GetPhysicalDeviceExternalImageFormatPropertiesNV, false);
// NVX_device_generated_commands
@@ -2324,10 +2398,20 @@ static void loader_add_layer_property_meta(
}
}
-static void loader_read_json_layer(
- const struct loader_instance *inst,
- struct loader_layer_list *layer_instance_list, cJSON *layer_node,
- cJSON *item, cJSON *disable_environment, bool is_implicit, char *filename) {
+// This structure is used to store the json file version
+// in a more managable way.
+typedef struct {
+ uint16_t major;
+ uint16_t minor;
+ uint16_t patch;
+} layer_json_version;
+
+static void
+loader_read_json_layer(const struct loader_instance *inst,
+ struct loader_layer_list *layer_instance_list,
+ cJSON *layer_node, layer_json_version version,
+ cJSON *item, cJSON *disable_environment,
+ bool is_implicit, char *filename) {
char *temp;
char *name, *type, *library_path, *api_version;
char *implementation_version, *description;
@@ -2394,7 +2478,7 @@ static void loader_read_json_layer(
#undef GET_JSON_ITEM
#undef GET_JSON_OBJECT
- // add list entry
+ // Add list entry
struct loader_layer_properties *props = NULL;
if (!strcmp(type, "DEVICE")) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
@@ -2429,13 +2513,13 @@ static void loader_read_json_layer(
char *fullpath = props->lib_name;
char *rel_base;
if (loader_platform_is_path(library_path)) {
- // a relative or absolute path
+ // A relative or absolute path
char *name_copy = loader_stack_alloc(strlen(filename) + 1);
strcpy(name_copy, filename);
rel_base = loader_platform_dirname(name_copy);
loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
} else {
- // a filename which is assumed in a system directory
+ // A filename which is assumed in a system directory
loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH,
MAX_STRING_SIZE, fullpath);
}
@@ -2489,40 +2573,69 @@ static void loader_read_json_layer(
cJSON *instance_extensions, *device_extensions, *functions,
*enable_environment;
- cJSON *entrypoints;
- char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
- char **entry_array;
- vkGetInstanceProcAddr = NULL;
- vkGetDeviceProcAddr = NULL;
- spec_version = NULL;
+ cJSON *entrypoints = NULL;
+ char *vkGetInstanceProcAddr = NULL;
+ char *vkGetDeviceProcAddr = NULL;
+ char *vkNegotiateLoaderLayerInterfaceVersion = NULL;
+ char *spec_version = NULL;
+ char **entry_array = NULL;
entrypoints = NULL;
- entry_array = NULL;
int i, j;
- /**
- * functions
- * vkGetInstanceProcAddr
- * vkGetDeviceProcAddr
- */
+ // Layer interface functions
+ // vkGetInstanceProcAddr
+ // vkGetDeviceProcAddr
+ // vkNegotiateLoaderLayerInterfaceVersion (starting with JSON file 1.1.0)
GET_JSON_OBJECT(layer_node, functions)
if (functions != NULL) {
+ if (version.major > 1 || version.minor >= 1) {
+ GET_JSON_ITEM(functions, vkNegotiateLoaderLayerInterfaceVersion)
+ if (vkNegotiateLoaderLayerInterfaceVersion != NULL)
+ strncpy(props->functions.str_negotiate_interface,
+ vkNegotiateLoaderLayerInterfaceVersion,
+ sizeof(props->functions.str_negotiate_interface));
+ props->functions.str_negotiate_interface
+ [sizeof(props->functions.str_negotiate_interface) - 1] = '\0';
+ } else {
+ props->functions.str_negotiate_interface[0] = '\0';
+ }
GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
- if (vkGetInstanceProcAddr != NULL)
+ if (vkGetInstanceProcAddr != NULL) {
strncpy(props->functions.str_gipa, vkGetInstanceProcAddr,
sizeof(props->functions.str_gipa));
+ if (version.major > 1 || version.minor >= 1) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Indicating layer-specific vkGetInstanceProcAddr "
+ "function is deprecated starting with JSON file "
+ "version 1.1.0. Instead, use the new "
+ "vkNegotiateLayerInterfaceVersion function to "
+ "return the GetInstanceProcAddr function for this"
+ "layer");
+ }
+ }
props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] = '\0';
- if (vkGetDeviceProcAddr != NULL)
+ if (vkGetDeviceProcAddr != NULL) {
strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr,
sizeof(props->functions.str_gdpa));
+ if (version.major > 1 || version.minor >= 1) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Indicating layer-specific vkGetDeviceProcAddr "
+ "function is deprecated starting with JSON file "
+ "version 1.1.0. Instead, use the new "
+ "vkNegotiateLayerInterfaceVersion function to "
+ "return the GetDeviceProcAddr function for this"
+ "layer");
+ }
+ }
props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] = '\0';
}
- /**
- * instance_extensions
- * array of
- * name
- * spec_version
- */
+
+ // instance_extensions
+ // array of {
+ // name
+ // spec_version
+ // }
GET_JSON_OBJECT(layer_node, instance_extensions)
if (instance_extensions != NULL) {
int count = cJSON_GetArraySize(instance_extensions);
@@ -2549,13 +2662,13 @@ static void loader_read_json_layer(
}
}
}
- /**
- * device_extensions
- * array of
- * name
- * spec_version
- * entrypoints
- */
+
+ // device_extensions
+ // array of {
+ // name
+ // spec_version
+ // entrypoints
+ // }
GET_JSON_OBJECT(layer_node, device_extensions)
if (device_extensions != NULL) {
int count = cJSON_GetArraySize(device_extensions);
@@ -2626,6 +2739,23 @@ static void loader_read_json_layer(
#undef GET_JSON_OBJECT
}
+static inline bool is_valid_layer_json_version(const layer_json_version *layer_json) {
+ // Supported versions are: 1.0.0, 1.0.1, and 1.1.0.
+ if ((layer_json->major == 1 && layer_json->minor == 1 && layer_json->patch == 0) ||
+ (layer_json->major == 1 && layer_json->minor == 0 && layer_json->patch < 2)) {
+ return true;
+ }
+ return false;
+}
+
+static inline bool layer_json_supports_layers_tag(const layer_json_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
@@ -2641,19 +2771,13 @@ static void
loader_add_layer_properties(const struct loader_instance *inst,
struct loader_layer_list *layer_instance_list,
cJSON *json, bool is_implicit, char *filename) {
- /* Fields in layer manifest file that are required:
- * (required) “file_format_version”
- *
- * If more than one "layer" object are to be used, use the "layers" array
- * instead.
- *
- * First get all required items and if any missing abort
- */
+ // The following Fields in layer manifest file that are required:
+ // - “file_format_version”
+ // - If more than one "layer" object are used, then the "layers" array is
+ // requred
cJSON *item, *layers_node, *layer_node;
- uint16_t file_major_vers = 0;
- uint16_t file_minor_vers = 0;
- uint16_t file_patch_vers = 0;
+ layer_json_version json_version;
char *vers_tok;
cJSON *disable_environment = NULL;
item = cJSON_GetObjectItem(json, "file_format_version");
@@ -2669,30 +2793,31 @@ loader_add_layer_properties(const struct loader_instance *inst,
// Get the major/minor/and patch as integers for easier comparison
vers_tok = strtok(file_vers, ".\"\n\r");
if (NULL != vers_tok) {
- file_major_vers = (uint16_t)atoi(vers_tok);
+ json_version.major = (uint16_t)atoi(vers_tok);
vers_tok = strtok(NULL, ".\"\n\r");
if (NULL != vers_tok) {
- file_minor_vers = (uint16_t)atoi(vers_tok);
+ json_version.minor = (uint16_t)atoi(vers_tok);
vers_tok = strtok(NULL, ".\"\n\r");
if (NULL != vers_tok) {
- file_patch_vers = (uint16_t)atoi(vers_tok);
+ json_version.patch = (uint16_t)atoi(vers_tok);
}
}
}
- if (file_major_vers != 1 || file_minor_vers != 0 || file_patch_vers > 1) {
+
+ if (!is_valid_layer_json_version(&json_version)) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
- "loader_add_layer_properties: Unexpected manifest file "
- "version (expected 1.0.0 or 1.0.1) in %s, may cause "
- "errors",
- filename);
+ "loader_add_layer_properties: %s invalid layer "
+ " manifest file version %d.%d.%d. May cause errors.",
+ filename, json_version.major, json_version.minor,
+ json_version.patch);
}
cJSON_Free(file_vers);
+
// If "layers" is present, read in the array of layer objects
layers_node = cJSON_GetObjectItem(json, "layers");
if (layers_node != NULL) {
int numItems = cJSON_GetArraySize(layers_node);
- if (file_major_vers == 1 && file_minor_vers == 0 &&
- file_patch_vers == 0) {
+ if (!layer_json_supports_layers_tag(&json_version)) {
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
"loader_add_layer_properties: \'layers\' tag not "
"supported until file version 1.0.1, but %s is "
@@ -2709,8 +2834,9 @@ loader_add_layer_properties(const struct loader_instance *inst,
curLayer, filename);
return;
}
- loader_read_json_layer(inst, layer_instance_list, layer_node, item,
- disable_environment, is_implicit, filename);
+ loader_read_json_layer(inst, layer_instance_list, layer_node,
+ json_version, item, disable_environment,
+ is_implicit, filename);
}
} else {
// Otherwise, try to read in individual layers
@@ -2730,14 +2856,11 @@ loader_add_layer_properties(const struct loader_instance *inst,
tempNode = tempNode->next;
layer_count++;
} while (tempNode != NULL);
- /*
- * 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 &&
- (file_major_vers > 1 ||
- !(file_minor_vers == 0 && file_patch_vers == 0))) {
+
+ // 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_layers_tag(&json_version)) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"loader_add_layer_properties: Multiple \'layer\' nodes"
" are deprecated starting in file version \"1.0.1\". "
@@ -2746,8 +2869,8 @@ loader_add_layer_properties(const struct loader_instance *inst,
} else {
do {
loader_read_json_layer(inst, layer_instance_list, layer_node,
- item, disable_environment, is_implicit,
- filename);
+ json_version, item, disable_environment,
+ is_implicit, filename);
layer_node = layer_node->next;
} while (layer_node != NULL);
}
@@ -2788,7 +2911,7 @@ loader_get_manifest_files(const struct loader_instance *inst,
bool is_layer, bool warn_if_not_present,
const char *location, const char *home_location,
struct loader_manifest_files *out_files) {
- const char *override = NULL;
+ const char * override = NULL;
char *override_getenv = NULL;
char *loc, *orig_loc = NULL;
char *reg = NULL;
@@ -3138,8 +3261,8 @@ VkResult loader_icd_scan(const struct loader_instance *inst,
}
// Get a list of manifest files for ICDs
- res = loader_get_manifest_files(inst, "VK_ICD_FILENAMES", NULL, false,
- true, DEFAULT_VK_DRIVERS_INFO,
+ res = loader_get_manifest_files(inst, "VK_ICD_FILENAMES", NULL, false, true,
+ DEFAULT_VK_DRIVERS_INFO,
HOME_VK_DRIVERS_INFO, &manifest_files);
if (VK_SUCCESS != res || manifest_files.count == 0) {
goto out;
@@ -3487,13 +3610,82 @@ void loader_implicit_layer_scan(const struct loader_instance *inst,
}
static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
+loader_gpdpa_instance_internal(VkInstance inst, const char *pName) {
+ // inst is not wrapped
+ if (inst == VK_NULL_HANDLE) {
+ return NULL;
+ }
+ VkLayerInstanceDispatchTable *disp_table =
+ *(VkLayerInstanceDispatchTable **)inst;
+ void *addr;
+
+ if (disp_table == NULL)
+ return NULL;
+
+ bool found_name;
+ addr =
+ loader_lookup_instance_dispatch_table(disp_table, pName, &found_name);
+ if (found_name) {
+ return addr;
+ }
+
+ if (loader_phys_dev_ext_gpa(loader_get_instance(inst), pName, true, NULL, &addr))
+ return addr;
+
+ // Don't call down the chain, this would be an infinite loop
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_gpdpa_instance_internal() unrecognized name %s", pName);
+ return NULL;
+}
+
+static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
+loader_gpdpa_instance_terminator(VkInstance inst, const char *pName) {
+ // inst is not wrapped
+ if (inst == VK_NULL_HANDLE) {
+ return NULL;
+ }
+ VkLayerInstanceDispatchTable *disp_table =
+ *(VkLayerInstanceDispatchTable **)inst;
+ void *addr;
+
+ if (disp_table == NULL)
+ return NULL;
+
+ bool found_name;
+ addr =
+ loader_lookup_instance_dispatch_table(disp_table, pName, &found_name);
+ if (found_name) {
+ return addr;
+ }
+
+ // Get the terminator, but don't perform checking since it should already
+ // have been setup if we get here.
+ if (loader_phys_dev_ext_gpa(loader_get_instance(inst), pName, false, NULL,
+ &addr)) {
+ return addr;
+ }
+
+ // Don't call down the chain, this would be an infinite loop
+ loader_log(NULL, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "loader_gpdpa_instance_terminator() unrecognized name %s",
+ pName);
+ return NULL;
+}
+
+static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
loader_gpa_instance_internal(VkInstance inst, const char *pName) {
- if (!strcmp(pName, "vkGetInstanceProcAddr"))
- return (void *)loader_gpa_instance_internal;
- if (!strcmp(pName, "vkCreateInstance"))
- return (void *)terminator_CreateInstance;
- if (!strcmp(pName, "vkCreateDevice"))
- return (void *)terminator_CreateDevice;
+ if (!strcmp(pName, "vkGetInstanceProcAddr")) {
+ return (PFN_vkVoidFunction)loader_gpa_instance_internal;
+ }
+ if (!strcmp(pName, "vk_layerGetPhysicalDeviceProcAddr")) {
+ return (PFN_vkVoidFunction)loader_gpdpa_instance_terminator;
+ }
+ if (!strcmp(pName, "vkCreateInstance")) {
+ return (PFN_vkVoidFunction)terminator_CreateInstance;
+ }
+ if (!strcmp(pName, "vkCreateDevice")) {
+ return (PFN_vkVoidFunction)terminator_CreateDevice;
+ }
// inst is not wrapped
if (inst == VK_NULL_HANDLE) {
@@ -3537,6 +3729,8 @@ loader_gpa_device_internal(VkDevice device, const char *pName) {
return (PFN_vkVoidFunction)loader_gpa_device_internal;
} else if (!strcmp(pName, "vkCreateSwapchainKHR")) {
return (PFN_vkVoidFunction)terminator_vkCreateSwapchainKHR;
+ } else if (!strcmp(pName, "vkCreateSharedSwapchainsKHR")) {
+ return (PFN_vkVoidFunction)terminator_vkCreateSharedSwapchainsKHR;
} else if (!strcmp(pName, "vkDebugMarkerSetObjectTagEXT")) {
return (PFN_vkVoidFunction)terminator_DebugMarkerSetObjectTagEXT;
} else if (!strcmp(pName, "vkDebugMarkerSetObjectNameEXT")) {
@@ -3592,15 +3786,15 @@ static void loader_init_dispatch_dev_ext_entry(struct loader_instance *inst,
*/
void loader_init_dispatch_dev_ext(struct loader_instance *inst,
struct loader_device *dev) {
- for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
- if (inst->disp_hash[i].func_name != NULL)
+ for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) {
+ if (inst->dev_ext_disp_hash[i].func_name != NULL)
loader_init_dispatch_dev_ext_entry(inst, dev, i,
- inst->disp_hash[i].func_name);
+ inst->dev_ext_disp_hash[i].func_name);
}
}
-static bool loader_check_icds_for_address(struct loader_instance *inst,
- const char *funcName) {
+static bool loader_check_icds_for_dev_ext_address(struct loader_instance *inst,
+ const char *funcName) {
struct loader_icd_term *icd_term;
icd_term = inst->icd_terms;
while (NULL != icd_term) {
@@ -3614,7 +3808,7 @@ static bool loader_check_icds_for_address(struct loader_instance *inst,
return false;
}
-static bool loader_check_layer_list_for_address(
+static bool loader_check_layer_list_for_dev_ext_address(
const struct loader_layer_list *const layers, const char *funcName) {
// Iterate over the layers.
for (uint32_t layer = 0; layer < layers->count; ++layer) {
@@ -3639,32 +3833,35 @@ static bool loader_check_layer_list_for_address(
}
static void loader_free_dev_ext_table(struct loader_instance *inst) {
- for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++) {
- loader_instance_heap_free(inst, inst->disp_hash[i].func_name);
- loader_instance_heap_free(inst, inst->disp_hash[i].list.index);
+ for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) {
+ loader_instance_heap_free(inst, inst->dev_ext_disp_hash[i].func_name);
+ loader_instance_heap_free(inst, inst->dev_ext_disp_hash[i].list.index);
}
- memset(inst->disp_hash, 0, sizeof(inst->disp_hash));
+ memset(inst->dev_ext_disp_hash, 0, sizeof(inst->dev_ext_disp_hash));
}
static bool loader_add_dev_ext_table(struct loader_instance *inst,
uint32_t *ptr_idx, const char *funcName) {
uint32_t i;
uint32_t idx = *ptr_idx;
- struct loader_dispatch_hash_list *list = &inst->disp_hash[idx].list;
+ struct loader_dispatch_hash_list *list = &inst->dev_ext_disp_hash[idx].list;
- if (!inst->disp_hash[idx].func_name) {
+ if (!inst->dev_ext_disp_hash[idx].func_name) {
// no entry here at this idx, so use it
assert(list->capacity == 0);
- inst->disp_hash[idx].func_name = (char *)loader_instance_heap_alloc(
- inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
- if (inst->disp_hash[idx].func_name == NULL) {
+ inst->dev_ext_disp_hash[idx].func_name =
+ (char *)loader_instance_heap_alloc(
+ inst, strlen(funcName) + 1,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (inst->dev_ext_disp_hash[idx].func_name == NULL) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"loader_add_dev_ext_table: Failed to allocate memory "
"for func_name %s",
funcName);
return false;
}
- strncpy(inst->disp_hash[idx].func_name, funcName, strlen(funcName) + 1);
+ strncpy(inst->dev_ext_disp_hash[idx].func_name, funcName,
+ strlen(funcName) + 1);
return true;
}
@@ -3696,14 +3893,15 @@ static bool loader_add_dev_ext_table(struct loader_instance *inst,
}
// find an unused index in the hash table and use it
- i = (idx + 1) % MAX_NUM_DEV_EXTS;
+ i = (idx + 1) % MAX_NUM_UNKNOWN_EXTS;
do {
- if (!inst->disp_hash[i].func_name) {
- assert(inst->disp_hash[i].list.capacity == 0);
- inst->disp_hash[i].func_name = (char *)loader_instance_heap_alloc(
- inst, strlen(funcName) + 1,
- VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
- if (inst->disp_hash[i].func_name == NULL) {
+ if (!inst->dev_ext_disp_hash[i].func_name) {
+ assert(inst->dev_ext_disp_hash[i].list.capacity == 0);
+ inst->dev_ext_disp_hash[i].func_name =
+ (char *)loader_instance_heap_alloc(
+ inst, strlen(funcName) + 1,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (inst->dev_ext_disp_hash[i].func_name == NULL) {
loader_log(
inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"loader_add_dev_ext_table: Failed to allocate memory "
@@ -3711,14 +3909,14 @@ static bool loader_add_dev_ext_table(struct loader_instance *inst,
funcName);
return false;
}
- strncpy(inst->disp_hash[i].func_name, funcName,
+ strncpy(inst->dev_ext_disp_hash[i].func_name, funcName,
strlen(funcName) + 1);
list->index[list->count] = i;
list->count++;
*ptr_idx = i;
return true;
}
- i = (i + 1) % MAX_NUM_DEV_EXTS;
+ i = (i + 1) % MAX_NUM_UNKNOWN_EXTS;
} while (i != idx);
loader_log(
@@ -3732,16 +3930,15 @@ static bool loader_add_dev_ext_table(struct loader_instance *inst,
static bool loader_name_in_dev_ext_table(struct loader_instance *inst,
uint32_t *idx, const char *funcName) {
uint32_t alt_idx;
- if (inst->disp_hash[*idx].func_name &&
- !strcmp(inst->disp_hash[*idx].func_name, funcName))
+ if (inst->dev_ext_disp_hash[*idx].func_name &&
+ !strcmp(inst->dev_ext_disp_hash[*idx].func_name, funcName))
return true;
// funcName wasn't at the primary spot in the hash table
// search the list of secondary locations (shallow search, not deep search)
- for (uint32_t i = 0; i < inst->disp_hash[*idx].list.count; i++) {
- alt_idx = inst->disp_hash[*idx].list.index[i];
- if (inst->disp_hash[*idx].func_name &&
- !strcmp(inst->disp_hash[*idx].func_name, funcName)) {
+ for (uint32_t i = 0; i < inst->dev_ext_disp_hash[*idx].list.count; i++) {
+ alt_idx = inst->dev_ext_disp_hash[*idx].list.index[i];
+ if (!strcmp(inst->dev_ext_disp_hash[*idx].func_name, funcName)) {
*idx = alt_idx;
return true;
}
@@ -3772,16 +3969,15 @@ void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) {
uint32_t idx;
uint32_t seed = 0;
- idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_DEV_EXTS;
+ idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_UNKNOWN_EXTS;
if (loader_name_in_dev_ext_table(inst, &idx, funcName))
// found funcName already in hash
return loader_get_dev_ext_trampoline(idx);
// Check if funcName is supported in either ICDs or a layer library
- if (!loader_check_icds_for_address(inst, funcName) &&
- !loader_check_layer_list_for_address(&inst->instance_layer_list,
- funcName)) {
+ if (!loader_check_icds_for_dev_ext_address(inst, funcName) &&
+ !loader_check_layer_list_for_dev_ext_address(&inst->instance_layer_list, funcName)) {
// if support found in layers continue on
return NULL;
}
@@ -3796,6 +3992,275 @@ void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName) {
return NULL;
}
+static bool
+loader_check_icds_for_phys_dev_ext_address(struct loader_instance *inst,
+ const char *funcName) {
+ struct loader_icd_term *icd_term;
+ icd_term = inst->icd_terms;
+ while (NULL != icd_term) {
+ if (icd_term->scanned_icd->interface_version >=
+ MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION &&
+ icd_term->scanned_icd->GetPhysicalDeviceProcAddr(icd_term->instance,
+ funcName))
+ // this icd supports funcName
+ return true;
+ icd_term = icd_term->next;
+ }
+
+ return false;
+}
+
+static bool
+loader_check_layer_list_for_phys_dev_ext_address(struct loader_instance *inst,
+ const char *funcName) {
+ struct loader_layer_properties *layer_prop_list =
+ inst->activated_layer_list.list;
+ for (uint32_t layer = 0; layer < inst->activated_layer_list.count; ++layer) {
+ // If this layer supports the vk_layerGetPhysicalDeviceProcAddr, then call
+ // it and see if it returns a valid pointer for this function name.
+ if (layer_prop_list[layer].interface_version > 1) {
+ const struct loader_layer_functions *const functions =
+ &(layer_prop_list[layer].functions);
+ if (NULL != functions->get_physical_device_proc_addr &&
+ NULL !=
+ functions->get_physical_device_proc_addr((VkInstance)inst,
+ funcName)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+static void loader_free_phys_dev_ext_table(struct loader_instance *inst) {
+ for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++) {
+ loader_instance_heap_free(inst,
+ inst->phys_dev_ext_disp_hash[i].func_name);
+ loader_instance_heap_free(inst,
+ inst->phys_dev_ext_disp_hash[i].list.index);
+ }
+ memset(inst->phys_dev_ext_disp_hash, 0,
+ sizeof(inst->phys_dev_ext_disp_hash));
+}
+
+static bool loader_add_phys_dev_ext_table(struct loader_instance *inst,
+ uint32_t *ptr_idx,
+ const char *funcName) {
+ uint32_t i;
+ uint32_t idx = *ptr_idx;
+ struct loader_dispatch_hash_list *list =
+ &inst->phys_dev_ext_disp_hash[idx].list;
+
+ if (!inst->phys_dev_ext_disp_hash[idx].func_name) {
+ // no entry here at this idx, so use it
+ assert(list->capacity == 0);
+ inst->phys_dev_ext_disp_hash[idx].func_name =
+ (char *)loader_instance_heap_alloc(
+ inst, strlen(funcName) + 1,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (inst->phys_dev_ext_disp_hash[idx].func_name == NULL) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_phys_dev_ext_table() can't allocate memory for "
+ "func_name");
+ return false;
+ }
+ strncpy(inst->phys_dev_ext_disp_hash[idx].func_name, funcName,
+ strlen(funcName) + 1);
+ return true;
+ }
+
+ // check for enough capacity
+ if (list->capacity == 0) {
+ list->index =
+ loader_instance_heap_alloc(inst, 8 * sizeof(*(list->index)),
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (list->index == NULL) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_phys_dev_ext_table() can't allocate list memory");
+ return false;
+ }
+ list->capacity = 8 * sizeof(*(list->index));
+ } else if (list->capacity < (list->count + 1) * sizeof(*(list->index))) {
+ list->index = loader_instance_heap_realloc(
+ inst, list->index, list->capacity, list->capacity * 2,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (list->index == NULL) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_phys_dev_ext_table() can't reallocate list memory");
+ return false;
+ }
+ list->capacity *= 2;
+ }
+
+ // find an unused index in the hash table and use it
+ i = (idx + 1) % MAX_NUM_UNKNOWN_EXTS;
+ do {
+ if (!inst->phys_dev_ext_disp_hash[i].func_name) {
+ assert(inst->phys_dev_ext_disp_hash[i].list.capacity == 0);
+ inst->phys_dev_ext_disp_hash[i].func_name =
+ (char *)loader_instance_heap_alloc(
+ inst, strlen(funcName) + 1,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (inst->phys_dev_ext_disp_hash[i].func_name == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_dev_ext_table() can't rallocate "
+ "func_name memory");
+ return false;
+ }
+ strncpy(inst->phys_dev_ext_disp_hash[i].func_name, funcName,
+ strlen(funcName) + 1);
+ list->index[list->count] = i;
+ list->count++;
+ *ptr_idx = i;
+ return true;
+ }
+ i = (i + 1) % MAX_NUM_UNKNOWN_EXTS;
+ } while (i != idx);
+
+ loader_log(
+ inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_add_phys_dev_ext_table() couldn't insert into hash table; is "
+ "it full?");
+ return false;
+}
+
+static bool loader_name_in_phys_dev_ext_table(struct loader_instance* inst,
+ uint32_t *idx, const char *funcName) {
+ uint32_t alt_idx;
+ if (inst->phys_dev_ext_disp_hash[*idx].func_name &&
+ !strcmp(inst->phys_dev_ext_disp_hash[*idx].func_name, funcName))
+ return true;
+
+ // funcName wasn't at the primary spot in the hash table
+ // search the list of secondary locations (shallow search, not deep search)
+ for (uint32_t i = 0; i < inst->phys_dev_ext_disp_hash[*idx].list.count;
+ i++) {
+ alt_idx = inst->phys_dev_ext_disp_hash[*idx].list.index[i];
+ if (!strcmp(inst->phys_dev_ext_disp_hash[*idx].func_name, funcName)) {
+ *idx = alt_idx;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// This function returns a generic trampoline and/or terminator function
+// address for any unknown physical device extension commands. A hash
+// table is used to keep a list of unknown entry points and their
+// mapping to the physical device extension dispatch table (struct
+// loader_phys_dev_ext_dispatch_table).
+// For a given entry point string (funcName), if an existing mapping is
+// found, then the trampoline address for that mapping is returned in
+// tramp_addr (if it is not NULL) and the terminator address for that
+// mapping is returned in term_addr (if it is not NULL). Otherwise,
+// this unknown entry point has not been seen yet.
+// If it has not been seen before, and perform_checking is 'true',
+// check if a layer or and ICD supports it. If so then a new entry in
+// the hash table is initialized and the trampoline and/or terminator
+// addresses are returned.
+// Null is returned if the hash table is full or if no discovered layer or
+// ICD returns a non-NULL GetProcAddr for it.
+bool loader_phys_dev_ext_gpa(struct loader_instance *inst, const char *funcName,
+ bool perform_checking, void **tramp_addr,
+ void **term_addr) {
+ uint32_t idx;
+ uint32_t seed = 0;
+ bool success = false;
+
+ if (inst == NULL) {
+ goto out;
+ }
+
+ if (NULL != tramp_addr) {
+ *tramp_addr = NULL;
+ }
+ if (NULL != term_addr) {
+ *term_addr = NULL;
+ }
+
+ // We should always check to see if any ICD supports it.
+ if (!loader_check_icds_for_phys_dev_ext_address(inst, funcName)) {
+ // If we're not checking layers, or we are and it's not in a layer, just
+ // return
+ if (!perform_checking ||
+ !loader_check_layer_list_for_phys_dev_ext_address(inst, funcName)) {
+ goto out;
+ }
+ }
+
+ idx = murmurhash(funcName, strlen(funcName), seed) % MAX_NUM_UNKNOWN_EXTS;
+ if (perform_checking &&
+ !loader_name_in_phys_dev_ext_table(inst, &idx, funcName)) {
+ uint32_t i;
+ bool added = false;
+
+ // Only need to add first one to get index in Instance. Others will use
+ // the same index.
+ if (!added && loader_add_phys_dev_ext_table(inst, &idx, funcName)) {
+ added = true;
+ }
+
+ // Setup the ICD function pointers
+ struct loader_icd_term *icd_term = inst->icd_terms;
+ while (NULL != icd_term) {
+ if (MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION <=
+ icd_term->scanned_icd->interface_version &&
+ NULL != icd_term->scanned_icd->GetPhysicalDeviceProcAddr) {
+ icd_term->phys_dev_ext[idx] =
+ (PFN_PhysDevExt)
+ icd_term->scanned_icd->GetPhysicalDeviceProcAddr(
+ icd_term->instance, funcName);
+
+ // Make sure we set the instance dispatch to point to the
+ // loader's terminator now since we can at least handle it
+ // in one ICD.
+ inst->disp->phys_dev_ext[idx] =
+ loader_get_phys_dev_ext_termin(idx);
+ } else {
+ icd_term->phys_dev_ext[idx] = NULL;
+ }
+
+ icd_term = icd_term->next;
+ }
+
+ // Now, search for the first layer attached and query using it to get
+ // the first entry point.
+ for (i = 0; i < inst->activated_layer_list.count; i++) {
+ struct loader_layer_properties *layer_prop =
+ &inst->activated_layer_list.list[i];
+ if (layer_prop->interface_version > 1 &&
+ NULL != layer_prop->functions.get_physical_device_proc_addr) {
+ inst->disp->phys_dev_ext[idx] =
+ (PFN_PhysDevExt)
+ layer_prop->functions.get_physical_device_proc_addr(
+ (VkInstance)inst, funcName);
+ if (NULL != inst->disp->phys_dev_ext[idx]) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (NULL != tramp_addr) {
+ *tramp_addr = loader_get_phys_dev_ext_tramp(idx);
+ }
+
+ if (NULL != term_addr) {
+ *term_addr = loader_get_phys_dev_ext_termin(idx);
+ }
+
+ success = true;
+
+out:
+ return success;
+}
+
struct loader_instance *loader_get_instance(const VkInstance instance) {
/* look up the loader_instance in our list by comparing dispatch tables, as
* there is no guarantee the instance is still a loader_instance* after any
@@ -3803,10 +4268,10 @@ struct loader_instance *loader_get_instance(const VkInstance instance) {
*/
const VkLayerInstanceDispatchTable *disp;
struct loader_instance *ptr_instance = NULL;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
for (struct loader_instance *inst = loader.instances; inst;
inst = inst->next) {
- if (inst->disp == disp) {
+ if (&inst->disp->layer_inst_disp == disp) {
ptr_instance = inst;
break;
}
@@ -3987,6 +4452,40 @@ loader_enable_instance_layers(struct loader_instance *inst,
return err;
}
+// Determine the layer interface version to use.
+bool loader_get_layer_interface_version(
+ PFN_vkNegotiateLoaderLayerInterfaceVersion fp_negotiate_layer_version,
+ VkNegotiateLayerInterface *interface_struct) {
+
+ memset(interface_struct, 0, sizeof(VkNegotiateLayerInterface));
+
+ // Base assumption is that all layers are version 1 at least.
+ interface_struct->loaderLayerInterfaceVersion = 1;
+
+ if (fp_negotiate_layer_version != NULL) {
+ // Layer supports the negotiation API, so call it with the loader's
+ // latest version supported
+ interface_struct->loaderLayerInterfaceVersion =
+ CURRENT_LOADER_LAYER_INTERFACE_VERSION;
+ VkResult result = fp_negotiate_layer_version(interface_struct);
+
+ if (result != VK_SUCCESS) {
+ // Layer no longer supports the loader's latest interface version so
+ // fail loading the Layer
+ return false;
+ }
+ }
+
+ if (interface_struct->loaderLayerInterfaceVersion <
+ MIN_SUPPORTED_LOADER_LAYER_INTERFACE_VERSION) {
+ // Loader no longer supports the layer's latest interface version so
+ // fail loading the layer
+ return false;
+ }
+
+ return true;
+}
+
/*
* Given the list of layers to activate in the loader_instance
* structure. This function will add a VkLayerInstanceCreateInfo
@@ -4015,8 +4514,10 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo,
VkInstanceCreateInfo loader_create_info;
VkResult res;
- PFN_vkGetInstanceProcAddr nextGIPA = loader_gpa_instance_internal;
- PFN_vkGetInstanceProcAddr fpGIPA = loader_gpa_instance_internal;
+ PFN_vkGetInstanceProcAddr next_gipa = loader_gpa_instance_internal;
+ PFN_vkGetInstanceProcAddr cur_gipa = loader_gpa_instance_internal;
+ PFN_GetPhysicalDeviceProcAddr next_gpdpa = loader_gpdpa_instance_internal;
+ PFN_GetPhysicalDeviceProcAddr cur_gpdpa = loader_gpdpa_instance_internal;
memcpy(&loader_create_info, pCreateInfo, sizeof(VkInstanceCreateInfo));
@@ -4037,42 +4538,113 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo,
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
- /* Create instance chain of enabled layers */
+ // Create instance chain of enabled layers
for (int32_t i = inst->activated_layer_list.count - 1; i >= 0; i--) {
struct loader_layer_properties *layer_prop =
&inst->activated_layer_list.list[i];
loader_platform_dl_handle lib_handle;
lib_handle = loader_open_layer_lib(inst, "instance", layer_prop);
- if (!lib_handle)
+ if (!lib_handle) {
continue;
- if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) ==
- NULL) {
- if (strlen(layer_prop->functions.str_gipa) == 0) {
- fpGIPA = (PFN_vkGetInstanceProcAddr)
- loader_platform_get_proc_address(
- lib_handle, "vkGetInstanceProcAddr");
- layer_prop->functions.get_instance_proc_addr = fpGIPA;
- } else
- fpGIPA = (PFN_vkGetInstanceProcAddr)
- loader_platform_get_proc_address(
- lib_handle, layer_prop->functions.str_gipa);
- if (!fpGIPA) {
- loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
- "loader_create_instance_chain: Failed to find "
- "\'vkGetInstanceProcAddr\' in layer %s",
- layer_prop->lib_name);
- continue;
+ }
+
+ if (NULL == layer_prop->functions.negotiate_layer_interface) {
+ PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_interface =
+ NULL;
+ bool functions_in_interface = false;
+ if (strlen(layer_prop->functions.str_negotiate_interface) ==
+ 0) {
+ negotiate_interface =
+ (PFN_vkNegotiateLoaderLayerInterfaceVersion)
+ loader_platform_get_proc_address(
+ lib_handle,
+ "vkNegotiateLoaderLayerInterfaceVersion");
+ } else {
+ negotiate_interface =
+ (PFN_vkNegotiateLoaderLayerInterfaceVersion)
+ loader_platform_get_proc_address(
+ lib_handle,
+ layer_prop->functions.str_negotiate_interface);
+ }
+
+ // If we can negotiate an interface version, then we can also
+ // get everything we need from the one function call, so try
+ // that first, and see if we can get all the function pointers
+ // necessary from that one call.
+ if (NULL != negotiate_interface) {
+ layer_prop->functions.negotiate_layer_interface =
+ negotiate_interface;
+
+ VkNegotiateLayerInterface interface_struct;
+
+ if (loader_get_layer_interface_version(negotiate_interface,
+ &interface_struct)) {
+
+ // Go ahead and set the properites version to the
+ // correct value.
+ layer_prop->interface_version =
+ interface_struct.loaderLayerInterfaceVersion;
+
+ // If the interface is 2 or newer, we have access to the
+ // new GetPhysicalDeviceProcAddr function, so grab it,
+ // and the other necessary functions, from the
+ // structure.
+ if (interface_struct.loaderLayerInterfaceVersion > 1) {
+ cur_gipa = interface_struct.pfnGetInstanceProcAddr;
+ cur_gpdpa =
+ interface_struct.pfnGetPhysicalDeviceProcAddr;
+ if (cur_gipa != NULL) {
+ // We've set the functions, so make sure we
+ // don't do the unnecessary calls later.
+ functions_in_interface = true;
+ }
+ }
+ }
+ }
+
+ if (!functions_in_interface) {
+ if ((cur_gipa =
+ layer_prop->functions.get_instance_proc_addr) ==
+ NULL) {
+ if (strlen(layer_prop->functions.str_gipa) == 0) {
+ cur_gipa = (PFN_vkGetInstanceProcAddr)
+ loader_platform_get_proc_address(
+ lib_handle, "vkGetInstanceProcAddr");
+ layer_prop->functions.get_instance_proc_addr =
+ cur_gipa;
+ } else {
+ cur_gipa = (PFN_vkGetInstanceProcAddr)
+ loader_platform_get_proc_address(
+ lib_handle, layer_prop->functions.str_gipa);
+ }
+
+ if (NULL == cur_gipa) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_create_instance_chain: Failed to"
+ " find \'vkGetInstanceProcAddr\' in "
+ "layer %s",
+ layer_prop->lib_name);
+ continue;
+ }
+ }
}
}
layer_instance_link_info[activated_layers].pNext =
chain_info.u.pLayerInfo;
layer_instance_link_info[activated_layers]
- .pfnNextGetInstanceProcAddr = nextGIPA;
+ .pfnNextGetInstanceProcAddr = next_gipa;
+ layer_instance_link_info[activated_layers]
+ .pfnNextGetPhysicalDeviceProcAddr = next_gpdpa;
+ next_gipa = cur_gipa;
+ if (layer_prop->interface_version > 1 && cur_gpdpa != NULL) {
+ layer_prop->functions.get_physical_device_proc_addr = cur_gpdpa;
+ next_gpdpa = cur_gpdpa;
+ }
+
chain_info.u.pLayerInfo =
&layer_instance_link_info[activated_layers];
- nextGIPA = fpGIPA;
loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
"Insert instance layer %s (%s)",
@@ -4083,7 +4655,7 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo,
}
PFN_vkCreateInstance fpCreateInstance =
- (PFN_vkCreateInstance)nextGIPA(*created_instance, "vkCreateInstance");
+ (PFN_vkCreateInstance)next_gipa(*created_instance, "vkCreateInstance");
if (fpCreateInstance) {
VkLayerInstanceCreateInfo create_info_disp;
@@ -4104,11 +4676,9 @@ VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo,
res = VK_ERROR_INITIALIZATION_FAILED;
}
- if (res != VK_SUCCESS) {
- // TODO: Need to clean up here
- } else {
- loader_init_instance_core_dispatch_table(inst->disp, nextGIPA,
- *created_instance);
+ if (res == VK_SUCCESS) {
+ loader_init_instance_core_dispatch_table(&inst->disp->layer_inst_disp,
+ next_gipa, *created_instance);
inst->instance = *created_instance;
}
@@ -4119,7 +4689,8 @@ void loader_activate_instance_layer_extensions(struct loader_instance *inst,
VkInstance created_inst) {
loader_init_instance_extension_dispatch_table(
- inst->disp, inst->disp->GetInstanceProcAddr, created_inst);
+ &inst->disp->layer_inst_disp,
+ inst->disp->layer_inst_disp.GetInstanceProcAddr, created_inst);
}
VkResult
@@ -4152,57 +4723,113 @@ loader_create_device_chain(const struct loader_physical_device_tramp *pd,
chain_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
chain_info.function = VK_LAYER_LINK_INFO;
chain_info.u.pLayerInfo = NULL;
- chain_info.pNext = pCreateInfo->pNext;
+ chain_info.pNext = loader_create_info.pNext;
loader_create_info.pNext = &chain_info;
- /* Create instance chain of enabled layers */
+ // Create instance chain of enabled layers
for (int32_t i = dev->activated_layer_list.count - 1; i >= 0; i--) {
struct loader_layer_properties *layer_prop =
&dev->activated_layer_list.list[i];
loader_platform_dl_handle lib_handle;
+ bool functions_in_interface = false;
lib_handle = loader_open_layer_lib(inst, "device", layer_prop);
- if (!lib_handle)
+ if (!lib_handle) {
continue;
- if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) ==
- NULL) {
- if (strlen(layer_prop->functions.str_gipa) == 0) {
- fpGIPA = (PFN_vkGetInstanceProcAddr)
- loader_platform_get_proc_address(
- lib_handle, "vkGetInstanceProcAddr");
- layer_prop->functions.get_instance_proc_addr = fpGIPA;
- } else
- fpGIPA = (PFN_vkGetInstanceProcAddr)
+ }
+
+ // If we can negotiate an interface version, then we can also
+ // get everything we need from the one function call, so try
+ // that first, and see if we can get all the function pointers
+ // necessary from that one call.
+ if (NULL == layer_prop->functions.negotiate_layer_interface) {
+ PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_interface =
+ NULL;
+ if (strlen(layer_prop->functions.str_negotiate_interface) ==
+ 0) {
+ negotiate_interface =
+ (PFN_vkNegotiateLoaderLayerInterfaceVersion)
+ loader_platform_get_proc_address(
+ lib_handle,
+ "vkNegotiateLoaderLayerInterfaceVersion");
+ } else {
+ negotiate_interface =
+ (PFN_vkNegotiateLoaderLayerInterfaceVersion)
+ loader_platform_get_proc_address(
+ lib_handle,
+ layer_prop->functions.str_negotiate_interface);
+ }
+
+ if (NULL != negotiate_interface) {
+ layer_prop->functions.negotiate_layer_interface =
+ negotiate_interface;
+
+ VkNegotiateLayerInterface interface_struct;
+
+ if (loader_get_layer_interface_version(negotiate_interface,
+ &interface_struct)) {
+
+ // Go ahead and set the properites version to the
+ // correct value.
+ layer_prop->interface_version =
+ interface_struct.loaderLayerInterfaceVersion;
+
+ // If the interface is 2 or newer, we have access to the
+ // new GetPhysicalDeviceProcAddr function, so grab it,
+ // and the other necessary functions, from the structure.
+ if (interface_struct.loaderLayerInterfaceVersion > 1) {
+ fpGIPA = interface_struct.pfnGetInstanceProcAddr;
+ fpGDPA = interface_struct.pfnGetDeviceProcAddr;
+ if (fpGIPA != NULL && fpGDPA) {
+ // We've set the functions, so make sure we
+ // don't do the unnecessary calls later.
+ functions_in_interface = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (!functions_in_interface) {
+ if ((fpGIPA = layer_prop->functions.get_instance_proc_addr) ==
+ NULL) {
+ if (strlen(layer_prop->functions.str_gipa) == 0) {
+ fpGIPA = (PFN_vkGetInstanceProcAddr)
+ loader_platform_get_proc_address(
+ lib_handle, "vkGetInstanceProcAddr");
+ layer_prop->functions.get_instance_proc_addr = fpGIPA;
+ } else
+ fpGIPA = (PFN_vkGetInstanceProcAddr)
loader_platform_get_proc_address(
lib_handle, layer_prop->functions.str_gipa);
- if (!fpGIPA) {
- loader_log(
- inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
- "loader_create_device_chain: Failed to find "
- "\'vkGetInstanceProcAddr\' in layer %s. Skipping"
- " layer.",
- layer_prop->lib_name);
- continue;
+ if (!fpGIPA) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "loader_create_device_chain: Failed to find "
+ "\'vkGetInstanceProcAddr\' in layer %s. Skipping"
+ " layer.",
+ layer_prop->lib_name);
+ continue;
+ }
}
- }
- if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) {
- if (strlen(layer_prop->functions.str_gdpa) == 0) {
- fpGDPA = (PFN_vkGetDeviceProcAddr)
- loader_platform_get_proc_address(lib_handle,
- "vkGetDeviceProcAddr");
- layer_prop->functions.get_device_proc_addr = fpGDPA;
- } else
- fpGDPA = (PFN_vkGetDeviceProcAddr)
+ if ((fpGDPA = layer_prop->functions.get_device_proc_addr) == NULL) {
+ if (strlen(layer_prop->functions.str_gdpa) == 0) {
+ fpGDPA = (PFN_vkGetDeviceProcAddr)
+ loader_platform_get_proc_address(lib_handle,
+ "vkGetDeviceProcAddr");
+ layer_prop->functions.get_device_proc_addr = fpGDPA;
+ } else
+ fpGDPA = (PFN_vkGetDeviceProcAddr)
loader_platform_get_proc_address(
lib_handle, layer_prop->functions.str_gdpa);
- if (!fpGDPA) {
- loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
- "Failed to find vkGetDeviceProcAddr in layer %s",
- layer_prop->lib_name);
- continue;
+ if (!fpGDPA) {
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "Failed to find vkGetDeviceProcAddr in layer %s",
+ layer_prop->lib_name);
+ continue;
+ }
}
}
-
layer_device_link_info[activated_layers].pNext =
chain_info.u.pLayerInfo;
layer_device_link_info[activated_layers]
@@ -4617,7 +5244,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(
loader_scanned_icd_clear(ptr_instance, &ptr_instance->icd_tramp_list);
loader_destroy_generic_list(
ptr_instance, (struct loader_generic_list *)&ptr_instance->ext_list);
- if (ptr_instance->phys_devs_term) {
+ if (NULL != ptr_instance->phys_devs_term) {
for (uint32_t i = 0; i < ptr_instance->phys_dev_count_term; i++) {
loader_instance_heap_free(ptr_instance,
ptr_instance->phys_devs_term[i]);
@@ -4625,6 +5252,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroyInstance(
loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_term);
}
loader_free_dev_ext_table(ptr_instance);
+ loader_free_phys_dev_ext_table(ptr_instance);
}
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDevice(
@@ -4780,8 +5408,8 @@ VkResult setupLoaderTrampPhysDevs(VkInstance instance) {
}
memset(local_phys_devs, 0, sizeof(VkPhysicalDevice) * total_count);
- res = inst->disp->EnumeratePhysicalDevices(instance, &total_count,
- local_phys_devs);
+ res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(
+ instance, &total_count, local_phys_devs);
if (VK_SUCCESS != res) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"setupLoaderTrampPhysDevs: Failed during dispatch call "
diff --git a/loader/loader.h b/loader/loader.h
index 45dc223b..019125f0 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -52,6 +52,13 @@
#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.
+#ifndef MAX_NUM_UNKNOWN_EXTS
+#define MAX_NUM_UNKNOWN_EXTS 250
+#endif
+
+
enum layer_type {
VK_LAYER_TYPE_INSTANCE_EXPLICIT = 0x1,
VK_LAYER_TYPE_INSTANCE_IMPLICIT = 0x2,
@@ -81,6 +88,11 @@ static const char std_validation_names[7][VK_MAX_EXTENSION_NAME_SIZE] = {
"VK_LAYER_LUNARG_core_validation", "VK_LAYER_LUNARG_swapchain",
"VK_LAYER_GOOGLE_unique_objects"};
+struct VkStructureHeader {
+ VkStructureType sType;
+ const void* pNext;
+};
+
// form of all dynamic lists/arrays
// only the list element should be changed
struct loader_generic_list {
@@ -115,13 +127,17 @@ struct loader_name_value {
struct loader_layer_functions {
char str_gipa[MAX_STRING_SIZE];
char str_gdpa[MAX_STRING_SIZE];
+ char str_negotiate_interface[MAX_STRING_SIZE];
+ PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_layer_interface;
PFN_vkGetInstanceProcAddr get_instance_proc_addr;
PFN_vkGetDeviceProcAddr get_device_proc_addr;
+ PFN_GetPhysicalDeviceProcAddr get_physical_device_proc_addr;
};
struct loader_layer_properties {
VkLayerProperties info;
enum layer_type type;
+ uint32_t interface_version; // PFN_vkNegotiateLoaderLayerInterfaceVersion
char lib_name[MAX_STRING_SIZE];
loader_platform_dl_handle lib_handle;
struct loader_layer_functions functions;
@@ -143,7 +159,7 @@ struct loader_dispatch_hash_list {
uint32_t *index; // index into the dev_ext dispatch table
};
-#define MAX_NUM_DEV_EXTS 250
+
// loader_dispatch_hash_entry and loader_dev_ext_dispatch_table.dev_ext have
// one to one correspondence; one loader_dispatch_hash_entry for one dev_ext
// dispatch entry.
@@ -155,7 +171,7 @@ struct loader_dispatch_hash_entry {
typedef void(VKAPI_PTR *PFN_vkDevExt)(VkDevice device);
struct loader_dev_ext_dispatch_table {
- PFN_vkDevExt dev_ext[MAX_NUM_DEV_EXTS];
+ PFN_vkDevExt dev_ext[MAX_NUM_UNKNOWN_EXTS];
};
struct loader_dev_dispatch_table {
@@ -199,19 +215,13 @@ struct loader_icd_term {
PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
PFN_vkGetPhysicalDeviceSparseImageFormatProperties
GetPhysicalDeviceSparseImageFormatProperties;
- PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
- PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
- PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
- PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT;
- PFN_vkDebugMarkerSetObjectNameEXT DebugMarkerSetObjectNameEXT;
+ // WSI extensions
PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
GetPhysicalDeviceSurfaceCapabilitiesKHR;
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
GetPhysicalDeviceSurfacePresentModesKHR;
- PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV
- GetPhysicalDeviceExternalImageFormatPropertiesNV;
#ifdef VK_USE_PLATFORM_WIN32_KHR
PFN_vkCreateWin32SurfaceKHR CreateWin32SurfaceKHR;
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR
@@ -249,12 +259,55 @@ struct loader_icd_term {
PFN_vkCreateDisplayPlaneSurfaceKHR CreateDisplayPlaneSurfaceKHR;
PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
+ PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR;
+
+ // KHR_get_physical_device_properties2
+ PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysicalDeviceFeatures2KHR;
+ PFN_vkGetPhysicalDeviceProperties2KHR GetPhysicalDeviceProperties2KHR;
+ PFN_vkGetPhysicalDeviceFormatProperties2KHR
+ GetPhysicalDeviceFormatProperties2KHR;
+ PFN_vkGetPhysicalDeviceImageFormatProperties2KHR
+ GetPhysicalDeviceImageFormatProperties2KHR;
+ PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR
+ GetPhysicalDeviceQueueFamilyProperties2KHR;
+ PFN_vkGetPhysicalDeviceMemoryProperties2KHR
+ GetPhysicalDeviceMemoryProperties2KHR;
+ PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR
+ GetPhysicalDeviceSparseImageFormatProperties2KHR;
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ // EXT_acquire_xlib_display
+ PFN_vkAcquireXlibDisplayEXT AcquireXlibDisplayEXT;
+ PFN_vkGetRandROutputDisplayEXT GetRandROutputDisplayEXT;
+#endif
+
+ // EXT_debug_report
+ PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+ PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+ PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+
+ // EXT_debug_marker (items needing a trampoline/terminator)
+ PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT;
+ PFN_vkDebugMarkerSetObjectNameEXT DebugMarkerSetObjectNameEXT;
+
+ // EXT_direct_mode_display
+ PFN_vkReleaseDisplayEXT ReleaseDisplayEXT;
+
+ // EXT_display_surface_counter
+ PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT
+ GetPhysicalDeviceSurfaceCapabilities2EXT;
+
+ // NV_external_memory_capabilities
+ PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV
+ GetPhysicalDeviceExternalImageFormatPropertiesNV;
// NVX_device_generated_commands
PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX
GetPhysicalDeviceGeneratedCommandsPropertiesNVX;
struct loader_icd_term *next;
+
+ PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
};
// per ICD library structure
@@ -266,15 +319,26 @@ struct loader_icd_tramp_list {
union loader_instance_extension_enables {
struct {
+ uint8_t khr_get_physical_device_properties2 : 1;
+ uint8_t ext_acquire_xlib_display : 1;
uint8_t ext_debug_report : 1;
+ uint8_t ext_direct_mode_display : 1;
+ uint8_t ext_display_surface_counter : 1;
uint8_t nv_external_memory_capabilities : 1;
};
uint64_t padding[4];
};
+struct loader_instance_dispatch_table {
+ VkLayerInstanceDispatchTable layer_inst_disp; // must be first entry in structure
+
+ // Physical device functions unknown to the loader
+ PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
+};
+
// per instance structure
struct loader_instance {
- VkLayerInstanceDispatchTable *disp; // must be first entry in structure
+ struct loader_instance_dispatch_table *disp; // must be first entry in structure
uint32_t total_gpu_count;
uint32_t phys_dev_count_term;
@@ -288,7 +352,8 @@ struct loader_instance {
struct loader_icd_term *icd_terms;
struct loader_icd_tramp_list icd_tramp_list;
- struct loader_dispatch_hash_entry disp_hash[MAX_NUM_DEV_EXTS];
+ struct loader_dispatch_hash_entry dev_ext_disp_hash[MAX_NUM_UNKNOWN_EXTS];
+ struct loader_dispatch_hash_entry phys_dev_ext_disp_hash[MAX_NUM_UNKNOWN_EXTS];
struct loader_msg_callback_map_entry *icd_msg_callback_map;
@@ -344,14 +409,14 @@ struct loader_instance {
/* per enumerated PhysicalDevice structure, used to wrap in trampoline code and
also same structure used to wrap in terminator code */
struct loader_physical_device_tramp {
- VkLayerInstanceDispatchTable *disp; // must be first entry in structure
+ struct loader_instance_dispatch_table *disp; // must be first entry in structure
struct loader_instance *this_instance;
VkPhysicalDevice phys_dev; // object from layers/loader terminator
};
/* per enumerated PhysicalDevice structure, used to wrap in terminator code */
struct loader_physical_device_term {
- VkLayerInstanceDispatchTable *disp; // must be first entry in structure
+ struct loader_instance_dispatch_table *disp; // must be first entry in structure
struct loader_icd_term *this_icd_term;
uint8_t icd_index;
VkPhysicalDevice phys_dev; // object from ICD
@@ -367,6 +432,7 @@ struct loader_scanned_icd {
uint32_t api_version;
uint32_t interface_version;
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+ PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr;
PFN_vkCreateInstance CreateInstance;
PFN_vkEnumerateInstanceExtensionProperties
EnumerateInstanceExtensionProperties;
@@ -397,10 +463,15 @@ loader_get_dev_dispatch(const void *obj) {
}
static inline VkLayerInstanceDispatchTable *
-loader_get_instance_dispatch(const void *obj) {
+loader_get_instance_layer_dispatch(const void *obj) {
return *((VkLayerInstanceDispatchTable **)obj);
}
+static inline struct loader_instance_dispatch_table *
+loader_get_instance_dispatch(const void *obj) {
+ return *((struct loader_instance_dispatch_table **)obj);
+}
+
static inline void loader_init_dispatch(void *obj, const void *data) {
#ifdef DEBUG
assert(valid_loader_magic_value(obj) &&
@@ -537,7 +608,10 @@ void loader_init_dispatch_dev_ext(struct loader_instance *inst,
struct loader_device *dev);
void *loader_dev_ext_gpa(struct loader_instance *inst, const char *funcName);
void *loader_get_dev_ext_trampoline(uint32_t index);
-void loader_override_terminating_device_proc(struct loader_device *dev);
+bool loader_phys_dev_ext_gpa(struct loader_instance *inst, const char *funcName,
+ bool perform_checking, void **tramp_addr, void **term_addr);
+void *loader_get_phys_dev_ext_tramp(uint32_t index);
+void *loader_get_phys_dev_ext_termin(uint32_t index);
struct loader_instance *loader_get_instance(const VkInstance instance);
void loader_deactivate_layers(const struct loader_instance *instance,
struct loader_device *device,
@@ -583,6 +657,7 @@ loader_create_device_chain(const struct loader_physical_device_tramp *pd,
const VkAllocationCallbacks *pAllocator,
const struct loader_instance *inst,
struct loader_device *dev);
+
VkResult loader_validate_device_extensions(
struct loader_physical_device_tramp *phys_dev,
const struct loader_layer_list *activated_device_layers,
diff --git a/loader/loader.rc b/loader/loader.rc
index 04226991..177de20b 100755
--- a/loader/loader.rc
+++ b/loader/loader.rc
@@ -1,7 +1,7 @@
//
-// Copyright (c) 2014-2016 The Khronos Group Inc.
-// Copyright (c) 2014-2016 Valve Corporation
-// Copyright (c) 2014-2016 LunarG, Inc.
+// Copyright (c) 2014-2017 The Khronos Group Inc.
+// Copyright (c) 2014-2017 Valve Corporation
+// Copyright (c) 2014-2017 LunarG, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -86,7 +86,7 @@ BEGIN
BEGIN
VALUE "FileDescription", VER_FILE_DESCRIPTION_STR
VALUE "FileVersion", VER_FILE_VERSION_STR
- VALUE "LegalCopyright", "Copyright (C) 2015-2016"
+ VALUE "LegalCopyright", "Copyright (C) 2015-2017"
VALUE "ProductName", "Vulkan Runtime"
VALUE "ProductVersion", VER_FILE_VERSION_STR
END
diff --git a/loader/phys_dev_ext.c b/loader/phys_dev_ext.c
new file mode 100644
index 00000000..90830250
--- /dev/null
+++ b/loader/phys_dev_ext.c
@@ -0,0 +1,828 @@
+/*
+ *
+ * Copyright (c) 2016 The Khronos Group Inc.
+ * Copyright (c) 2016 Valve Corporation
+ * Copyright (c) 2016 LunarG, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Author: Mark Young <marky@lunarg.com>
+ *
+ */
+
+// This code is used to enable generic instance extensions which use a physical device
+// as the first parameter. If the extension is already known by the loader, it will
+// not use this code, but instead use the more direct route. However, if it is
+// unknown to the loader, it will use this code. Technically, this is not trampoline
+// code since we don't want to optimize it out.
+
+#include "vk_loader_platform.h"
+#include "loader.h"
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC optimize(3) // force gcc to use tail-calls
+#endif
+
+// Trampoline function macro for unknown physical device extension command.
+#define PhysDevExtTramp(num) \
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTramp##num( \
+ VkPhysicalDevice physical_device) { \
+ const struct loader_instance_dispatch_table *disp; \
+ disp = loader_get_instance_dispatch(physical_device); \
+ disp->phys_dev_ext[num]( \
+ loader_unwrap_physical_device(physical_device)); \
+ }
+
+// Terminator function macro for unknown physical device extension command.
+#define PhysDevExtTermin(num) \
+VKAPI_ATTR void VKAPI_CALL vkPhysDevExtTermin##num( \
+ VkPhysicalDevice physical_device) { \
+ struct loader_physical_device_term *phys_dev_term = \
+ (struct loader_physical_device_term *)physical_device; \
+ struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; \
+ struct loader_instance *inst = \
+ (struct loader_instance *)icd_term->this_instance; \
+ if (NULL == icd_term->phys_dev_ext[num]) { \
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, \
+ "Extension %s not supported for this physical device", \
+ inst->phys_dev_ext_disp_hash[num].func_name); \
+ } \
+ icd_term->phys_dev_ext[num](phys_dev_term->phys_dev); \
+ }
+
+// Instantiations of the trampoline and terminator
+PhysDevExtTramp(0) PhysDevExtTermin(0)
+PhysDevExtTramp(1) PhysDevExtTermin(1)
+PhysDevExtTramp(2) PhysDevExtTermin(2)
+PhysDevExtTramp(3) PhysDevExtTermin(3)
+PhysDevExtTramp(4) PhysDevExtTermin(4)
+PhysDevExtTramp(5) PhysDevExtTermin(5)
+PhysDevExtTramp(6) PhysDevExtTermin(6)
+PhysDevExtTramp(7) PhysDevExtTermin(7)
+PhysDevExtTramp(8) PhysDevExtTermin(8)
+PhysDevExtTramp(9) PhysDevExtTermin(9)
+PhysDevExtTramp(10) PhysDevExtTermin(10)
+PhysDevExtTramp(11) PhysDevExtTermin(11)
+PhysDevExtTramp(12) PhysDevExtTermin(12)
+PhysDevExtTramp(13) PhysDevExtTermin(13)
+PhysDevExtTramp(14) PhysDevExtTermin(14)
+PhysDevExtTramp(15) PhysDevExtTermin(15)
+PhysDevExtTramp(16) PhysDevExtTermin(16)
+PhysDevExtTramp(17) PhysDevExtTermin(17)
+PhysDevExtTramp(18) PhysDevExtTermin(18)
+PhysDevExtTramp(19) PhysDevExtTermin(19)
+PhysDevExtTramp(20) PhysDevExtTermin(20)
+PhysDevExtTramp(21) PhysDevExtTermin(21)
+PhysDevExtTramp(22) PhysDevExtTermin(22)
+PhysDevExtTramp(23) PhysDevExtTermin(23)
+PhysDevExtTramp(24) PhysDevExtTermin(24)
+PhysDevExtTramp(25) PhysDevExtTermin(25)
+PhysDevExtTramp(26) PhysDevExtTermin(26)
+PhysDevExtTramp(27) PhysDevExtTermin(27)
+PhysDevExtTramp(28) PhysDevExtTermin(28)
+PhysDevExtTramp(29) PhysDevExtTermin(29)
+PhysDevExtTramp(30) PhysDevExtTermin(30)
+PhysDevExtTramp(31) PhysDevExtTermin(31)
+PhysDevExtTramp(32) PhysDevExtTermin(32)
+PhysDevExtTramp(33) PhysDevExtTermin(33)
+PhysDevExtTramp(34) PhysDevExtTermin(34)
+PhysDevExtTramp(35) PhysDevExtTermin(35)
+PhysDevExtTramp(36) PhysDevExtTermin(36)
+PhysDevExtTramp(37) PhysDevExtTermin(37)
+PhysDevExtTramp(38) PhysDevExtTermin(38)
+PhysDevExtTramp(39) PhysDevExtTermin(39)
+PhysDevExtTramp(40) PhysDevExtTermin(40)
+PhysDevExtTramp(41) PhysDevExtTermin(41)
+PhysDevExtTramp(42) PhysDevExtTermin(42)
+PhysDevExtTramp(43) PhysDevExtTermin(43)
+PhysDevExtTramp(44) PhysDevExtTermin(44)
+PhysDevExtTramp(45) PhysDevExtTermin(45)
+PhysDevExtTramp(46) PhysDevExtTermin(46)
+PhysDevExtTramp(47) PhysDevExtTermin(47)
+PhysDevExtTramp(48) PhysDevExtTermin(48)
+PhysDevExtTramp(49) PhysDevExtTermin(49)
+PhysDevExtTramp(50) PhysDevExtTermin(50)
+PhysDevExtTramp(51) PhysDevExtTermin(51)
+PhysDevExtTramp(52) PhysDevExtTermin(52)
+PhysDevExtTramp(53) PhysDevExtTermin(53)
+PhysDevExtTramp(54) PhysDevExtTermin(54)
+PhysDevExtTramp(55) PhysDevExtTermin(55)
+PhysDevExtTramp(56) PhysDevExtTermin(56)
+PhysDevExtTramp(57) PhysDevExtTermin(57)
+PhysDevExtTramp(58) PhysDevExtTermin(58)
+PhysDevExtTramp(59) PhysDevExtTermin(59)
+PhysDevExtTramp(60) PhysDevExtTermin(60)
+PhysDevExtTramp(61) PhysDevExtTermin(61)
+PhysDevExtTramp(62) PhysDevExtTermin(62)
+PhysDevExtTramp(63) PhysDevExtTermin(63)
+PhysDevExtTramp(64) PhysDevExtTermin(64)
+PhysDevExtTramp(65) PhysDevExtTermin(65)
+PhysDevExtTramp(66) PhysDevExtTermin(66)
+PhysDevExtTramp(67) PhysDevExtTermin(67)
+PhysDevExtTramp(68) PhysDevExtTermin(68)
+PhysDevExtTramp(69) PhysDevExtTermin(69)
+PhysDevExtTramp(70) PhysDevExtTermin(70)
+PhysDevExtTramp(71) PhysDevExtTermin(71)
+PhysDevExtTramp(72) PhysDevExtTermin(72)
+PhysDevExtTramp(73) PhysDevExtTermin(73)
+PhysDevExtTramp(74) PhysDevExtTermin(74)
+PhysDevExtTramp(75) PhysDevExtTermin(75)
+PhysDevExtTramp(76) PhysDevExtTermin(76)
+PhysDevExtTramp(77) PhysDevExtTermin(77)
+PhysDevExtTramp(78) PhysDevExtTermin(78)
+PhysDevExtTramp(79) PhysDevExtTermin(79)
+PhysDevExtTramp(80) PhysDevExtTermin(80)
+PhysDevExtTramp(81) PhysDevExtTermin(81)
+PhysDevExtTramp(82) PhysDevExtTermin(82)
+PhysDevExtTramp(83) PhysDevExtTermin(83)
+PhysDevExtTramp(84) PhysDevExtTermin(84)
+PhysDevExtTramp(85) PhysDevExtTermin(85)
+PhysDevExtTramp(86) PhysDevExtTermin(86)
+PhysDevExtTramp(87) PhysDevExtTermin(87)
+PhysDevExtTramp(88) PhysDevExtTermin(88)
+PhysDevExtTramp(89) PhysDevExtTermin(89)
+PhysDevExtTramp(90) PhysDevExtTermin(90)
+PhysDevExtTramp(91) PhysDevExtTermin(91)
+PhysDevExtTramp(92) PhysDevExtTermin(92)
+PhysDevExtTramp(93) PhysDevExtTermin(93)
+PhysDevExtTramp(94) PhysDevExtTermin(94)
+PhysDevExtTramp(95) PhysDevExtTermin(95)
+PhysDevExtTramp(96) PhysDevExtTermin(96)
+PhysDevExtTramp(97) PhysDevExtTermin(97)
+PhysDevExtTramp(98) PhysDevExtTermin(98)
+PhysDevExtTramp(99) PhysDevExtTermin(99)
+PhysDevExtTramp(100) PhysDevExtTermin(100)
+PhysDevExtTramp(101) PhysDevExtTermin(101)
+PhysDevExtTramp(102) PhysDevExtTermin(102)
+PhysDevExtTramp(103) PhysDevExtTermin(103)
+PhysDevExtTramp(104) PhysDevExtTermin(104)
+PhysDevExtTramp(105) PhysDevExtTermin(105)
+PhysDevExtTramp(106) PhysDevExtTermin(106)
+PhysDevExtTramp(107) PhysDevExtTermin(107)
+PhysDevExtTramp(108) PhysDevExtTermin(108)
+PhysDevExtTramp(109) PhysDevExtTermin(109)
+PhysDevExtTramp(110) PhysDevExtTermin(110)
+PhysDevExtTramp(111) PhysDevExtTermin(111)
+PhysDevExtTramp(112) PhysDevExtTermin(112)
+PhysDevExtTramp(113) PhysDevExtTermin(113)
+PhysDevExtTramp(114) PhysDevExtTermin(114)
+PhysDevExtTramp(115) PhysDevExtTermin(115)
+PhysDevExtTramp(116) PhysDevExtTermin(116)
+PhysDevExtTramp(117) PhysDevExtTermin(117)
+PhysDevExtTramp(118) PhysDevExtTermin(118)
+PhysDevExtTramp(119) PhysDevExtTermin(119)
+PhysDevExtTramp(120) PhysDevExtTermin(120)
+PhysDevExtTramp(121) PhysDevExtTermin(121)
+PhysDevExtTramp(122) PhysDevExtTermin(122)
+PhysDevExtTramp(123) PhysDevExtTermin(123)
+PhysDevExtTramp(124) PhysDevExtTermin(124)
+PhysDevExtTramp(125) PhysDevExtTermin(125)
+PhysDevExtTramp(126) PhysDevExtTermin(126)
+PhysDevExtTramp(127) PhysDevExtTermin(127)
+PhysDevExtTramp(128) PhysDevExtTermin(128)
+PhysDevExtTramp(129) PhysDevExtTermin(129)
+PhysDevExtTramp(130) PhysDevExtTermin(130)
+PhysDevExtTramp(131) PhysDevExtTermin(131)
+PhysDevExtTramp(132) PhysDevExtTermin(132)
+PhysDevExtTramp(133) PhysDevExtTermin(133)
+PhysDevExtTramp(134) PhysDevExtTermin(134)
+PhysDevExtTramp(135) PhysDevExtTermin(135)
+PhysDevExtTramp(136) PhysDevExtTermin(136)
+PhysDevExtTramp(137) PhysDevExtTermin(137)
+PhysDevExtTramp(138) PhysDevExtTermin(138)
+PhysDevExtTramp(139) PhysDevExtTermin(139)
+PhysDevExtTramp(140) PhysDevExtTermin(140)
+PhysDevExtTramp(141) PhysDevExtTermin(141)
+PhysDevExtTramp(142) PhysDevExtTermin(142)
+PhysDevExtTramp(143) PhysDevExtTermin(143)
+PhysDevExtTramp(144) PhysDevExtTermin(144)
+PhysDevExtTramp(145) PhysDevExtTermin(145)
+PhysDevExtTramp(146) PhysDevExtTermin(146)
+PhysDevExtTramp(147) PhysDevExtTermin(147)
+PhysDevExtTramp(148) PhysDevExtTermin(148)
+PhysDevExtTramp(149) PhysDevExtTermin(149)
+PhysDevExtTramp(150) PhysDevExtTermin(150)
+PhysDevExtTramp(151) PhysDevExtTermin(151)
+PhysDevExtTramp(152) PhysDevExtTermin(152)
+PhysDevExtTramp(153) PhysDevExtTermin(153)
+PhysDevExtTramp(154) PhysDevExtTermin(154)
+PhysDevExtTramp(155) PhysDevExtTermin(155)
+PhysDevExtTramp(156) PhysDevExtTermin(156)
+PhysDevExtTramp(157) PhysDevExtTermin(157)
+PhysDevExtTramp(158) PhysDevExtTermin(158)
+PhysDevExtTramp(159) PhysDevExtTermin(159)
+PhysDevExtTramp(160) PhysDevExtTermin(160)
+PhysDevExtTramp(161) PhysDevExtTermin(161)
+PhysDevExtTramp(162) PhysDevExtTermin(162)
+PhysDevExtTramp(163) PhysDevExtTermin(163)
+PhysDevExtTramp(164) PhysDevExtTermin(164)
+PhysDevExtTramp(165) PhysDevExtTermin(165)
+PhysDevExtTramp(166) PhysDevExtTermin(166)
+PhysDevExtTramp(167) PhysDevExtTermin(167)
+PhysDevExtTramp(168) PhysDevExtTermin(168)
+PhysDevExtTramp(169) PhysDevExtTermin(169)
+PhysDevExtTramp(170) PhysDevExtTermin(170)
+PhysDevExtTramp(171) PhysDevExtTermin(171)
+PhysDevExtTramp(172) PhysDevExtTermin(172)
+PhysDevExtTramp(173) PhysDevExtTermin(173)
+PhysDevExtTramp(174) PhysDevExtTermin(174)
+PhysDevExtTramp(175) PhysDevExtTermin(175)
+PhysDevExtTramp(176) PhysDevExtTermin(176)
+PhysDevExtTramp(177) PhysDevExtTermin(177)
+PhysDevExtTramp(178) PhysDevExtTermin(178)
+PhysDevExtTramp(179) PhysDevExtTermin(179)
+PhysDevExtTramp(180) PhysDevExtTermin(180)
+PhysDevExtTramp(181) PhysDevExtTermin(181)
+PhysDevExtTramp(182) PhysDevExtTermin(182)
+PhysDevExtTramp(183) PhysDevExtTermin(183)
+PhysDevExtTramp(184) PhysDevExtTermin(184)
+PhysDevExtTramp(185) PhysDevExtTermin(185)
+PhysDevExtTramp(186) PhysDevExtTermin(186)
+PhysDevExtTramp(187) PhysDevExtTermin(187)
+PhysDevExtTramp(188) PhysDevExtTermin(188)
+PhysDevExtTramp(189) PhysDevExtTermin(189)
+PhysDevExtTramp(190) PhysDevExtTermin(190)
+PhysDevExtTramp(191) PhysDevExtTermin(191)
+PhysDevExtTramp(192) PhysDevExtTermin(192)
+PhysDevExtTramp(193) PhysDevExtTermin(193)
+PhysDevExtTramp(194) PhysDevExtTermin(194)
+PhysDevExtTramp(195) PhysDevExtTermin(195)
+PhysDevExtTramp(196) PhysDevExtTermin(196)
+PhysDevExtTramp(197) PhysDevExtTermin(197)
+PhysDevExtTramp(198) PhysDevExtTermin(198)
+PhysDevExtTramp(199) PhysDevExtTermin(199)
+PhysDevExtTramp(200) PhysDevExtTermin(200)
+PhysDevExtTramp(201) PhysDevExtTermin(201)
+PhysDevExtTramp(202) PhysDevExtTermin(202)
+PhysDevExtTramp(203) PhysDevExtTermin(203)
+PhysDevExtTramp(204) PhysDevExtTermin(204)
+PhysDevExtTramp(205) PhysDevExtTermin(205)
+PhysDevExtTramp(206) PhysDevExtTermin(206)
+PhysDevExtTramp(207) PhysDevExtTermin(207)
+PhysDevExtTramp(208) PhysDevExtTermin(208)
+PhysDevExtTramp(209) PhysDevExtTermin(209)
+PhysDevExtTramp(210) PhysDevExtTermin(210)
+PhysDevExtTramp(211) PhysDevExtTermin(211)
+PhysDevExtTramp(212) PhysDevExtTermin(212)
+PhysDevExtTramp(213) PhysDevExtTermin(213)
+PhysDevExtTramp(214) PhysDevExtTermin(214)
+PhysDevExtTramp(215) PhysDevExtTermin(215)
+PhysDevExtTramp(216) PhysDevExtTermin(216)
+PhysDevExtTramp(217) PhysDevExtTermin(217)
+PhysDevExtTramp(218) PhysDevExtTermin(218)
+PhysDevExtTramp(219) PhysDevExtTermin(219)
+PhysDevExtTramp(220) PhysDevExtTermin(220)
+PhysDevExtTramp(221) PhysDevExtTermin(221)
+PhysDevExtTramp(222) PhysDevExtTermin(222)
+PhysDevExtTramp(223) PhysDevExtTermin(223)
+PhysDevExtTramp(224) PhysDevExtTermin(224)
+PhysDevExtTramp(225) PhysDevExtTermin(225)
+PhysDevExtTramp(226) PhysDevExtTermin(226)
+PhysDevExtTramp(227) PhysDevExtTermin(227)
+PhysDevExtTramp(228) PhysDevExtTermin(228)
+PhysDevExtTramp(229) PhysDevExtTermin(229)
+PhysDevExtTramp(230) PhysDevExtTermin(230)
+PhysDevExtTramp(231) PhysDevExtTermin(231)
+PhysDevExtTramp(232) PhysDevExtTermin(232)
+PhysDevExtTramp(233) PhysDevExtTermin(233)
+PhysDevExtTramp(234) PhysDevExtTermin(234)
+PhysDevExtTramp(235) PhysDevExtTermin(235)
+PhysDevExtTramp(236) PhysDevExtTermin(236)
+PhysDevExtTramp(237) PhysDevExtTermin(237)
+PhysDevExtTramp(238) PhysDevExtTermin(238)
+PhysDevExtTramp(239) PhysDevExtTermin(239)
+PhysDevExtTramp(240) PhysDevExtTermin(240)
+PhysDevExtTramp(241) PhysDevExtTermin(241)
+PhysDevExtTramp(242) PhysDevExtTermin(242)
+PhysDevExtTramp(243) PhysDevExtTermin(243)
+PhysDevExtTramp(244) PhysDevExtTermin(244)
+PhysDevExtTramp(245) PhysDevExtTermin(245)
+PhysDevExtTramp(246) PhysDevExtTermin(246)
+PhysDevExtTramp(247) PhysDevExtTermin(247)
+PhysDevExtTramp(248) PhysDevExtTermin(248)
+PhysDevExtTramp(249) PhysDevExtTermin(249)
+
+
+void *loader_get_phys_dev_ext_tramp(uint32_t index) {
+ switch (index) {
+#define TRAMP_CASE_HANDLE(num) case num: return vkPhysDevExtTramp##num
+ TRAMP_CASE_HANDLE(0);
+ TRAMP_CASE_HANDLE(1);
+ TRAMP_CASE_HANDLE(2);
+ TRAMP_CASE_HANDLE(3);
+ TRAMP_CASE_HANDLE(4);
+ TRAMP_CASE_HANDLE(5);
+ TRAMP_CASE_HANDLE(6);
+ TRAMP_CASE_HANDLE(7);
+ TRAMP_CASE_HANDLE(8);
+ TRAMP_CASE_HANDLE(9);
+ TRAMP_CASE_HANDLE(10);
+ TRAMP_CASE_HANDLE(11);
+ TRAMP_CASE_HANDLE(12);
+ TRAMP_CASE_HANDLE(13);
+ TRAMP_CASE_HANDLE(14);
+ TRAMP_CASE_HANDLE(15);
+ TRAMP_CASE_HANDLE(16);
+ TRAMP_CASE_HANDLE(17);
+ TRAMP_CASE_HANDLE(18);
+ TRAMP_CASE_HANDLE(19);
+ TRAMP_CASE_HANDLE(20);
+ TRAMP_CASE_HANDLE(21);
+ TRAMP_CASE_HANDLE(22);
+ TRAMP_CASE_HANDLE(23);
+ TRAMP_CASE_HANDLE(24);
+ TRAMP_CASE_HANDLE(25);
+ TRAMP_CASE_HANDLE(26);
+ TRAMP_CASE_HANDLE(27);
+ TRAMP_CASE_HANDLE(28);
+ TRAMP_CASE_HANDLE(29);
+ TRAMP_CASE_HANDLE(30);
+ TRAMP_CASE_HANDLE(31);
+ TRAMP_CASE_HANDLE(32);
+ TRAMP_CASE_HANDLE(33);
+ TRAMP_CASE_HANDLE(34);
+ TRAMP_CASE_HANDLE(35);
+ TRAMP_CASE_HANDLE(36);
+ TRAMP_CASE_HANDLE(37);
+ TRAMP_CASE_HANDLE(38);
+ TRAMP_CASE_HANDLE(39);
+ TRAMP_CASE_HANDLE(40);
+ TRAMP_CASE_HANDLE(41);
+ TRAMP_CASE_HANDLE(42);
+ TRAMP_CASE_HANDLE(43);
+ TRAMP_CASE_HANDLE(44);
+ TRAMP_CASE_HANDLE(45);
+ TRAMP_CASE_HANDLE(46);
+ TRAMP_CASE_HANDLE(47);
+ TRAMP_CASE_HANDLE(48);
+ TRAMP_CASE_HANDLE(49);
+ TRAMP_CASE_HANDLE(50);
+ TRAMP_CASE_HANDLE(51);
+ TRAMP_CASE_HANDLE(52);
+ TRAMP_CASE_HANDLE(53);
+ TRAMP_CASE_HANDLE(54);
+ TRAMP_CASE_HANDLE(55);
+ TRAMP_CASE_HANDLE(56);
+ TRAMP_CASE_HANDLE(57);
+ TRAMP_CASE_HANDLE(58);
+ TRAMP_CASE_HANDLE(59);
+ TRAMP_CASE_HANDLE(60);
+ TRAMP_CASE_HANDLE(61);
+ TRAMP_CASE_HANDLE(62);
+ TRAMP_CASE_HANDLE(63);
+ TRAMP_CASE_HANDLE(64);
+ TRAMP_CASE_HANDLE(65);
+ TRAMP_CASE_HANDLE(66);
+ TRAMP_CASE_HANDLE(67);
+ TRAMP_CASE_HANDLE(68);
+ TRAMP_CASE_HANDLE(69);
+ TRAMP_CASE_HANDLE(70);
+ TRAMP_CASE_HANDLE(71);
+ TRAMP_CASE_HANDLE(72);
+ TRAMP_CASE_HANDLE(73);
+ TRAMP_CASE_HANDLE(74);
+ TRAMP_CASE_HANDLE(75);
+ TRAMP_CASE_HANDLE(76);
+ TRAMP_CASE_HANDLE(77);
+ TRAMP_CASE_HANDLE(78);
+ TRAMP_CASE_HANDLE(79);
+ TRAMP_CASE_HANDLE(80);
+ TRAMP_CASE_HANDLE(81);
+ TRAMP_CASE_HANDLE(82);
+ TRAMP_CASE_HANDLE(83);
+ TRAMP_CASE_HANDLE(84);
+ TRAMP_CASE_HANDLE(85);
+ TRAMP_CASE_HANDLE(86);
+ TRAMP_CASE_HANDLE(87);
+ TRAMP_CASE_HANDLE(88);
+ TRAMP_CASE_HANDLE(89);
+ TRAMP_CASE_HANDLE(90);
+ TRAMP_CASE_HANDLE(91);
+ TRAMP_CASE_HANDLE(92);
+ TRAMP_CASE_HANDLE(93);
+ TRAMP_CASE_HANDLE(94);
+ TRAMP_CASE_HANDLE(95);
+ TRAMP_CASE_HANDLE(96);
+ TRAMP_CASE_HANDLE(97);
+ TRAMP_CASE_HANDLE(98);
+ TRAMP_CASE_HANDLE(99);
+ TRAMP_CASE_HANDLE(100);
+ TRAMP_CASE_HANDLE(101);
+ TRAMP_CASE_HANDLE(102);
+ TRAMP_CASE_HANDLE(103);
+ TRAMP_CASE_HANDLE(104);
+ TRAMP_CASE_HANDLE(105);
+ TRAMP_CASE_HANDLE(106);
+ TRAMP_CASE_HANDLE(107);
+ TRAMP_CASE_HANDLE(108);
+ TRAMP_CASE_HANDLE(109);
+ TRAMP_CASE_HANDLE(110);
+ TRAMP_CASE_HANDLE(111);
+ TRAMP_CASE_HANDLE(112);
+ TRAMP_CASE_HANDLE(113);
+ TRAMP_CASE_HANDLE(114);
+ TRAMP_CASE_HANDLE(115);
+ TRAMP_CASE_HANDLE(116);
+ TRAMP_CASE_HANDLE(117);
+ TRAMP_CASE_HANDLE(118);
+ TRAMP_CASE_HANDLE(119);
+ TRAMP_CASE_HANDLE(120);
+ TRAMP_CASE_HANDLE(121);
+ TRAMP_CASE_HANDLE(122);
+ TRAMP_CASE_HANDLE(123);
+ TRAMP_CASE_HANDLE(124);
+ TRAMP_CASE_HANDLE(125);
+ TRAMP_CASE_HANDLE(126);
+ TRAMP_CASE_HANDLE(127);
+ TRAMP_CASE_HANDLE(128);
+ TRAMP_CASE_HANDLE(129);
+ TRAMP_CASE_HANDLE(130);
+ TRAMP_CASE_HANDLE(131);
+ TRAMP_CASE_HANDLE(132);
+ TRAMP_CASE_HANDLE(133);
+ TRAMP_CASE_HANDLE(134);
+ TRAMP_CASE_HANDLE(135);
+ TRAMP_CASE_HANDLE(136);
+ TRAMP_CASE_HANDLE(137);
+ TRAMP_CASE_HANDLE(138);
+ TRAMP_CASE_HANDLE(139);
+ TRAMP_CASE_HANDLE(140);
+ TRAMP_CASE_HANDLE(141);
+ TRAMP_CASE_HANDLE(142);
+ TRAMP_CASE_HANDLE(143);
+ TRAMP_CASE_HANDLE(144);
+ TRAMP_CASE_HANDLE(145);
+ TRAMP_CASE_HANDLE(146);
+ TRAMP_CASE_HANDLE(147);
+ TRAMP_CASE_HANDLE(148);
+ TRAMP_CASE_HANDLE(149);
+ TRAMP_CASE_HANDLE(150);
+ TRAMP_CASE_HANDLE(151);
+ TRAMP_CASE_HANDLE(152);
+ TRAMP_CASE_HANDLE(153);
+ TRAMP_CASE_HANDLE(154);
+ TRAMP_CASE_HANDLE(155);
+ TRAMP_CASE_HANDLE(156);
+ TRAMP_CASE_HANDLE(157);
+ TRAMP_CASE_HANDLE(158);
+ TRAMP_CASE_HANDLE(159);
+ TRAMP_CASE_HANDLE(160);
+ TRAMP_CASE_HANDLE(161);
+ TRAMP_CASE_HANDLE(162);
+ TRAMP_CASE_HANDLE(163);
+ TRAMP_CASE_HANDLE(164);
+ TRAMP_CASE_HANDLE(165);
+ TRAMP_CASE_HANDLE(166);
+ TRAMP_CASE_HANDLE(167);
+ TRAMP_CASE_HANDLE(168);
+ TRAMP_CASE_HANDLE(169);
+ TRAMP_CASE_HANDLE(170);
+ TRAMP_CASE_HANDLE(171);
+ TRAMP_CASE_HANDLE(172);
+ TRAMP_CASE_HANDLE(173);
+ TRAMP_CASE_HANDLE(174);
+ TRAMP_CASE_HANDLE(175);
+ TRAMP_CASE_HANDLE(176);
+ TRAMP_CASE_HANDLE(177);
+ TRAMP_CASE_HANDLE(178);
+ TRAMP_CASE_HANDLE(179);
+ TRAMP_CASE_HANDLE(180);
+ TRAMP_CASE_HANDLE(181);
+ TRAMP_CASE_HANDLE(182);
+ TRAMP_CASE_HANDLE(183);
+ TRAMP_CASE_HANDLE(184);
+ TRAMP_CASE_HANDLE(185);
+ TRAMP_CASE_HANDLE(186);
+ TRAMP_CASE_HANDLE(187);
+ TRAMP_CASE_HANDLE(188);
+ TRAMP_CASE_HANDLE(189);
+ TRAMP_CASE_HANDLE(190);
+ TRAMP_CASE_HANDLE(191);
+ TRAMP_CASE_HANDLE(192);
+ TRAMP_CASE_HANDLE(193);
+ TRAMP_CASE_HANDLE(194);
+ TRAMP_CASE_HANDLE(195);
+ TRAMP_CASE_HANDLE(196);
+ TRAMP_CASE_HANDLE(197);
+ TRAMP_CASE_HANDLE(198);
+ TRAMP_CASE_HANDLE(199);
+ TRAMP_CASE_HANDLE(200);
+ TRAMP_CASE_HANDLE(201);
+ TRAMP_CASE_HANDLE(202);
+ TRAMP_CASE_HANDLE(203);
+ TRAMP_CASE_HANDLE(204);
+ TRAMP_CASE_HANDLE(205);
+ TRAMP_CASE_HANDLE(206);
+ TRAMP_CASE_HANDLE(207);
+ TRAMP_CASE_HANDLE(208);
+ TRAMP_CASE_HANDLE(209);
+ TRAMP_CASE_HANDLE(210);
+ TRAMP_CASE_HANDLE(211);
+ TRAMP_CASE_HANDLE(212);
+ TRAMP_CASE_HANDLE(213);
+ TRAMP_CASE_HANDLE(214);
+ TRAMP_CASE_HANDLE(215);
+ TRAMP_CASE_HANDLE(216);
+ TRAMP_CASE_HANDLE(217);
+ TRAMP_CASE_HANDLE(218);
+ TRAMP_CASE_HANDLE(219);
+ TRAMP_CASE_HANDLE(220);
+ TRAMP_CASE_HANDLE(221);
+ TRAMP_CASE_HANDLE(222);
+ TRAMP_CASE_HANDLE(223);
+ TRAMP_CASE_HANDLE(224);
+ TRAMP_CASE_HANDLE(225);
+ TRAMP_CASE_HANDLE(226);
+ TRAMP_CASE_HANDLE(227);
+ TRAMP_CASE_HANDLE(228);
+ TRAMP_CASE_HANDLE(229);
+ TRAMP_CASE_HANDLE(230);
+ TRAMP_CASE_HANDLE(231);
+ TRAMP_CASE_HANDLE(232);
+ TRAMP_CASE_HANDLE(233);
+ TRAMP_CASE_HANDLE(234);
+ TRAMP_CASE_HANDLE(235);
+ TRAMP_CASE_HANDLE(236);
+ TRAMP_CASE_HANDLE(237);
+ TRAMP_CASE_HANDLE(238);
+ TRAMP_CASE_HANDLE(239);
+ TRAMP_CASE_HANDLE(240);
+ TRAMP_CASE_HANDLE(241);
+ TRAMP_CASE_HANDLE(242);
+ TRAMP_CASE_HANDLE(243);
+ TRAMP_CASE_HANDLE(244);
+ TRAMP_CASE_HANDLE(245);
+ TRAMP_CASE_HANDLE(246);
+ TRAMP_CASE_HANDLE(247);
+ TRAMP_CASE_HANDLE(248);
+ TRAMP_CASE_HANDLE(249);
+ }
+ return NULL;
+}
+
+void *loader_get_phys_dev_ext_termin(uint32_t index) {
+ switch (index) {
+#define TERM_CASE_HANDLE(num) case num: return vkPhysDevExtTermin##num
+ TERM_CASE_HANDLE(0);
+ TERM_CASE_HANDLE(1);
+ TERM_CASE_HANDLE(2);
+ TERM_CASE_HANDLE(3);
+ TERM_CASE_HANDLE(4);
+ TERM_CASE_HANDLE(5);
+ TERM_CASE_HANDLE(6);
+ TERM_CASE_HANDLE(7);
+ TERM_CASE_HANDLE(8);
+ TERM_CASE_HANDLE(9);
+ TERM_CASE_HANDLE(10);
+ TERM_CASE_HANDLE(11);
+ TERM_CASE_HANDLE(12);
+ TERM_CASE_HANDLE(13);
+ TERM_CASE_HANDLE(14);
+ TERM_CASE_HANDLE(15);
+ TERM_CASE_HANDLE(16);
+ TERM_CASE_HANDLE(17);
+ TERM_CASE_HANDLE(18);
+ TERM_CASE_HANDLE(19);
+ TERM_CASE_HANDLE(20);
+ TERM_CASE_HANDLE(21);
+ TERM_CASE_HANDLE(22);
+ TERM_CASE_HANDLE(23);
+ TERM_CASE_HANDLE(24);
+ TERM_CASE_HANDLE(25);
+ TERM_CASE_HANDLE(26);
+ TERM_CASE_HANDLE(27);
+ TERM_CASE_HANDLE(28);
+ TERM_CASE_HANDLE(29);
+ TERM_CASE_HANDLE(30);
+ TERM_CASE_HANDLE(31);
+ TERM_CASE_HANDLE(32);
+ TERM_CASE_HANDLE(33);
+ TERM_CASE_HANDLE(34);
+ TERM_CASE_HANDLE(35);
+ TERM_CASE_HANDLE(36);
+ TERM_CASE_HANDLE(37);
+ TERM_CASE_HANDLE(38);
+ TERM_CASE_HANDLE(39);
+ TERM_CASE_HANDLE(40);
+ TERM_CASE_HANDLE(41);
+ TERM_CASE_HANDLE(42);
+ TERM_CASE_HANDLE(43);
+ TERM_CASE_HANDLE(44);
+ TERM_CASE_HANDLE(45);
+ TERM_CASE_HANDLE(46);
+ TERM_CASE_HANDLE(47);
+ TERM_CASE_HANDLE(48);
+ TERM_CASE_HANDLE(49);
+ TERM_CASE_HANDLE(50);
+ TERM_CASE_HANDLE(51);
+ TERM_CASE_HANDLE(52);
+ TERM_CASE_HANDLE(53);
+ TERM_CASE_HANDLE(54);
+ TERM_CASE_HANDLE(55);
+ TERM_CASE_HANDLE(56);
+ TERM_CASE_HANDLE(57);
+ TERM_CASE_HANDLE(58);
+ TERM_CASE_HANDLE(59);
+ TERM_CASE_HANDLE(60);
+ TERM_CASE_HANDLE(61);
+ TERM_CASE_HANDLE(62);
+ TERM_CASE_HANDLE(63);
+ TERM_CASE_HANDLE(64);
+ TERM_CASE_HANDLE(65);
+ TERM_CASE_HANDLE(66);
+ TERM_CASE_HANDLE(67);
+ TERM_CASE_HANDLE(68);
+ TERM_CASE_HANDLE(69);
+ TERM_CASE_HANDLE(70);
+ TERM_CASE_HANDLE(71);
+ TERM_CASE_HANDLE(72);
+ TERM_CASE_HANDLE(73);
+ TERM_CASE_HANDLE(74);
+ TERM_CASE_HANDLE(75);
+ TERM_CASE_HANDLE(76);
+ TERM_CASE_HANDLE(77);
+ TERM_CASE_HANDLE(78);
+ TERM_CASE_HANDLE(79);
+ TERM_CASE_HANDLE(80);
+ TERM_CASE_HANDLE(81);
+ TERM_CASE_HANDLE(82);
+ TERM_CASE_HANDLE(83);
+ TERM_CASE_HANDLE(84);
+ TERM_CASE_HANDLE(85);
+ TERM_CASE_HANDLE(86);
+ TERM_CASE_HANDLE(87);
+ TERM_CASE_HANDLE(88);
+ TERM_CASE_HANDLE(89);
+ TERM_CASE_HANDLE(90);
+ TERM_CASE_HANDLE(91);
+ TERM_CASE_HANDLE(92);
+ TERM_CASE_HANDLE(93);
+ TERM_CASE_HANDLE(94);
+ TERM_CASE_HANDLE(95);
+ TERM_CASE_HANDLE(96);
+ TERM_CASE_HANDLE(97);
+ TERM_CASE_HANDLE(98);
+ TERM_CASE_HANDLE(99);
+ TERM_CASE_HANDLE(100);
+ TERM_CASE_HANDLE(101);
+ TERM_CASE_HANDLE(102);
+ TERM_CASE_HANDLE(103);
+ TERM_CASE_HANDLE(104);
+ TERM_CASE_HANDLE(105);
+ TERM_CASE_HANDLE(106);
+ TERM_CASE_HANDLE(107);
+ TERM_CASE_HANDLE(108);
+ TERM_CASE_HANDLE(109);
+ TERM_CASE_HANDLE(110);
+ TERM_CASE_HANDLE(111);
+ TERM_CASE_HANDLE(112);
+ TERM_CASE_HANDLE(113);
+ TERM_CASE_HANDLE(114);
+ TERM_CASE_HANDLE(115);
+ TERM_CASE_HANDLE(116);
+ TERM_CASE_HANDLE(117);
+ TERM_CASE_HANDLE(118);
+ TERM_CASE_HANDLE(119);
+ TERM_CASE_HANDLE(120);
+ TERM_CASE_HANDLE(121);
+ TERM_CASE_HANDLE(122);
+ TERM_CASE_HANDLE(123);
+ TERM_CASE_HANDLE(124);
+ TERM_CASE_HANDLE(125);
+ TERM_CASE_HANDLE(126);
+ TERM_CASE_HANDLE(127);
+ TERM_CASE_HANDLE(128);
+ TERM_CASE_HANDLE(129);
+ TERM_CASE_HANDLE(130);
+ TERM_CASE_HANDLE(131);
+ TERM_CASE_HANDLE(132);
+ TERM_CASE_HANDLE(133);
+ TERM_CASE_HANDLE(134);
+ TERM_CASE_HANDLE(135);
+ TERM_CASE_HANDLE(136);
+ TERM_CASE_HANDLE(137);
+ TERM_CASE_HANDLE(138);
+ TERM_CASE_HANDLE(139);
+ TERM_CASE_HANDLE(140);
+ TERM_CASE_HANDLE(141);
+ TERM_CASE_HANDLE(142);
+ TERM_CASE_HANDLE(143);
+ TERM_CASE_HANDLE(144);
+ TERM_CASE_HANDLE(145);
+ TERM_CASE_HANDLE(146);
+ TERM_CASE_HANDLE(147);
+ TERM_CASE_HANDLE(148);
+ TERM_CASE_HANDLE(149);
+ TERM_CASE_HANDLE(150);
+ TERM_CASE_HANDLE(151);
+ TERM_CASE_HANDLE(152);
+ TERM_CASE_HANDLE(153);
+ TERM_CASE_HANDLE(154);
+ TERM_CASE_HANDLE(155);
+ TERM_CASE_HANDLE(156);
+ TERM_CASE_HANDLE(157);
+ TERM_CASE_HANDLE(158);
+ TERM_CASE_HANDLE(159);
+ TERM_CASE_HANDLE(160);
+ TERM_CASE_HANDLE(161);
+ TERM_CASE_HANDLE(162);
+ TERM_CASE_HANDLE(163);
+ TERM_CASE_HANDLE(164);
+ TERM_CASE_HANDLE(165);
+ TERM_CASE_HANDLE(166);
+ TERM_CASE_HANDLE(167);
+ TERM_CASE_HANDLE(168);
+ TERM_CASE_HANDLE(169);
+ TERM_CASE_HANDLE(170);
+ TERM_CASE_HANDLE(171);
+ TERM_CASE_HANDLE(172);
+ TERM_CASE_HANDLE(173);
+ TERM_CASE_HANDLE(174);
+ TERM_CASE_HANDLE(175);
+ TERM_CASE_HANDLE(176);
+ TERM_CASE_HANDLE(177);
+ TERM_CASE_HANDLE(178);
+ TERM_CASE_HANDLE(179);
+ TERM_CASE_HANDLE(180);
+ TERM_CASE_HANDLE(181);
+ TERM_CASE_HANDLE(182);
+ TERM_CASE_HANDLE(183);
+ TERM_CASE_HANDLE(184);
+ TERM_CASE_HANDLE(185);
+ TERM_CASE_HANDLE(186);
+ TERM_CASE_HANDLE(187);
+ TERM_CASE_HANDLE(188);
+ TERM_CASE_HANDLE(189);
+ TERM_CASE_HANDLE(190);
+ TERM_CASE_HANDLE(191);
+ TERM_CASE_HANDLE(192);
+ TERM_CASE_HANDLE(193);
+ TERM_CASE_HANDLE(194);
+ TERM_CASE_HANDLE(195);
+ TERM_CASE_HANDLE(196);
+ TERM_CASE_HANDLE(197);
+ TERM_CASE_HANDLE(198);
+ TERM_CASE_HANDLE(199);
+ TERM_CASE_HANDLE(200);
+ TERM_CASE_HANDLE(201);
+ TERM_CASE_HANDLE(202);
+ TERM_CASE_HANDLE(203);
+ TERM_CASE_HANDLE(204);
+ TERM_CASE_HANDLE(205);
+ TERM_CASE_HANDLE(206);
+ TERM_CASE_HANDLE(207);
+ TERM_CASE_HANDLE(208);
+ TERM_CASE_HANDLE(209);
+ TERM_CASE_HANDLE(210);
+ TERM_CASE_HANDLE(211);
+ TERM_CASE_HANDLE(212);
+ TERM_CASE_HANDLE(213);
+ TERM_CASE_HANDLE(214);
+ TERM_CASE_HANDLE(215);
+ TERM_CASE_HANDLE(216);
+ TERM_CASE_HANDLE(217);
+ TERM_CASE_HANDLE(218);
+ TERM_CASE_HANDLE(219);
+ TERM_CASE_HANDLE(220);
+ TERM_CASE_HANDLE(221);
+ TERM_CASE_HANDLE(222);
+ TERM_CASE_HANDLE(223);
+ TERM_CASE_HANDLE(224);
+ TERM_CASE_HANDLE(225);
+ TERM_CASE_HANDLE(226);
+ TERM_CASE_HANDLE(227);
+ TERM_CASE_HANDLE(228);
+ TERM_CASE_HANDLE(229);
+ TERM_CASE_HANDLE(230);
+ TERM_CASE_HANDLE(231);
+ TERM_CASE_HANDLE(232);
+ TERM_CASE_HANDLE(233);
+ TERM_CASE_HANDLE(234);
+ TERM_CASE_HANDLE(235);
+ TERM_CASE_HANDLE(236);
+ TERM_CASE_HANDLE(237);
+ TERM_CASE_HANDLE(238);
+ TERM_CASE_HANDLE(239);
+ TERM_CASE_HANDLE(240);
+ TERM_CASE_HANDLE(241);
+ TERM_CASE_HANDLE(242);
+ TERM_CASE_HANDLE(243);
+ TERM_CASE_HANDLE(244);
+ TERM_CASE_HANDLE(245);
+ TERM_CASE_HANDLE(246);
+ TERM_CASE_HANDLE(247);
+ TERM_CASE_HANDLE(248);
+ TERM_CASE_HANDLE(249);
+ }
+ return NULL;
+}
diff --git a/loader/table_ops.h b/loader/table_ops.h
index eecc952a..b3b90795 100644
--- a/loader/table_ops.h
+++ b/loader/table_ops.h
@@ -46,7 +46,7 @@ static inline void
loader_init_device_dispatch_table(struct loader_dev_dispatch_table *dev_table,
PFN_vkGetDeviceProcAddr gpa, VkDevice dev) {
VkLayerDispatchTable *table = &dev_table->core_dispatch;
- for (uint32_t i = 0; i < MAX_NUM_DEV_EXTS; i++)
+ for (uint32_t i = 0; i < MAX_NUM_UNKNOWN_EXTS; i++)
dev_table->ext_dispatch.dev_ext[i] = (PFN_vkDevExt)vkDevExtError;
table->GetDeviceProcAddr =
@@ -269,27 +269,49 @@ static inline void loader_init_device_extension_dispatch_table(
(PFN_vkGetSwapchainImagesKHR)gpa(dev, "vkGetSwapchainImagesKHR");
table->QueuePresentKHR =
(PFN_vkQueuePresentKHR)gpa(dev, "vkQueuePresentKHR");
+
+ // KHR_display_swapchain
+ table->CreateSharedSwapchainsKHR = (PFN_vkCreateSharedSwapchainsKHR)gpa(
+ dev, "vkCreateSharedSwapchainsKHR");
+
+ // KHR_maintenance1
+ table->TrimCommandPoolKHR =
+ (PFN_vkTrimCommandPoolKHR)gpa(dev, "vkTrimCommandPoolKHR");
+
+ // EXT_display_control
+ table->DisplayPowerControlEXT =
+ (PFN_vkDisplayPowerControlEXT)gpa(dev, "vkDisplayPowerControlEXT");
+ table->RegisterDeviceEventEXT =
+ (PFN_vkRegisterDeviceEventEXT)gpa(dev, "vkRegisterDeviceEventEXT");
+ table->RegisterDisplayEventEXT =
+ (PFN_vkRegisterDisplayEventEXT)gpa(dev, "vkRegisterDisplayEventEXT");
+ table->GetSwapchainCounterEXT =
+ (PFN_vkGetSwapchainCounterEXT)gpa(dev, "vkGetSwapchainCounterEXT");
+
+ // EXT_debug_marker
+ table->DebugMarkerSetObjectTagEXT = (PFN_vkDebugMarkerSetObjectTagEXT)gpa(
+ dev, "vkDebugMarkerSetObjectTagEXT");
+ table->DebugMarkerSetObjectNameEXT = (PFN_vkDebugMarkerSetObjectNameEXT)gpa(
+ dev, "vkDebugMarkerSetObjectNameEXT");
+ table->CmdDebugMarkerBeginEXT =
+ (PFN_vkCmdDebugMarkerBeginEXT)gpa(dev, "vkCmdDebugMarkerBeginEXT");
+ table->CmdDebugMarkerEndEXT =
+ (PFN_vkCmdDebugMarkerEndEXT)gpa(dev, "vkCmdDebugMarkerEndEXT");
+ table->CmdDebugMarkerInsertEXT =
+ (PFN_vkCmdDebugMarkerInsertEXT)gpa(dev, "vkCmdDebugMarkerInsertEXT");
+
+ // AMD_draw_indirect_count
table->CmdDrawIndirectCountAMD =
(PFN_vkCmdDrawIndirectCountAMD)gpa(dev, "vkCmdDrawIndirectCountAMD");
table->CmdDrawIndexedIndirectCountAMD =
(PFN_vkCmdDrawIndexedIndirectCountAMD)gpa(
dev, "vkCmdDrawIndexedIndirectCountAMD");
+
#ifdef VK_USE_PLATFORM_WIN32_KHR
+ // NV_external_memory_win32
table->GetMemoryWin32HandleNV =
(PFN_vkGetMemoryWin32HandleNV)gpa(dev, "vkGetMemoryWin32HandleNV");
-#endif // VK_USE_PLATFORM_WIN32_KHR
- table->CreateSharedSwapchainsKHR =
- (PFN_vkCreateSharedSwapchainsKHR)gpa(dev, "vkCreateSharedSwapchainsKHR");
- table->DebugMarkerSetObjectTagEXT =
- (PFN_vkDebugMarkerSetObjectTagEXT)gpa(dev, "vkDebugMarkerSetObjectTagEXT");
- table->DebugMarkerSetObjectNameEXT =
- (PFN_vkDebugMarkerSetObjectNameEXT)gpa(dev, "vkDebugMarkerSetObjectNameEXT");
- table->CmdDebugMarkerBeginEXT =
- (PFN_vkCmdDebugMarkerBeginEXT)gpa(dev, "vkCmdDebugMarkerBeginEXT");
- table->CmdDebugMarkerEndEXT =
- (PFN_vkCmdDebugMarkerEndEXT)gpa(dev, "vkCmdDebugMarkerEndEXT");
- table->CmdDebugMarkerInsertEXT =
- (PFN_vkCmdDebugMarkerInsertEXT)gpa(dev, "vkCmdDebugMarkerInsertEXT");
+#endif
// NVX_device_generated_commands
table->CmdProcessCommandsNVX =
@@ -562,7 +584,6 @@ loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table,
return (void *)table->CmdEndRenderPass;
if (!strcmp(name, "CmdExecuteCommands"))
return (void *)table->CmdExecuteCommands;
-
if (!strcmp(name, "DestroySwapchainKHR"))
return (void *)table->DestroySwapchainKHR;
if (!strcmp(name, "GetSwapchainImagesKHR"))
@@ -580,6 +601,8 @@ loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table,
// object before passing the appropriate info along to the ICD.
if (!strcmp(name, "CreateSwapchainKHR")) {
return (void *)vkCreateSwapchainKHR;
+ } else if (!strcmp(name, "CreateSharedSwapchainsKHR")) {
+ return (void *)vkCreateSharedSwapchainsKHR;
} else if (!strcmp(name, "DebugMarkerSetObjectTagEXT")) {
return (void *)vkDebugMarkerSetObjectTagEXT;
} else if (!strcmp(name, "DebugMarkerSetObjectNameEXT")) {
@@ -629,16 +652,9 @@ loader_init_instance_core_dispatch_table(VkLayerInstanceDispatchTable *table,
static inline void loader_init_instance_extension_dispatch_table(
VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa,
VkInstance inst) {
+ // WSI extensions
table->DestroySurfaceKHR =
(PFN_vkDestroySurfaceKHR)gpa(inst, "vkDestroySurfaceKHR");
- table->CreateDebugReportCallbackEXT =
- (PFN_vkCreateDebugReportCallbackEXT)gpa(
- inst, "vkCreateDebugReportCallbackEXT");
- table->DestroyDebugReportCallbackEXT =
- (PFN_vkDestroyDebugReportCallbackEXT)gpa(
- inst, "vkDestroyDebugReportCallbackEXT");
- table->DebugReportMessageEXT =
- (PFN_vkDebugReportMessageEXT)gpa(inst, "vkDebugReportMessageEXT");
table->GetPhysicalDeviceSurfaceSupportKHR =
(PFN_vkGetPhysicalDeviceSurfaceSupportKHR)gpa(
inst, "vkGetPhysicalDeviceSurfaceSupportKHR");
@@ -651,9 +667,6 @@ static inline void loader_init_instance_extension_dispatch_table(
table->GetPhysicalDeviceSurfacePresentModesKHR =
(PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)gpa(
inst, "vkGetPhysicalDeviceSurfacePresentModesKHR");
- table->GetPhysicalDeviceExternalImageFormatPropertiesNV =
- (PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)gpa(
- inst, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV");
#ifdef VK_USE_PLATFORM_MIR_KHR
table->CreateMirSurfaceKHR =
(PFN_vkCreateMirSurfaceKHR)gpa(inst, "vkCreateMirSurfaceKHR");
@@ -709,12 +722,125 @@ static inline void loader_init_instance_extension_dispatch_table(
(PFN_vkCreateDisplayPlaneSurfaceKHR)gpa(
inst, "vkCreateDisplayPlaneSurfaceKHR");
- // NVX_device_generated_commands (physical device commands)
+ // KHR_get_physical_device_properties2
+ table->GetPhysicalDeviceFeatures2KHR =
+ (PFN_vkGetPhysicalDeviceFeatures2KHR)gpa(
+ inst, "vkGetPhysicalDeviceFeatures2KHR");
+ table->GetPhysicalDeviceProperties2KHR =
+ (PFN_vkGetPhysicalDeviceProperties2KHR)gpa(
+ inst, "vkGetPhysicalDeviceProperties2KHR");
+ table->GetPhysicalDeviceFormatProperties2KHR =
+ (PFN_vkGetPhysicalDeviceFormatProperties2KHR)gpa(
+ inst, "vkGetPhysicalDeviceFormatProperties2KHR");
+ table->GetPhysicalDeviceImageFormatProperties2KHR =
+ (PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)gpa(
+ inst, "vkGetPhysicalDeviceImageFormatProperties2KHR");
+ table->GetPhysicalDeviceQueueFamilyProperties2KHR =
+ (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)gpa(
+ inst, "vkGetPhysicalDeviceQueueFamilyProperties2KHR");
+ table->GetPhysicalDeviceMemoryProperties2KHR =
+ (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)gpa(
+ inst, "vkGetPhysicalDeviceMemoryProperties2KHR");
+ table->GetPhysicalDeviceSparseImageFormatProperties2KHR =
+ (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)gpa(
+ inst, "vkGetPhysicalDeviceSparseImageFormatProperties2KHR");
+
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ // EXT_acquire_xlib_display
+ table->AcquireXlibDisplayEXT =
+ (PFN_vkAcquireXlibDisplayEXT)gpa(inst, "vkAcquireXlibDisplayEXT");
+ table->GetRandROutputDisplayEXT =
+ (PFN_vkGetRandROutputDisplayEXT)gpa(inst, "vkGetRandROutputDisplayEXT");
+#endif
+
+ // EXT_debug_report
+ table->CreateDebugReportCallbackEXT =
+ (PFN_vkCreateDebugReportCallbackEXT)gpa(
+ inst, "vkCreateDebugReportCallbackEXT");
+ table->DestroyDebugReportCallbackEXT =
+ (PFN_vkDestroyDebugReportCallbackEXT)gpa(
+ inst, "vkDestroyDebugReportCallbackEXT");
+ table->DebugReportMessageEXT =
+ (PFN_vkDebugReportMessageEXT)gpa(inst, "vkDebugReportMessageEXT");
+
+ // EXT_direct_mode_display
+ table->ReleaseDisplayEXT =
+ (PFN_vkReleaseDisplayEXT)gpa(inst, "vkReleaseDisplayEXT");
+
+ // EXT_display_surface_counter
+ table->GetPhysicalDeviceSurfaceCapabilities2EXT =
+ (PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT)gpa(
+ inst, "vkGetPhysicalDeviceSurfaceCapabilities2EXT");
+
+ // NV_external_memory_capabilities
+ table->GetPhysicalDeviceExternalImageFormatPropertiesNV =
+ (PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV)gpa(
+ inst, "vkGetPhysicalDeviceExternalImageFormatPropertiesNV");
+
+ // NVX_device_generated_commands (physical device command)
table->GetPhysicalDeviceGeneratedCommandsPropertiesNVX =
(PFN_vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX)gpa(
inst, "vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX");
}
+static inline void *loader_lookup_instance_extension_dispatch_table(
+ const VkLayerInstanceDispatchTable *table, const char *name,
+ bool *found_name) {
+
+ *found_name = true;
+
+ // KHR_get_physical_device_properties2
+ if (!strcmp(name, "GetPhysicalDeviceFeatures2KHR"))
+ return (void *)table->GetPhysicalDeviceFeatures2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceProperties2KHR"))
+ return (void *)table->GetPhysicalDeviceProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceFormatProperties2KHR"))
+ return (void *)table->GetPhysicalDeviceFormatProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceImageFormatProperties2KHR"))
+ return (void *)table->GetPhysicalDeviceImageFormatProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceQueueFamilyProperties2KHR"))
+ return (void *)table->GetPhysicalDeviceQueueFamilyProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceMemoryProperties2KHR"))
+ return (void *)table->GetPhysicalDeviceMemoryProperties2KHR;
+ if (!strcmp(name, "GetPhysicalDeviceSparseImageFormatProperties2KHR"))
+ return (void *)table->GetPhysicalDeviceSparseImageFormatProperties2KHR;
+
+// EXT_acquire_xlib_display
+#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
+ if (!strcmp(name, "AcquireXlibDisplayEXT"))
+ return (void *)table->AcquireXlibDisplayEXT;
+ if (!strcmp(name, "GetRandROutputDisplayEXT"))
+ return (void *)table->GetRandROutputDisplayEXT;
+#endif
+
+ // EXT_debug_report
+ if (!strcmp(name, "CreateDebugReportCallbackEXT"))
+ return (void *)table->CreateDebugReportCallbackEXT;
+ if (!strcmp(name, "DestroyDebugReportCallbackEXT"))
+ return (void *)table->DestroyDebugReportCallbackEXT;
+ if (!strcmp(name, "DebugReportMessageEXT"))
+ return (void *)table->DebugReportMessageEXT;
+
+ // EXT_direct_mode_display
+ if (!strcmp(name, "ReleaseDisplayEXT"))
+ return (void *)table->ReleaseDisplayEXT;
+
+ // EXT_display_surface_counter
+ if (!strcmp(name, "GetPhysicalDeviceSurfaceCapabilities2EXT"))
+ return (void *)table->GetPhysicalDeviceSurfaceCapabilities2EXT;
+
+ // NV_external_memory_capabilities
+ if (!strcmp(name, "GetPhysicalDeviceExternalImageFormatPropertiesNV"))
+ return (void *)table->GetPhysicalDeviceExternalImageFormatPropertiesNV;
+
+ // NVX_device_generated_commands
+ if (!strcmp(name, "GetPhysicalDeviceGeneratedCommandsPropertiesNVX"))
+ return (void *)table->GetPhysicalDeviceGeneratedCommandsPropertiesNVX;
+
+ *found_name = false;
+ return NULL;
+}
+
static inline void *
loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable *table,
const char *name, bool *found_name) {
@@ -759,8 +885,6 @@ loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable *table,
return (void *)table->GetPhysicalDeviceSurfaceFormatsKHR;
if (!strcmp(name, "GetPhysicalDeviceSurfacePresentModesKHR"))
return (void *)table->GetPhysicalDeviceSurfacePresentModesKHR;
- if (!strcmp(name, "GetPhysicalDeviceExternalImageFormatPropertiesNV"))
- return (void *)table->GetPhysicalDeviceExternalImageFormatPropertiesNV;
#ifdef VK_USE_PLATFORM_MIR_KHR
if (!strcmp(name, "CreateMirSurfaceKHR"))
return (void *)table->CreateMirSurfaceKHR;
@@ -806,17 +930,6 @@ loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable *table,
if (!strcmp(name, "CreateDisplayPlaneSurfaceKHR"))
return (void *)table->CreateDisplayPlaneSurfaceKHR;
- if (!strcmp(name, "CreateDebugReportCallbackEXT"))
- return (void *)table->CreateDebugReportCallbackEXT;
- if (!strcmp(name, "DestroyDebugReportCallbackEXT"))
- return (void *)table->DestroyDebugReportCallbackEXT;
- if (!strcmp(name, "DebugReportMessageEXT"))
- return (void *)table->DebugReportMessageEXT;
-
- // NVX_device_generated_commands
- if (!strcmp(name, "GetPhysicalDeviceGeneratedCommandsPropertiesNVX"))
- return (void *)table->GetPhysicalDeviceGeneratedCommandsPropertiesNVX;
-
- *found_name = false;
- return NULL;
+ return loader_lookup_instance_extension_dispatch_table(table, name,
+ found_name);
}
diff --git a/loader/trampoline.c b/loader/trampoline.c
index 257ece7b..4d14f581 100644
--- a/loader/trampoline.c
+++ b/loader/trampoline.c
@@ -409,6 +409,8 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
&created_instance);
if (res == VK_SUCCESS) {
+ memset(ptr_instance->enabled_known_extensions.padding, 0, sizeof(uint64_t) * 4);
+
wsi_create_instance(ptr_instance, &ici);
debug_report_create_instance(ptr_instance, &ici);
extensions_create_instance(ptr_instance, &ici);
@@ -484,7 +486,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(
return;
}
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
loader_platform_thread_lock_mutex(&loader_lock);
@@ -508,6 +510,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(
loader_deactivate_layers(ptr_instance, NULL,
&ptr_instance->activated_layer_list);
+
if (ptr_instance->phys_devs_tramp) {
for (uint32_t i = 0; i < ptr_instance->phys_dev_count_tramp; i++) {
loader_instance_heap_free(ptr_instance,
@@ -515,6 +518,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(
}
loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_tramp);
}
+
if (callback_setup) {
util_DestroyDebugReportCallbacks(ptr_instance, pAllocator,
ptr_instance->num_tmp_callbacks,
@@ -535,7 +539,7 @@ vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
VkResult res = VK_SUCCESS;
uint32_t count, i;
struct loader_instance *inst;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
loader_platform_thread_lock_mutex(&loader_lock);
@@ -594,7 +598,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
disp->GetPhysicalDeviceFeatures(unwrapped_phys_dev, pFeatures);
}
@@ -604,7 +608,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_pd =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
disp->GetPhysicalDeviceFormatProperties(unwrapped_pd, format, pFormatInfo);
}
@@ -616,7 +620,7 @@ vkGetPhysicalDeviceImageFormatProperties(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
return disp->GetPhysicalDeviceImageFormatProperties(
unwrapped_phys_dev, format, type, tiling, usage, flags,
pImageFormatProperties);
@@ -627,7 +631,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
disp->GetPhysicalDeviceProperties(unwrapped_phys_dev, pProperties);
}
@@ -638,7 +642,7 @@ vkGetPhysicalDeviceQueueFamilyProperties(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
disp->GetPhysicalDeviceQueueFamilyProperties(
unwrapped_phys_dev, pQueueFamilyPropertyCount, pQueueProperties);
}
@@ -649,7 +653,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
disp->GetPhysicalDeviceMemoryProperties(unwrapped_phys_dev,
pMemoryProperties);
}
@@ -682,7 +686,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(
}
res = loader_add_device_extensions(
- inst, inst->disp->EnumerateDeviceExtensionProperties,
+ inst, inst->disp->layer_inst_disp.EnumerateDeviceExtensionProperties,
phys_dev->phys_dev, "Unknown", &icd_exts);
if (res != VK_SUCCESS) {
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
@@ -801,7 +805,7 @@ vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
if (pLayerName == NULL || strlen(pLayerName) == 0) {
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
res = disp->EnumerateDeviceExtensionProperties(
phys_dev->phys_dev, NULL, pPropertyCount, pProperties);
} else {
@@ -1147,7 +1151,7 @@ vkGetPhysicalDeviceSparseImageFormatProperties(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
disp->GetPhysicalDeviceSparseImageFormatProperties(
unwrapped_phys_dev, format, type, samples, usage, tiling,
diff --git a/loader/vulkan-1.def b/loader/vulkan-1.def
index e8e36260..2f67eb4c 100644
--- a/loader/vulkan-1.def
+++ b/loader/vulkan-1.def
@@ -1,9 +1,9 @@
;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
-; Copyright (c) 2015-2016 The Khronos Group Inc.
-; Copyright (c) 2015-2016 Valve Corporation
-; Copyright (c) 2015-2016 LunarG, Inc.
+; Copyright (c) 2015-2017 The Khronos Group Inc.
+; Copyright (c) 2015-2017 Valve Corporation
+; Copyright (c) 2015-2017 LunarG, Inc.
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
diff --git a/loader/wsi.c b/loader/wsi.c
index c577063b..b2e96f8d 100644
--- a/loader/wsi.c
+++ b/loader/wsi.c
@@ -152,7 +152,7 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL
vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface,
const VkAllocationCallbacks *pAllocator) {
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
disp->DestroySurfaceKHR(instance, surface, pAllocator);
}
@@ -205,7 +205,7 @@ vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->GetPhysicalDeviceSurfaceSupportKHR(
unwrapped_phys_dev, queueFamilyIndex, surface, pSupported);
return res;
@@ -261,7 +261,7 @@ vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->GetPhysicalDeviceSurfaceCapabilitiesKHR(
unwrapped_phys_dev, surface, pSurfaceCapabilities);
return res;
@@ -317,7 +317,7 @@ vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->GetPhysicalDeviceSurfaceFormatsKHR(
unwrapped_phys_dev, surface, pSurfaceFormatCount, pSurfaceFormats);
return res;
@@ -373,7 +373,7 @@ vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->GetPhysicalDeviceSurfacePresentModesKHR(
unwrapped_phys_dev, surface, pPresentModeCount, pPresentModes);
return res;
@@ -548,7 +548,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
VkResult res;
res = disp->CreateWin32SurfaceKHR(instance, pCreateInfo, pAllocator,
@@ -638,7 +638,7 @@ vkGetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkBool32 res = disp->GetPhysicalDeviceWin32PresentationSupportKHR(
unwrapped_phys_dev, queueFamilyIndex);
return res;
@@ -682,7 +682,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR(
VkInstance instance, const VkMirSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
VkResult res;
res =
@@ -771,7 +771,7 @@ vkGetPhysicalDeviceMirPresentationSupportKHR(VkPhysicalDevice physicalDevice,
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkBool32 res = disp->GetPhysicalDeviceMirPresentationSupportKHR(
unwrapped_phys_dev, queueFamilyIndex, connection);
return res;
@@ -818,7 +818,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
VkResult res;
res = disp->CreateWaylandSurfaceKHR(instance, pCreateInfo, pAllocator,
@@ -907,7 +907,7 @@ vkGetPhysicalDeviceWaylandPresentationSupportKHR(
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkBool32 res = disp->GetPhysicalDeviceWaylandPresentationSupportKHR(
unwrapped_phys_dev, queueFamilyIndex, display);
return res;
@@ -953,7 +953,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
VkResult res;
res =
@@ -1043,7 +1043,7 @@ vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkBool32 res = disp->GetPhysicalDeviceXcbPresentationSupportKHR(
unwrapped_phys_dev, queueFamilyIndex, connection, visual_id);
return res;
@@ -1089,7 +1089,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
VkResult res;
res =
@@ -1178,7 +1178,7 @@ vkGetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkBool32 res = disp->GetPhysicalDeviceXlibPresentationSupportKHR(
unwrapped_phys_dev, queueFamilyIndex, dpy, visualID);
return res;
@@ -1224,7 +1224,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
VkInstance instance, ANativeWindow *window,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
VkResult res;
res = disp->CreateAndroidSurfaceKHR(instance, window, pAllocator, pSurface);
@@ -1271,7 +1271,7 @@ vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice,
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->GetPhysicalDeviceDisplayPropertiesKHR(
unwrapped_phys_dev, pPropertyCount, pProperties);
return res;
@@ -1309,7 +1309,7 @@ vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->GetPhysicalDeviceDisplayPlanePropertiesKHR(
unwrapped_phys_dev, pPropertyCount, pProperties);
return res;
@@ -1351,7 +1351,7 @@ vkGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice,
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->GetDisplayPlaneSupportedDisplaysKHR(
unwrapped_phys_dev, planeIndex, pDisplayCount, pDisplays);
return res;
@@ -1388,7 +1388,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR(
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->GetDisplayModePropertiesKHR(
unwrapped_phys_dev, display, pPropertyCount, pProperties);
return res;
@@ -1426,7 +1426,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR(
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->CreateDisplayModeKHR(unwrapped_phys_dev, display,
pCreateInfo, pAllocator, pMode);
return res;
@@ -1464,7 +1464,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR(
VkPhysicalDevice unwrapped_phys_dev =
loader_unwrap_physical_device(physicalDevice);
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(physicalDevice);
+ disp = loader_get_instance_layer_dispatch(physicalDevice);
VkResult res = disp->GetDisplayPlaneCapabilitiesKHR(
unwrapped_phys_dev, mode, planeIndex, pCapabilities);
return res;
@@ -1499,7 +1499,7 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR(
VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
const VkLayerInstanceDispatchTable *disp;
- disp = loader_get_instance_dispatch(instance);
+ disp = loader_get_instance_layer_dispatch(instance);
VkResult res;
res = disp->CreateDisplayPlaneSurfaceKHR(instance, pCreateInfo, pAllocator,
@@ -1581,8 +1581,8 @@ out:
return vkRes;
}
-// This is the trampoline entrypoint
-// for CreateSharedSwapchainsKHR
+// EXT_display_swapchain Extension command
+
LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR(
VkDevice device, uint32_t swapchainCount,
const VkSwapchainCreateInfoKHR *pCreateInfos,
@@ -1593,6 +1593,47 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR(
pAllocator, pSwapchains);
}
+VKAPI_ATTR VkResult VKAPI_CALL terminator_vkCreateSharedSwapchainsKHR(
+ VkDevice device, uint32_t swapchainCount,
+ const VkSwapchainCreateInfoKHR *pCreateInfos,
+ const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains) {
+ uint32_t icd_index = 0;
+ struct loader_device *dev;
+ struct loader_icd_term *icd_term =
+ loader_get_icd_and_device(device, &dev, &icd_index);
+ if (NULL != icd_term && NULL != icd_term->CreateSharedSwapchainsKHR) {
+ VkIcdSurface *icd_surface =
+ (VkIcdSurface *)(uintptr_t)pCreateInfos->surface;
+ if (NULL != icd_surface->real_icd_surfaces) {
+ if ((VkSurfaceKHR)NULL !=
+ icd_surface->real_icd_surfaces[icd_index]) {
+ // We found the ICD, and there is an ICD KHR surface
+ // associated with it, so copy the CreateInfo struct
+ // and point it at the ICD's surface.
+ VkSwapchainCreateInfoKHR *pCreateCopy =
+ loader_stack_alloc(sizeof(VkSwapchainCreateInfoKHR) *
+ swapchainCount);
+ if (NULL == pCreateCopy) {
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+ memcpy(pCreateCopy, pCreateInfos,
+ sizeof(VkSwapchainCreateInfoKHR) * swapchainCount);
+ for (uint32_t sc = 0; sc < swapchainCount; sc++) {
+ pCreateCopy[sc].surface =
+ icd_surface->real_icd_surfaces[icd_index];
+ }
+ return icd_term->CreateSharedSwapchainsKHR(
+ device, swapchainCount, pCreateCopy, pAllocator,
+ pSwapchains);
+ }
+ }
+ return icd_term->CreateSharedSwapchainsKHR(device, swapchainCount,
+ pCreateInfos, pAllocator,
+ pSwapchains);
+ }
+ return VK_SUCCESS;
+}
+
bool wsi_swapchain_instance_gpa(struct loader_instance *ptr_instance,
const char *name, void **addr) {
*addr = NULL;
diff --git a/loader/wsi.h b/loader/wsi.h
index 77cc183d..b93a53c7 100644
--- a/loader/wsi.h
+++ b/loader/wsi.h
@@ -169,4 +169,9 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(
VkInstance instance, const VkDisplaySurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
+VKAPI_ATTR VkResult VKAPI_CALL terminator_vkCreateSharedSwapchainsKHR(
+ VkDevice device, uint32_t swapchainCount,
+ const VkSwapchainCreateInfoKHR *pCreateInfos,
+ const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchains);
+
#endif /* WSI_H */