Vulkan 扩展

(本章文本内容的更多细节, 参见 Vulkan Specification 1.1, 代码为示例用伪码)

对于不同的平台, 驱动, 操作系统等, 当Vulkan的底层实现不同时, Vulkan 可用的功能集也有很多区别. 本章描述了 Vulkan 如何定义和扩展功能集, 主要介绍了四个概念: Extension, Feature, Limitation, 和 Format.

Vulkan 初始化流程

在开发应用程序时, 需要启用的 Vulkan 功能集需要在初始化 Device 前确定下来.

对应 vk 初始化的前三步: Instance –> Physical Device –> Device

以下是初始化过程中与功能相关的过程:

枚举 vk 支持的 Instance-level Extensions

创建 Instance

枚举 物理设备, 选择 GPU,

枚举 GPU 支持的 Device Extensions, 从中选择要启用的

​ 查询支持的 Extensions 的 Features 结构体, 从中选择要启用的

​ 查询支持的 Extensions 的 Properties 结构体

查询 GPU 支持的 Feature, 从中选择要启用的

查询 GPU 的 Properties

将启用的 Extensions 和 Features 列表放入 CreateInfo 结构体, 创建逻辑设备 Device,

  • Extension: 功能集的抽象概念, 用来为 Vulkan 添加新的 Commands,Structures 和 Enumerants. 同时可能新增 Features, Limitations, 和 Format.

  • Feature: bool 值集合, 可选功能的开关. 可以用来查询设备支持的功能,

  • Limitation 和 Format 是两个只读参数集, Limitation 又称做 Properties, 表示设备特征值; Format 表示支持的格式.

本章后面各章节对此流程各步骤进行解释, 并包含示例代码.

Extensions: 扩展

  • 扩展 (Extensions) 可用来为 Vk 添加新功能. Vk 核心的新版本 (如: VK_VERSION_1_1) 也可以视为一个扩展.
  • 扩展可以定义新的 命令, 枚举, 和结构. ( Commands,Structures 和 Enumerants)

  • 扩展分为实例级和设备级 (Instance-level 和 Device-level)

  • 当 Commands 用来枚举实例属性 (instance properties), 或接受 VkInstance 对象作为参数, 则被视为实例级功能。
  • 当 Commands 用来枚举物理设备属性 (physical device properties), 或接受 VkDevice 及其子类对象作为参数,则被视为设备级功能。

为了方便编译,在 Khronos 提供的 vulkan_core.h 中除了核心API, 还定义了已注册 Extensions 定义的接口,包括新 结构, 枚举, 和命令的函数指针类型。扩展的实现通过 Layers 和 Vulkan实现来提供。

启用 Vk Extensions

  • Vk Extensions 需要在初始化阶段显式启用.
  • 启用 instance extension, 要在创建 VKInstance 时, 将扩展名添加到 VkInstanceCreateInfo 的成员 ppEnabledExtensionNames 中.
  • 启用 device extension, 要在 创建 VkDevice时, 将扩展名添加到 VkDeviceCreateInfo的成员 ppEnabledExtensionNames 中.
  • Physical-Device-Level 功能没有启用机制,只要 VkPhysicalDevice 的功能对应的 Extensions 在枚举函数 vkEnumerateDeviceExtensionProperties 中被列出.

启用 扩展操作而言, 除了 启用 该扩展自身定义的命令, 枚举, 和结构外, 不会更改核心Vulkan API 或其他扩展的功能。

示例: 创建 VkInstance 时, 启用 Extensions:

// add Target Extension Names
std::vector<const char*> extensions();
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);

VkInstanceCreateInfo inst_info = {};
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
...

// Enable Instance Extensions
inst_info.enabledExtensionCount = extensions.size();
inst_info.ppEnabledExtensionNames = extensions.data();

VkInstance instance;
VkResult res = vkCreateInstance(&inst_info, NULL, &instance);

对 VkPhysicalDevice, 枚举其支持的 Extensions:

// 枚举设备
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);

std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
// 选择设备
VkPhysicalDevice physicalDevice = devices[0]; // 仅示例,正确代码应选择对应 GPU 设备

