## 4.1. Physical Devices

To retrieve a list of physical device objects representing the physical devices installed in the system, call:

    VkResult vkEnumeratePhysicalDevices(
        VkInstance                                  instance,
        uint32_t*                                   pPhysicalDeviceCount,
        VkPhysicalDevice*                           pPhysicalDevices);

- `instance` is a handle to a Vulkan instance previously created with `vkCreateInstance`.
- `pPhysicalDeviceCount` is a pointer to an integer related to the number of physical devices available or queried, as described below.
- `pPhysicalDevices` is either `NULL` or a pointer to an array of `VkPhysicalDevice` handles.

If `pPhysicalDevices` is `NULL`, then the number of physical devices available is returned in `pPhysicalDeviceCount`. Otherwise, `pPhysicalDeviceCount` must point to a variable set by the user to the number of elements in the `pPhysicalDevices` array, and on return the variable is overwritten with the number of structures actually written to `pPhysicalDevices`. If `pPhysicalDeviceCount` is less than the number of physical devices available, at most `pPhysicalDeviceCount` structures will be written. If `pPhysicalDeviceCount` is smaller than the number of physical devices available, `VK_INCOMPLETE` will be returned instead of `VK_SUCCESS`, to indicate that not all the available physical devices were returned.

To query general properties of physical devices once enumerated, call:

    void vkGetPhysicalDeviceProperties(
        VkPhysicalDevice                            physicalDevice,
        VkPhysicalDeviceProperties*                 pProperties);

- `physicalDevice` is the handle to the physical device whose properties will be queried.
- `pProperties` points to an instance of the `VkPhysicalDeviceProperties` structure, that will be filled with returned information.

The `VkPhysicalDeviceProperties` structure is defined as:

    typedef struct VkPhysicalDeviceProperties {
        uint32_t                            apiVersion;
        uint32_t                            driverVersion;
        uint32_t                            vendorID;
        uint32_t                            deviceID;
        VkPhysicalDeviceType                deviceType;
        char                                deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
        uint8_t                             pipelineCacheUUID[VK_UUID_SIZE];
        VkPhysicalDeviceLimits              limits;
        VkPhysicalDeviceSparseProperties    sparseProperties;
    } VkPhysicalDeviceProperties;

- `apiVersion` is the version of Vulkan supported by the device, encoded as described in the API Version Numbers and Semantics section.
- `driverVersion` is the vendor-specified version of the driver.
- `vendorID` is a unique identifier for the vendor (see below) of the physical device.
- `deviceID` is a unique identifier for the physical device among devices available from the vendor.
- `deviceType` is a `VkPhysicalDeviceType` specifying the type of device.
- `deviceName` is a null-terminated UTF-8 string containing the name of the device.
- `pipelineCacheUUID` is an array of size `VK_UUID_SIZE`, containing 8-bit values that represent a universally unique identifier for the device.
- `limits` is the `VkPhysicalDeviceLimits` structure which specifies device-specific limits of the physical device. See Limits for details.
- `sparseProperties` is the `VkPhysicalDeviceSparseProperties` structure which specifies various sparse related properties of the physical device. See Sparse Properties for details.

The `vendorID` and `deviceID` fields are provided to allow applications to adapt to device characteristics that are not adequately exposed by other Vulkan queries. These may include performance profiles, hardware errata, or other characteristics. In PCI-based implementations, the low sixteen bits of `vendorID` and `deviceID` must contain (respectively) the PCI vendor and device IDs associated with the hardware device, and the remaining bits must be set to zero. In non-PCI implementations, the choice of what values to return may be dictated by operating system or platform policies. It is otherwise at the discretion of the implementer, subject to the following constraints and guidelines:

- For purposes of physical device identification, the vendor of a physical device is the entity responsible for the most salient characteristics of the hardware represented by the physical device handle. In the case of a discrete GPU, this should be the GPU chipset vendor. In the case of a GPU or other accelerator integrated into a system-on-chip (SoC), this should be the supplier of the silicon IP used to create the GPU or other accelerator.
- If the vendor of the physical device has a valid PCI vendor ID issued by PCI-SIG, that ID should be used to construct `vendorID` as described above for PCI-based implementations. Implementations that do not return a PCI vendor ID in `vendorID` must return a valid Khronos vendor ID, obtained as described in the Vulkan Documentation and Extensions document in the section “Registering a Vendor ID with Khronos”. Khronos vendor IDs are allocated starting at 0x10000, to distinguish them from the PCI vendor ID namespace.
- The vendor of the physical device is responsible for selecting `deviceID`. The value selected should uniquely identify both the device version and any major configuration options (for example, core count in the case of multicore devices). The same device ID should be used for all physical implementations of that device version and configuration. For example, all uses of a specific silicon IP GPU version and configuration should use the same device ID, even if those uses occur in different SoCs.

The physical devices types are:

    typedef enum VkPhysicalDeviceType {
        VK_PHYSICAL_DEVICE_TYPE_OTHER = 0,
        VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
        VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2,
        VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3,
        VK_PHYSICAL_DEVICE_TYPE_CPU = 4,
    } VkPhysicalDeviceType;

- `VK_PHYSICAL_DEVICE_TYPE_OTHER` The device does not match any other available types.
- `VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU` The device is typically one embedded in or tightly coupled with the host.
- `VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU` The device is typically a separate processor connected to the host via an interlink.
- `VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU` The device is typically a virtual node in a virtualization environment.
- `VK_PHYSICAL_DEVICE_TYPE_CPU` The device is typically running on the same processors as the host.

