// Copyright 2015-2021 The Khronos Group, Inc.
//
// SPDX-License-Identifier: CC-BY-4.0

[[initialization]]
= Initialization

Before using Vulkan, an application must: initialize it by loading the
Vulkan commands, and creating a sname:VkInstance object.


[[initialization-functionpointers]]
== Command Function Pointers

Vulkan commands are not necessarily exposed by static linking on a platform.
Commands to query function pointers for Vulkan commands are described below.

[NOTE]
.Note
====
When extensions are <<extendingvulkan-compatibility-promotion,promoted>> or
otherwise incorporated into another extension or Vulkan core version,
command <<extendingvulkan-compatibility-aliases,aliases>> may be included.
Whilst the behavior of each command alias is identical, the behavior of
retrieving each alias's function pointer is not.
A function pointer for a given alias can only be retrieved if the extension
or version that introduced that alias is supported and enabled, irrespective
of whether any other alias is available.
====

[open,refpage='vkGetInstanceProcAddr',desc='Return a function pointer for a command',type='protos',xrefs='PFN_vkVoidFunction']
--
Function pointers for all Vulkan commands can: be obtained with the command:

include::{generated}/api/protos/vkGetInstanceProcAddr.txt[]

  * pname:instance is the instance that the function pointer will be
    compatible with, or `NULL` for commands not dependent on any instance.
  * pname:pName is the name of the command to obtain.

fname:vkGetInstanceProcAddr itself is obtained in a platform- and loader-
specific manner.
Typically, the loader library will export this command as a function symbol,
so applications can: link against the loader library, or load it dynamically
and look up the symbol using platform-specific APIs.