// 枚举 Extensions
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr);

std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, availableExtensions.data());

创建 VkDevice 时, 启用 Extensions:

// add Target Extension Names
std::vector<const char*> device_extension_names();
// check if physicalDevice support extension:
for (const auto& extension : availableExtensions) {
    if(strcmp(extension.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME) == 0)
            device_extension_names.push_back(extension.extensionName);
    }
}

VkDeviceCreateInfo device_info = {};
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_info.pNext = NULL;
...

// Enable Device Extensions
device_info.enabledExtensionCount = device_extension_names.size();
device_info.ppEnabledExtensionNames = enabledExtensionCount ? device_extension_names.data() : NULL;

VkDevice device;
res = vkCreateDevice(physicalDevice, &device_info, NULL, &device);

Features: 功能

Features 用来设置或查询 非所有实现都支持 的功能。 Feature 均为 bool 值.

  • Features 是物理设备的属性。(physical device properties)

  • 这些功能是“可选”的,并且必须在使用前明确启用。

核心 Features

Vk 核心中定义的 Features, 可以通过 vkGetPhysicalDeviceFeatures 查询.

VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
vkGetPhysicalDeviceFeatures(mPhysicalDevice, &mPhysicalDeviceFeatures);

查询结果 VkPhysicalDeviceFeatures 的结构体定义如下:

// Provided by VK_VERSION_1_0
typedef struct VkPhysicalDeviceFeatures {
    VkBool32    robustBufferAccess;
    VkBool32    fullDrawIndexUint32;
    VkBool32    imageCubeArray;
    VkBool32    independentBlend;
    VkBool32    geometryShader;
    VkBool32    tessellationShader;
    VkBool32    sampleRateShading;
    .... // 总计50+个 Bool 值
 } VkPhysicalDeviceFeatures

其中每个 Feature 的含义 在 Vulkan Specification 1.1/Features 中都有解释.

例如:

IndependentBlend 指定: 是否每个 attachments 的 VkPipelineColorBlendAttachmentState 设置互相独立。

  • 未启用此 Feature,则所有 color attachments 的 VkPipelineColorBlendAttachmentState 设置必须相同。
  • 若启用此 Feature,则可以为每个绑定的 color attachment 提供不同的VkPipelineColorBlendAttachmentState

扩展提供的Features

查询函数: vkGetPhysicalDeviceFeatures2

VkPhysicalDeviceFeatures2 physicalDeviceFeatures2;
vkGetPhysicalDeviceFeatures2(mPhysicalDevice, &physicalDeviceFeatures2);

查询结果: VkPhysicalDeviceFeatures2 结构:

// Provided by VK_VERSION_1_1
typedef struct VkPhysicalDeviceFeatures2 {
    VkStructureType             sType;
    void*                       pNext;
    VkPhysicalDeviceFeatures    features;
} VkPhysicalDeviceFeatures2;
  • sType: VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2

  • pNext: 指针链.

  • VkPhysicalDeviceFeatures: Vulkan 1.0 提供的核心 Features

注: VkPhysicalDeviceFeatures2 等价 VkPhysicalDeviceFeatures2KHR, vkGetPhysicalDeviceFeatures2 等价 vkGetPhysicalDeviceFeatures2KHR

通过 pNext, 可以获得扩展所定义的 Features 结构体, 有的由 Vulkan 核心新版本提供, 有的由其他 Extension提供.

例如:

Vulkan 1.1 提供的 samplerYcbcrConversion.

// Provided by VK_VERSION_1_1: VK_KHR_sampler_ycbcr_conversion
typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           samplerYcbcrConversion;
} VkPhysicalDeviceSamplerYcbcrConversionFeatures;

VK_EXT_transform_feedback 提供的 transformFeedback 和 geometryStreams.

// Provided by VK_EXT_transform_feedback
typedef struct VkPhysicalDeviceTransformFeedbackFeaturesEXT {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           transformFeedback;
    VkBool32           geometryStreams;
} VkPhysicalDeviceTransformFeedbackFeaturesEXT;