The physical device type is advertised for informational purposes only, and does not directly affect the operation of the system. However, the device type may correlate with other advertised properties or capabilities of the system, such as how many memory heaps there are.

To query properties of queues available on a physical device, call:

    void vkGetPhysicalDeviceQueueFamilyProperties(
        VkPhysicalDevice                            physicalDevice,
        uint32_t*                                   pQueueFamilyPropertyCount,
        VkQueueFamilyProperties*                    pQueueFamilyProperties);

- `physicalDevice` is the handle to the physical device whose properties will be queried.
- `pQueueFamilyPropertyCount` is a pointer to an integer related to the number of queue families available or queried, as described below.
- `pQueueFamilyProperties` is either `NULL` or a pointer to an array of `VkQueueFamilyProperties` structures.

If `pQueueFamilyProperties` is `NULL`, then the number of queue families available is returned in `pQueueFamilyPropertyCount`. Otherwise, `pQueueFamilyPropertyCount` must point to a variable set by the user to the number of elements in the `pQueueFamilyProperties` array, and on return the variable is overwritten with the number of structures actually written to `pQueueFamilyProperties`. If `pQueueFamilyPropertyCount` is less than the number of queue families available, at most `pQueueFamilyPropertyCount` structures will be written.

The `VkQueueFamilyProperties` structure is defined as:

    typedef struct VkQueueFamilyProperties {
        VkQueueFlags    queueFlags;
        uint32_t        queueCount;
        uint32_t        timestampValidBits;
        VkExtent3D      minImageTransferGranularity;
    } VkQueueFamilyProperties;

- `queueFlags` contains flags indicating the capabilities of the queues in this queue family.
- `queueCount` is the unsigned integer count of queues in this queue family.
- `timestampValidBits` is the unsigned integer count of meaningful bits in the timestamps written via `vkCmdWriteTimestamp`. The valid range for the count is 36..64 bits, or a value of 0, indicating no support for timestamps. Bits outside the valid range are guaranteed to be zeros.
- `minImageTransferGranularity` is the minimum granularity supported for image transfer operations on the queues in this queue family.

The bits specified in `queueFlags` are:

    typedef enum VkQueueFlagBits {
        VK_QUEUE_GRAPHICS_BIT = 0x00000001,
        VK_QUEUE_COMPUTE_BIT = 0x00000002,
        VK_QUEUE_TRANSFER_BIT = 0x00000004,
        VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008,
    } VkQueueFlagBits;

- if `VK_QUEUE_GRAPHICS_BIT` is set, then the queues in this queue family support graphics operations.
- if `VK_QUEUE_COMPUTE_BIT` is set, then the queues in this queue family support compute operations.
- if `VK_QUEUE_TRANSFER_BIT` is set, then the queues in this queue family support transfer operations.
- if `VK_QUEUE_SPARSE_BINDING_BIT` is set, then the queues in this queue family support sparse memory management operations (see Sparse Resources). If any of the sparse resource features are enabled, then at least one queue family must support this bit.

If an implementation exposes any queue family that supports graphics operations, at least one queue family of at least one physical device exposed by the implementation must support both graphics and compute operations.

| Note
All commands that are allowed on a queue that supports transfer operations are also allowed on a queue that supports either graphics or compute operations thus if the capabilities of a queue family include `VK_QUEUE_GRAPHICS_BIT` or `VK_QUEUE_COMPUTE_BIT` then reporting the `VK_QUEUE_TRANSFER_BIT` capability separately for that queue family is optional.

For further details see Queues.

The value returned in `minImageTransferGranularity` has a unit of compressed texel blocks for images having a block-compressed format, and a unit of texels otherwise.

Possible values of `minImageTransferGranularity` are:

- $(0,0,0)$ which indicates that only whole mip levels must be transferred using the image transfer operations on the corresponding queues. In this case, the following restrictions apply to all offset and extent parameters of image transfer operations:

  - The `x`, `y`, and `z` members of a `VkOffset3D` parameter must always be zero.
  - The `width`, `height`, and `depth` members of a `VkExtent3D` parameter must always match the width, height, and depth of the image subresource corresponding to the parameter, respectively.

- $(Ax, Ay, Az)$ where $Ax$ , $Ay$ , and $Az$ are all integer powers of two. In this case the following restrictions apply to all image transfer operations:

  - `x`, `y`, and `z` of a `VkOffset3D` parameter must be integer multiples of $Ax$ , $Ay$ , and $Az$ , respectively.
  - `width` of a `VkExtent3D` parameter must be an integer multiple of $Ax$ , or else $(x + width)$ must equal the width of the image subresource corresponding to the parameter.
  - `height` of a `VkExtent3D` parameter must be an integer multiple of $Ay$ , or else $(y + height)$ must equal the height of the image subresource corresponding to the parameter.
  - `depth` of a `VkExtent3D` parameter must be an integer multiple of $Az$ , or else $(z + depth)$ must equal the depth of the image subresource corresponding to the parameter.
  - If the format of the image corresponding to the parameters is one of the block-compressed formats then for the purposes of the above calculations the granularity must be scaled up by the compressed texel block dimensions.

Queues supporting graphics and/or compute operations must report $(1,1,1)$ in `minImageTransferGranularity`, meaning that there are no additional restrictions on the granularity of image transfer operations for these queues. Other queues supporting image transfer operations are only required to support whole mip level transfers, thus `minImageTransferGranularity` for queues belonging to such queue families may be $(0,0,0)$ .

The Device Memory section describes memory properties queried from the physical device.

For physical device feature queries see the Features chapter.