The table below defines the various use cases for
fname:vkGetInstanceProcAddr and expected return value ("`fp`" is "`function
pointer`") for each case.
A valid returned function pointer ("`fp`") must: not be `NULL`.

The returned function pointer is of type tlink:PFN_vkVoidFunction, and must:
be cast to the type of the command being queried before use.

.fname:vkGetInstanceProcAddr behavior
[width="80%",options="header"]
|====
| pname:instance   | pname:pName                                  | return value
| *^1^             | `NULL`                                       | undefined:
| invalid non-`NULL` instance | *^1^                              | undefined:
ifdef::VK_VERSION_1_2[]
| `NULL`           | flink:vkGetInstanceProcAddr                  | fp^4^
endif::VK_VERSION_1_2[]
ifdef::VK_VERSION_1_1[]
| `NULL`           | flink:vkEnumerateInstanceVersion             | fp
endif::VK_VERSION_1_1[]
| `NULL`           | flink:vkEnumerateInstanceExtensionProperties | fp
| `NULL`           | flink:vkEnumerateInstanceLayerProperties     | fp
| `NULL`           | flink:vkCreateInstance                       | fp
| instance         | core Vulkan command                          | fp^2^
| instance         | enabled instance extension commands for pname:instance    | fp^2^
| instance         | available device extension^3^ commands for pname:instance | fp^2^
2+|  any other case, not covered above                            | `NULL`
|====

1::
    "*" means any representable value for the parameter (including valid
    values, invalid values, and `NULL`).

2::
    The returned function pointer must: only be called with a dispatchable
    object (the first parameter) that is pname:instance or a child of
    pname:instance, e.g. slink:VkInstance, slink:VkPhysicalDevice,
    slink:VkDevice, slink:VkQueue, or slink:VkCommandBuffer.

3::
    An "`available device extension`" is a device extension supported by any
    physical device enumerated by pname:instance.

ifdef::VK_VERSION_1_2[]
4::
    Starting with Vulkan 1.2, fname:vkGetInstanceProcAddr can resolve itself
    with a `NULL` instance pointer.
endif::VK_VERSION_1_2[]

include::{generated}/validity/protos/vkGetInstanceProcAddr.txt[]
--

[open,refpage='vkGetDeviceProcAddr',desc='Return a function pointer for a command',type='protos',xrefs='PFN_vkVoidFunction']
--
In order to support systems with multiple Vulkan implementations, the
function pointers returned by fname:vkGetInstanceProcAddr may: point to
dispatch code that calls a different real implementation for different
slink:VkDevice objects or their child objects.
The overhead of the internal dispatch for slink:VkDevice objects can be
avoided by obtaining device-specific function pointers for any commands that
use a device or device-child object as their dispatchable object.
Such function pointers can: be obtained with the command:

include::{generated}/api/protos/vkGetDeviceProcAddr.txt[]

The table below defines the various use cases for fname:vkGetDeviceProcAddr
and expected return value ("`fp`" is "`function pointer`") for each case.
A valid returned function pointer ("`fp`") must: not be `NULL`.

The returned function pointer is of type tlink:PFN_vkVoidFunction, and must:
be cast to the type of the command being queried before use.
The function pointer must: only be called with a dispatchable object (the
first parameter) that is pname:device or a child of pname:device.

.fname:vkGetDeviceProcAddr behavior
[width="80%",options="header"]
|====
| pname:device   | pname:pName                      | return value
| `NULL`         | *^1^                             | undefined:
| invalid device | *^1^                             | undefined:
| device         | `NULL`                           | undefined:
| device         | core device-level Vulkan command^2^ | fp^3^
| device         | enabled extension device-level commands^2^ | fp^3^
2+| any other case, not covered above               | `NULL`
|====

1::
    "*" means any representable value for the parameter (including valid
    values, invalid values, and `NULL`).

2::
    In this function, device-level excludes all physical-device-level
    commands.

3::
    The returned function pointer must: only be called with a dispatchable
    object (the first parameter) that is pname:device or a child of
    pname:device e.g. slink:VkDevice, slink:VkQueue, or
    slink:VkCommandBuffer.

include::{generated}/validity/protos/vkGetDeviceProcAddr.txt[]
--

[open,refpage='PFN_vkVoidFunction',desc='Placeholder function pointer type returned by queries',type='funcpointers',xrefs='vkGetDeviceProcAddr vkGetInstanceProcAddr']
--
The definition of tlink:PFN_vkVoidFunction is:

include::{generated}/api/funcpointers/PFN_vkVoidFunction.txt[]
--


ifdef::VK_VERSION_1_1[]
=== Extending Physical Device Core Functionality

New core physical-device-level functionality can: be used when the
physical-device version is greater than or equal to the version of Vulkan
that added the new functionality.
The Vulkan version supported by a physical device can: be obtained by
calling flink:vkGetPhysicalDeviceProperties.
endif::VK_VERSION_1_1[]


ifdef::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]
[[initialization-phys-dev-extensions]]
=== Extending Physical Device From Device Extensions

When the `<<VK_KHR_get_physical_device_properties2>>` extension is enabled,
ifdef::VK_VERSION_1_1[]
or when both the instance and the physical-device versions are at least 1.1,
endif::VK_VERSION_1_1[]
physical-device-level functionality of a device extension can: be used with
a physical device if the corresponding extension is enumerated by
flink:vkEnumerateDeviceExtensionProperties for that physical device, even
before a logical device has been created.

To obtain a function pointer for a physical-device-level command from a
device extension, an application can: use flink:vkGetInstanceProcAddr.
This function pointer may: point to dispatch code, which calls a different
real implementation for different sname:VkPhysicalDevice objects.
Applications must: not use a slink:VkPhysicalDevice in any command added by
an extension or core version that is not supported by that physical device.

Device extensions may: define structures that can: be added to the
ptext:pNext chain of physical-device-level commands.
endif::VK_VERSION_1_1,VK_KHR_get_physical_device_properties2[]


[[initialization-instances]]
== Instances

[open,refpage='VkInstance',desc='Opaque handle to an instance object',type='handles']
--
There is no global state in Vulkan and all per-application state is stored
in a sname:VkInstance object.
Creating a sname:VkInstance object initializes the Vulkan library and allows
the application to pass information about itself to the implementation.

Instances are represented by sname:VkInstance handles:

include::{generated}/api/handles/VkInstance.txt[]
--

ifdef::VK_VERSION_1_1[]
[open,refpage='vkEnumerateInstanceVersion',desc='Query instance-level version before instance creation',type='protos']
--
To query the version of instance-level functionality supported by the
implementation, call:

include::{generated}/api/protos/vkEnumerateInstanceVersion.txt[]

  * pname:pApiVersion is a pointer to a code:uint32_t, which is the version
    of Vulkan supported by instance-level functionality, encoded as
    described in <<extendingvulkan-coreversions-versionnumbers>>.

[NOTE]
.Note
====
The intended behaviour of flink:vkEnumerateInstanceVersion is that an
implementation should: not need to perform memory allocations and should:
unconditionally return ename:VK_SUCCESS.
The loader, and any enabled layers, may: return
ename:VK_ERROR_OUT_OF_HOST_MEMORY in the case of a failed memory allocation.
====

include::{generated}/validity/protos/vkEnumerateInstanceVersion.txt[]
--
endif::VK_VERSION_1_1[]

[open,refpage='vkCreateInstance',desc='Create a new Vulkan instance',type='protos']
--
To create an instance object, call:

include::{generated}/api/protos/vkCreateInstance.txt[]

  * pname:pCreateInfo is a pointer to a slink:VkInstanceCreateInfo structure
    controlling creation of the instance.
  * pname:pAllocator controls host memory allocation as described in the
    <<memory-allocation, Memory Allocation>> chapter.
  * pname:pInstance points a slink:VkInstance handle in which the resulting
    instance is returned.

fname:vkCreateInstance verifies that the requested layers exist.
If not, fname:vkCreateInstance will return ename:VK_ERROR_LAYER_NOT_PRESENT.
Next fname:vkCreateInstance verifies that the requested extensions are
supported (e.g. in the implementation or in any enabled instance layer) and
if any requested extension is not supported, fname:vkCreateInstance must:
return ename:VK_ERROR_EXTENSION_NOT_PRESENT.
After verifying and enabling the instance layers and extensions the
sname:VkInstance object is created and returned to the application.
If a requested extension is only supported by a layer, both the layer and
the extension need to be specified at fname:vkCreateInstance time for the
creation to succeed.

.Valid Usage
****
  * [[VUID-vkCreateInstance-ppEnabledExtensionNames-01388]]
    All <<extendingvulkan-extensions-extensiondependencies, required
    extensions>> for each extension in the
    slink:VkInstanceCreateInfo::pname:ppEnabledExtensionNames list must:
    also be present in that list
****

include::{generated}/validity/protos/vkCreateInstance.txt[]
--

[open,refpage='VkInstanceCreateInfo',desc='Structure specifying parameters of a newly created instance',type='structs']
--
The sname:VkInstanceCreateInfo structure is defined as:

include::{generated}/api/structs/VkInstanceCreateInfo.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:flags is reserved for future use.
  * pname:pApplicationInfo is `NULL` or a pointer to a
    sname:VkApplicationInfo structure.
    If not `NULL`, this information helps implementations recognize behavior
    inherent to classes of applications.
    slink:VkApplicationInfo is defined in detail below.
  * pname:enabledLayerCount is the number of global layers to enable.
  * pname:ppEnabledLayerNames is a pointer to an array of
    pname:enabledLayerCount null-terminated UTF-8 strings containing the
    names of layers to enable for the created instance.
    The layers are loaded in the order they are listed in this array, with
    the first array element being the closest to the application, and the
    last array element being the closest to the driver.
    See the <<extendingvulkan-layers>> section for further details.
  * pname:enabledExtensionCount is the number of global extensions to
    enable.
  * pname:ppEnabledExtensionNames is a pointer to an array of
    pname:enabledExtensionCount null-terminated UTF-8 strings containing the
    names of extensions to enable.

ifdef::VK_EXT_debug_report,VK_EXT_debug_utils[]
To capture events that occur while creating or destroying an instance, an
application can link a
ifdef::VK_EXT_debug_report[]
slink:VkDebugReportCallbackCreateInfoEXT structure
ifdef::VK_EXT_debug_utils[]
or a
endif::VK_EXT_debug_utils[]
endif::VK_EXT_debug_report[]
ifdef::VK_EXT_debug_utils[]
slink:VkDebugUtilsMessengerCreateInfoEXT structure
endif::VK_EXT_debug_utils[]
to the pname:pNext element of the sname:VkInstanceCreateInfo structure given
to fname:vkCreateInstance.
This callback is only valid for the duration of the flink:vkCreateInstance
and the flink:vkDestroyInstance call.
Use
ifdef::VK_EXT_debug_report[]
flink:vkCreateDebugReportCallbackEXT
ifdef::VK_EXT_debug_utils[]
or
endif::VK_EXT_debug_utils[]
endif::VK_EXT_debug_report[]
ifdef::VK_EXT_debug_utils[]
flink:vkCreateDebugUtilsMessengerEXT
endif::VK_EXT_debug_utils[]
to create persistent callback objects.

.Valid Usage
****
ifdef::VK_EXT_debug_report[]
  * [[VUID-VkInstanceCreateInfo-pNext-04925]]
    If the pname:pNext chain of sname:VkInstanceCreateInfo includes a
    sname:VkDebugReportCallbackCreateInfoEXT structure, the list of enabled
    extensions in pname:ppEnabledExtensionNames must: contain
    VK_EXT_debug_report.
endif::VK_EXT_debug_report[]
ifdef::VK_EXT_debug_utils[]
  * [[VUID-VkInstanceCreateInfo-pNext-04926]]
    If the pname:pNext chain of sname:VkInstanceCreateInfo includes a
    sname:VkDebugUtilsMessengerCreateInfoEXT structure, the list of enabled
    extensions in pname:ppEnabledExtensionNames must: contain
    VK_EXT_debug_utils.
endif::VK_EXT_debug_utils[]
****
endif::VK_EXT_debug_report,VK_EXT_debug_utils[]

include::{generated}/validity/structs/VkInstanceCreateInfo.txt[]
--

[open,refpage='VkInstanceCreateFlags',desc='Reserved for future use',type='flags']
--
include::{generated}/api/flags/VkInstanceCreateFlags.txt[]

tname:VkInstanceCreateFlags is a bitmask type for setting a mask, but is
currently reserved for future use.
--

ifdef::VK_EXT_validation_flags[]
include::VK_EXT_validation_flags.txt[]
endif::VK_EXT_validation_flags[]

ifdef::VK_EXT_validation_features[]
include::VK_EXT_validation_features.txt[]
endif::VK_EXT_validation_features[]

[open,refpage='VkApplicationInfo',desc='Structure specifying application information',type='structs']
--
The sname:VkApplicationInfo structure is defined as:

include::{generated}/api/structs/VkApplicationInfo.txt[]

  * pname:sType is the type of this structure.
  * pname:pNext is `NULL` or a pointer to a structure extending this
    structure.
  * pname:pApplicationName is `NULL` or is a pointer to a null-terminated
    UTF-8 string containing the name of the application.
  * pname:applicationVersion is an unsigned integer variable containing the
    developer-supplied version number of the application.
  * pname:pEngineName is `NULL` or is a pointer to a null-terminated UTF-8
    string containing the name of the engine (if any) used to create the
    application.
  * pname:engineVersion is an unsigned integer variable containing the
    developer-supplied version number of the engine used to create the
    application.
ifndef::VK_VERSION_1_1[]
  * pname:apiVersion is the version of the Vulkan API against which the
    application expects to run, encoded as described in
    <<extendingvulkan-coreversions-versionnumbers>>.
    If pname:apiVersion is 0 the implementation must: ignore it, otherwise
    if the implementation does not support the requested pname:apiVersion,
    or an effective substitute for pname:apiVersion, it must: return
    ename:VK_ERROR_INCOMPATIBLE_DRIVER.
endif::VK_VERSION_1_1[]
ifdef::VK_VERSION_1_1[]
  * pname:apiVersion must: be the highest version of Vulkan that the
    application is designed to use, encoded as described in
    <<extendingvulkan-coreversions-versionnumbers>>.
endif::VK_VERSION_1_1[]
    The patch version number specified in pname:apiVersion is ignored when
    creating an instance object.
    Only the major and minor versions of the instance must: match those
    requested in pname:apiVersion.

ifdef::VK_VERSION_1_1[]
Vulkan 1.0 implementations were required to return
ename:VK_ERROR_INCOMPATIBLE_DRIVER if pname:apiVersion was larger than 1.0.
Implementations that support Vulkan 1.1 or later must: not return
ename:VK_ERROR_INCOMPATIBLE_DRIVER for any value of pname:apiVersion.

[NOTE]
.Note
====
Because Vulkan 1.0 implementations may: fail with
ename:VK_ERROR_INCOMPATIBLE_DRIVER, applications should: determine the
version of Vulkan available before calling flink:vkCreateInstance.
If the flink:vkGetInstanceProcAddr returns `NULL` for
flink:vkEnumerateInstanceVersion, it is a Vulkan 1.0 implementation.
Otherwise, the application can: call flink:vkEnumerateInstanceVersion to
determine the version of Vulkan.
====

ifdef::VK_VERSION_1_1[]
As long as the instance supports at least Vulkan 1.1, an application can:
use different versions of Vulkan with an instance than it does with a device
or physical device.

[NOTE]
.Note
====

The Khronos validation layers will treat pname:apiVersion as the highest API
version the application targets, and will validate API usage against the
minimum of that version and the implementation version (instance or device,
depending on context).
If an application tries to use functionality from a greater version than
this, a validation error will be triggered.

For example, if the instance supports Vulkan 1.1 and three physical devices
support Vulkan 1.0, Vulkan 1.1, and Vulkan 1.2, respectively, and if the
application sets pname:apiVersion to 1.2, the application can: use the
following versions of Vulkan:

  * Vulkan 1.0 can: be used with the instance and with all physical devices.
  * Vulkan 1.1 can: be used with the instance and with the physical devices
    that support Vulkan 1.1 and Vulkan 1.2.
  * Vulkan 1.2 can: be used with the physical device that supports Vulkan
    1.2.

If we modify the above example so that the application sets pname:apiVersion
to 1.1, then the application must: not use Vulkan 1.2 functionality on the
physical device that supports Vulkan 1.2.
====
endif::VK_VERSION_1_1[]

Implicit layers must: be disabled if they do not support a version at least
as high as pname:apiVersion.
See the <<LoaderAndLayerInterface, Vulkan Loader Specification and
Architecture Overview>> document for additional information.

[NOTE]
.Note
====
Providing a `NULL` slink:VkInstanceCreateInfo::pname:pApplicationInfo or
providing an pname:apiVersion of 0 is equivalent to providing an
pname:apiVersion of `VK_MAKE_API_VERSION(0,1,0,0)`.
====
endif::VK_VERSION_1_1[]

.Valid Usage
****
  * [[VUID-VkApplicationInfo-apiVersion-04010]]
    If pname:apiVersion is not `0`, then it must: be greater than or equal
    to dlink:VK_API_VERSION_1_0
****

include::{generated}/validity/structs/VkApplicationInfo.txt[]
--

[open,refpage='vkDestroyInstance',desc='Destroy an instance of Vulkan',type='protos']
--
To destroy an instance, call:

include::{generated}/api/protos/vkDestroyInstance.txt[]

  * pname:instance is the handle of the instance to destroy.
  * pname:pAllocator controls host memory allocation as described in the
    <<memory-allocation, Memory Allocation>> chapter.

.Valid Usage
****
  * [[VUID-vkDestroyInstance-instance-00629]]
    All child objects created using pname:instance must: have been destroyed
    prior to destroying pname:instance
  * [[VUID-vkDestroyInstance-instance-00630]]
    If sname:VkAllocationCallbacks were provided when pname:instance was
    created, a compatible set of callbacks must: be provided here
  * [[VUID-vkDestroyInstance-instance-00631]]
    If no sname:VkAllocationCallbacks were provided when pname:instance was
    created, pname:pAllocator must: be `NULL`
****

include::{generated}/validity/protos/vkDestroyInstance.txt[]
--