查询示例:

// 扩展的 Feature 结构体
VkPhysicalDeviceSamplerYcbcrConversionFeatures mSamplerYcbcrConversionFeatures = {};
mSamplerYcbcrConversionFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;

// vk1.1 的 VkPhysicalDeviceFeatures2
VkPhysicalDeviceFeatures2 deviceFeatures = {};
deviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
deviceFeatures.pNext = mVertexAttributeDivisorFeatures
// 查询
vkGetPhysicalDeviceFeatures2(mPhysicalDevice, &deviceFeatures);
// 使用
if (mVertexAttributeDivisorFeatures.vertexAttributeInstanceRateDivisor)
{
...
}

启用 Features

Features 默认皆为不启用状态. 必须在 VkDevice 创建时显式启用。如果启用了物理设备不支持的功能,则 VkDevice 创建将失败,并返回VK_ERROR_FEATURE_NOT_PRESENT。

启用方法:

  1. 创建 VkPhysicalDeviceFeatures 结构的指针 (或1.1的 VkPhysicalDeviceFeatures2结构)
  2. 将成员设置为 VK_TRUE 或 VK_FALSE, eg: physicalDeviceFeatures.independentBlend = VK_TRUE
  3. 通过传递给 vkCreateDevice 用的 VkDeviceCreateInfo结构的 pEnabledFeatures 成员.

要启动所有设备的功能 (慎用),则只需传入查询函数vkGetPhysicalDeviceFeatures 返回的VkPhysicalDeviceFeatures结构即可。要禁用单个功能,应用程序可以在相同结构中将所需成员设置为VK_FALSE。

用过给 pNext链添加 Extensions 提供的 Features 结构体, 来启用扩展的 Features.

// 查询核心 Features 是否支持
VkPhysicalDeviceFeatures mPhysicalDeviceFeatures;
vkGetPhysicalDeviceFeatures(mPhysicalDevice, &mPhysicalDeviceFeatures);

// 设置启用 Features
VkPhysicalDeviceFeatures2KHR enabledFeatures = {};
enabledFeatures.sType                        = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
enabledFeatures.features.imageCubeArray = mPhysicalDeviceFeatures.imageCubeArray; 
enabledFeatures.features.independentBlend = mPhysicalDeviceFeatures.independentBlend;

// Create Device
VkDeviceCreateInfo device_info = {};
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

// 指向 Features 结构体以设置 Extensions 提供的 Features
// mSamplerYcbcrConversionFeatures : 前面查询示例中的结构体. 
device_info.pNext = mSamplerYcbcrConversionFeatures; 

// Enable Physical Device Features
device_info.pEnabledFeatures = &enabledFeatures.features;
...

VkDevice device;
res = vkCreateDevice(physicalDevice, &device_info, NULL, &device);

Limitations

Limits 提供开发应用程序可能需要明确的一些设备特征值, 这些特征的最小值,最大值等会随底层实现的不同而异.

通过 VkPhysicalDeviceLimits 结构体获取核心1.0的 Limits, 或利用 vk1.1 中加入的 VkPhysicalDeviceProperties2 的 pNext 链 获取各 Extension 新增的 Limits.

结构体 VkPhysicalDeviceLimits 定义如下:

// Provided by VK_VERSION_1_0
typedef struct VkPhysicalDeviceLimits {
    uint32_t              maxImageDimension1D;
    uint32_t              maxImageDimension2D;
    uint32_t              maxImageDimension3D;
    uint32_t              maxImageDimensionCube;
    uint32_t              maxImageArrayLayers;
    uint32_t              maxTexelBufferElements;
    uint32_t              maxUniformBufferRange;
    uint32_t              maxStorageBufferRange;
    uint32_t              maxPushConstantsSize;
    uint32_t              maxMemoryAllocationCount;
    uint32_t              maxSamplerAllocationCount;
    VkDeviceSize          bufferImageGranularity;
    VkDeviceSize          sparseAddressSpaceSize;
    ... // 省略约 100+ 个值
} VkPhysicalDeviceLimits;

specs 文档对每个值都有介绍:

例如:

maxUniformBufferRange : 当将结构体 VkDescriptorBufferInfo 作为参数调用 vkUpdateDescriptorSets , 并且 descriptors 类型为VK_DESCRIPTOR_TYPE_UNIFORM_BUFFERVK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC 时, 其结构体成员 range 可设的最大值.

查询扩展提供的Limits

查询扩展提供的结构体均以 Properties 而非 Limits 结尾, 其查询方法与查询 扩展提供的 Feature 一样.

查询函数和结果结构体如下:

VkPhysicalDeviceProperties2 deviceProperties;
vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);

查询结果示例:

结构体VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT 包含了扩展 VK_EXT_vertex_attribute_divisor 提供的 limits 值 maxVertexAttribDivisor:

// Provided by VK_EXT_vertex_attribute_divisor
typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           maxVertexAttribDivisor;
} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT;

Formats

对于不同的 vk 实现, 其支持的缓冲区和图像格式可能会不同。虽然 Vulkan 规定了一组必须支持的 Format 的最小集,但在使用除此以外的 Format功能之前, 必须显式的查询,以确保实现支持这些格式。

查询命令: vkGetPhysicalDeviceFormatProperties, 查询返回的VkFormat 结构体的包含了当前实现所支持的格式功能。

VkFormat 结构体示例:

// Provided by VK_VERSION_1_0
typedef enum VkFormat {
    VK_FORMAT_UNDEFINED = 0,
    VK_FORMAT_R4G4_UNORM_PACK8 = 1,
    VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2,
    VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3,
    VK_FORMAT_R5G6B5_UNORM_PACK16 = 4,
    VK_FORMAT_B5G6R5_UNORM_PACK16 = 5,
    VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6,
    VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7,
    VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8,
    ... // 约 300+, 其中

关于 Format 相关的内容比较复杂, 本章节以及后续章节都不进行深入. 如果需要考虑再单独进行研究.

39. Extending Vulkan

New functionality may be added to Vulkan via either new extensions or new versions of the core, or new versions of an extension in some cases.

This chapter describes how Vulkan is versioned, how compatibility is affected between different versions, and compatibility rules that are followed by the Vulkan Working Group.

39.1. Instance and Device Functionality

Commands that enumerate instance properties, or that accept a VkInstance object as a parameter, are considered instance-level functionality. Commands that enumerate physical device properties, or that accept a VkDevice object or any of a device’s child objects as a parameter, are considered device-level functionality.

39.4. Extensions

Extensions may define new Vulkan commands, structures, and enumerants. For compilation purposes, the interfaces defined by registered extensions, including new structures and enumerants as well as function pointer types for new commands, are defined in the Khronos-supplied vulkan_core.h together with the core API. However, commands defined by extensions may not be available for static linking - in which case function pointers to these commands should be queried at runtime as described in Command Function Pointers. Extensions may be provided by layers as well as by a Vulkan implementation.

Because extensions may extend or change the behavior of the Vulkan API, extension authors should add support for their extensions to the Khronos validation layers. This is especially important for new commands whose parameters have been wrapped by the validation layers. See the “Vulkan Loader Specification and Architecture Overview” document for additional information.

39.4.1. Instance Extensions

Instance extensions add new instance-level functionality to the API, outside of the core specification.

To query the available instance extensions, call:

// Provided by VK_VERSION_1_0
VkResult vkEnumerateInstanceExtensionProperties(
    const char*                                 pLayerName,
    uint32_t*                                   pPropertyCount,
    VkExtensionProperties*                      pProperties);
  • pLayerName is either NULL or a pointer to a null-terminated UTF-8 string naming the layer to retrieve extensions from.
  • pPropertyCount is a pointer to an integer related to the number of extension properties available or queried, as described below.
  • pProperties is either NULL or a pointer to an array of VkExtensionProperties structures.

When pLayerName parameter is NULL, only extensions provided by the Vulkan implementation or by implicitly enabled layers are returned. When pLayerName is the name of a layer, the instance extensions provided by that layer are returned.

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

Because the list of available layers may change externally between calls to vkEnumerateInstanceExtensionProperties, two calls may retrieve different results if a pLayerName is available in one call but not in another. The extensions supported by a layer may also change between two calls, e.g. if the layer implementation is replaced by a different version between those calls.

Implementations must not advertise any pair of extensions that cannot be enabled together due to behavioral differences, or any extension that cannot be enabled against the advertised version.

39.4.2. Device Extensions

Device extensions add new device-level functionality to the API, outside of the core specification.

To query the extensions available to a given physical device, call:

// Provided by VK_VERSION_1_0
VkResult vkEnumerateDeviceExtensionProperties(
    VkPhysicalDevice                            physicalDevice,
    const char*                                 pLayerName,
    uint32_t*                                   pPropertyCount,
    VkExtensionProperties*                      pProperties);
  • physicalDevice is the physical device that will be queried.
  • pLayerName is either NULL or a pointer to a null-terminated UTF-8 string naming the layer to retrieve extensions from.
  • pPropertyCount is a pointer to an integer related to the number of extension properties available or queried, and is treated in the same fashion as the vkEnumerateInstanceExtensionProperties::pPropertyCount parameter.
  • pProperties is either NULL or a pointer to an array of VkExtensionProperties structures.

When pLayerName parameter is NULL, only extensions provided by the Vulkan implementation or by implicitly enabled layers are returned. When pLayerName is the name of a layer, the device extensions provided by that layer are returned.

Implementations must not advertise any pair of extensions that cannot be enabled together due to behavioral differences, or any extension that cannot be enabled against the advertised version.

40. Features

Features describe functionality which is not supported on all implementations. Features are properties of the physical device. Features are optional, and must be explicitly enabled before use. Support for features is reported and enabled on a per-feature basis.

NoteFeatures are reported via the basic VkPhysicalDeviceFeatures structure, as well as the extensible structure VkPhysicalDeviceFeatures2, which was added in the VK_KHR_get_physical_device_properties2 extension and included in Vulkan 1.1. When new features are added in future Vulkan versions or extensions, each extension should introduce one new feature structure, if needed. This structure can be added to the pNext chain of the VkPhysicalDeviceFeatures2 structure.

For convenience, new core versions of Vulkan may introduce new unified features structures for features promoted from extensions. At the same time, the extension’s original features structure (if any) is also promoted to the core API, and is an alias of the extension’s structure. This results in multiple names for the same feature: in the original extension’s feature structure and the promoted structure alias, in the unified feature structure. When a feature was implicitly supported and enabled in the extension, but an explicit name was added during promotion, then the extension itself acts as an alias for the feature as listed in the table below.

All aliases of the same feature in the core API must be reported consistently: either all must be reported as supported, or none of them. When a promoted extension is available, any corresponding feature aliases must be supported.

// Provided by VK_VERSION_1_1
typedef struct VkPhysicalDeviceFeatures2 {
    VkStructureType             sType;
    void*                       pNext;
    VkPhysicalDeviceFeatures    features;
} VkPhysicalDeviceFeatures2;

The pNext chain of this structure is used to extend the structure with features defined by extensions.

Fine-grained features used by a logical device must be enabled at VkDevice creation time. If a feature is enabled that the physical device does not support, VkDevice creation will fail and return VK_ERROR_FEATURE_NOT_PRESENT.

The fine-grained features are enabled by passing a pointer to the VkPhysicalDeviceFeatures structure via the pEnabledFeatures member of the VkDeviceCreateInfo structure that is passed into the vkCreateDevice call. If a member of pEnabledFeatures is set to VK_TRUE or VK_FALSE, then the device will be created with the indicated feature enabled or disabled, respectively. Features can also be enabled by using the VkPhysicalDeviceFeatures2 structure.

If an application wishes to enable all features supported by a device, it can simply pass in the VkPhysicalDeviceFeatures structure that was previously returned by vkGetPhysicalDeviceFeatures. To disable an individual feature, the application can set the desired member to VK_FALSE in the same structure. Setting pEnabledFeatures to NULL and not including a VkPhysicalDeviceFeatures2 in the pNext chain of VkDeviceCreateInfo is equivalent to setting all members of the structure to VK_FALSE.

To query support for atomic operations on floating-point numbers, call vkGetPhysicalDeviceFeatures2 with a VkPhysicalDeviceShaderAtomicFloatFeaturesEXT structure included in the pNext chain of its pFeatures parameter.

The VkPhysicalDeviceShaderAtomicFloatFeaturesEXT structure is defined as:

// Provided by VK_EXT_shader_atomic_float
typedef struct VkPhysicalDeviceShaderAtomicFloatFeaturesEXT {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           shaderBufferFloat32Atomics;
    VkBool32           shaderBufferFloat32AtomicAdd;
    VkBool32           shaderBufferFloat64Atomics;
    VkBool32           shaderBufferFloat64AtomicAdd;
    VkBool32           shaderSharedFloat32Atomics;
    VkBool32           shaderSharedFloat32AtomicAdd;
    VkBool32           shaderSharedFloat64Atomics;
    VkBool32           shaderSharedFloat64AtomicAdd;
    VkBool32           shaderImageFloat32Atomics;
    VkBool32           shaderImageFloat32AtomicAdd;
    VkBool32           sparseImageFloat32Atomics;
    VkBool32           sparseImageFloat32AtomicAdd;
} VkPhysicalDeviceShaderAtomicFloatFeaturesEXT;

41. Limits

Limits are implementation-dependent minimums, maximums, and other device characteristics that an application may need to be aware of.

NoteLimits are reported via the basic VkPhysicalDeviceLimits structure, as well as the extensible structure VkPhysicalDeviceProperties2, which was added in VK_KHR_get_physical_device_properties2 and included in Vulkan 1.1. When limits are added in future Vulkan versions or extensions, each extension should introduce one new limit structure, if needed. This structure can be added to the pNext chain of the VkPhysicalDeviceProperties2 structure.

The VkPhysicalDeviceLimits structure is defined as:

// Provided by VK_VERSION_1_0
typedef struct VkPhysicalDeviceLimits {
    uint32_t              maxImageDimension1D;
    uint32_t              maxImageDimension2D;
    uint32_t              maxImageDimension3D;
    uint32_t              maxImageDimensionCube;
    uint32_t              maxImageArrayLayers;
    uint32_t              maxTexelBufferElements;
    uint32_t              maxUniformBufferRange;
    uint32_t              maxStorageBufferRange;
    uint32_t              maxPushConstantsSize;
    uint32_t              maxMemoryAllocationCount;
    uint32_t              maxSamplerAllocationCount;
    VkDeviceSize          bufferImageGranularity;
    VkDeviceSize          sparseAddressSpaceSize;
    ... // 约 100+ 个值
} VkPhysicalDeviceLimits;

specs 文档对每个值都有介绍

The VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT structure is defined as:

// Provided by VK_EXT_vertex_attribute_divisor
typedef struct VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           maxVertexAttribDivisor;
} VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT;

42. Formats

Supported buffer and image formats may vary across implementations. A minimum set of format features are guaranteed, but others must be explicitly queried before use to ensure they are supported by the implementation.

The features for the set of formats (VkFormat) supported by the implementation are queried individually using the vkGetPhysicalDeviceFormatProperties command.

42.1. Format Definition

The following image formats can be passed to, and may be returned from Vulkan commands. The memory required to store each format is discussed with that format, and also summarized in the Representation and Texel Block Size section and the Compatible formats table.

// Provided by VK_VERSION_1_0
typedef enum VkFormat {
    VK_FORMAT_UNDEFINED = 0,
    VK_FORMAT_R4G4_UNORM_PACK8 = 1,
    VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2,
    VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3,
    VK_FORMAT_R5G6B5_UNORM_PACK16 = 4,
    VK_FORMAT_B5G6R5_UNORM_PACK16 = 5,
    VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6,
    VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7,
    VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8,
    ... // 约 300+, 其中

43. Additional Capabilities

This chapter describes additional capabilities beyond the minimum capabilities described in the (Limits and Formats chapters, including: