固定功能顶点处理

顶点获取通过可配置的状态来控制,作为一个逻辑上独立的图形管线阶段。

顶点属性

顶点着色器可以定义输入变量,这些变量接收由绘制命令从一个或多个 VkBuffer 传输的顶点属性数据。顶点着色器输入变量通过间接绑定绑定到缓冲区,其中顶点着色器将一个顶点输入属性编号与每个变量关联,顶点输入属性与每个管线的顶点输入绑定关联,而顶点输入绑定通过 vkCmdBindVertexBuffers 命令与每个绘制的特定缓冲区关联。顶点输入属性和顶点输入绑定描述还包含格式信息,用于控制如何从缓冲区内存中提取数据并将其转换为顶点着色器期望的格式。

VkPhysicalDeviceLimits::maxVertexInputAttributes 个顶点输入属性和 VkPhysicalDeviceLimits::maxVertexInputBindings 个顶点输入绑定(每个都由从零开始的索引引用),其中至少有与顶点输入绑定一样多的顶点输入属性。应用程序可以将多个顶点输入属性交错存储在单个缓冲区中,并使用单个顶点输入绑定来访问这些属性。

在 GLSL 中,顶点着色器使用 location 布局限定符将输入变量与顶点输入属性编号关联。Component 布局限定符将顶点着色器输入变量的分量与顶点输入属性的分量关联。

GLSL 示例
// Assign location M to variableName
layout (location=M, component=2) in vec2 variableName;

// Assign locations [N,N+L) to the array elements of variableNameArray
layout (location=N) in vec4 variableNameArray[L];

在 SPIR-V 中,顶点着色器使用 Location 修饰将输入变量与顶点输入属性编号关联。Component 修饰将顶点着色器输入变量的分量与顶点输入属性的分量关联。LocationComponent 修饰通过 OpDecorate 指令指定。

SPIR-V 示例
               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "variableName"
               OpName %15 "variableNameArray"
               OpDecorate %18 BuiltIn VertexIndex
               OpDecorate %19 BuiltIn InstanceIndex
               OpDecorate %9 Location M
               OpDecorate %9 Component 2
               OpDecorate %15 Location N
               ...
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeVector %6 2
          %8 = OpTypePointer Input %7
          %9 = OpVariable %8 Input
         %10 = OpTypeVector %6 4
         %11 = OpTypeInt 32 0
         %12 = OpConstant %11 L
         %13 = OpTypeArray %10 %12
         %14 = OpTypePointer Input %13
         %15 = OpVariable %14 Input
               ...

属性位置和组件分配

Location 修饰指定使用哪个顶点输入属性来读取和解释变量将要消耗的数据。

当使用 16 位或 32 位标量或向量数据类型声明的顶点着色器输入变量被分配 Location 时,其值取自使用对应的 VkVertexInputAttributeDescription::location 指定的输入属性的分量。使用的分量取决于变量的类型和变量声明中指定的 Component 修饰,如 16 位和 32 位输入变量访问的输入属性分量 中所述。任何 16 位或 32 位标量或向量输入都将消耗单个 Location。对于 16 位和 32 位数据类型,缺少的组件将使用 下文 中描述的默认值填充。

如果实现支持 storageInputOutput16,则顶点着色器输入变量的宽度可以为 16 位。

在以下所有组件分配规范中,如果启用了 vertexAttributeRobustness 并且没有为正在读取的着色器顶点属性 Location 指定 VkVertexInputAttributeDescription::location,则对于下面指定的每个等效的 (x,y,z,w) 组件消耗条目,将使用值 (0,0,0,0) 或 (0,0,0,1)。

表 1. 16 位和 32 位输入变量访问的输入属性分量
16 位或 32 位数据类型 Component 修饰 消耗的分量

标量

0 或未指定

(x, o, o, o)

标量

1

(o, y, o, o)

标量

2

(o, o, z, o)

标量

3

(o, o, o, w)

双分量向量

0 或未指定

(x, y, o, o)

双分量向量

1

(o, y, z, o)

双分量向量

2

(o, o, z, w)

三分量向量

0 或未指定

(x, y, z, o)

三分量向量

1

(o, y, z, w)

四分量向量

0 或未指定

(x, y, z, w)

由“o”指示的分量可供其他来自同一属性的输入变量使用,如果使用,则要么用输入格式中的相应分量(如果存在)填充,要么使用默认值填充。

当使用 32 位浮点矩阵类型声明的顶点着色器输入变量被分配 Location i 时,其值取自从对应的 VkVertexInputAttributeDescription::location 开始的连续输入属性。此类矩阵被视为列向量的数组,其值取自 32 位输入矩阵变量访问的输入属性 中标识的输入属性。 VkVertexInputAttributeDescription::format 必须使用与相应类型的列向量对应的 VkFormat 指定。Component 修饰不能与矩阵类型一起使用。

表 2. 32 位输入矩阵变量访问的输入属性
数据类型 列向量类型 消耗的位置 消耗的分量

mat2

双分量向量

i, i+1

(x, y, o, o), (x, y, o, o)

mat2x3

三分量向量

i, i+1

(x, y, z, o), (x, y, z, o)

mat2x4

四分量向量

i, i+1

(x, y, z, w), (x, y, z, w)

mat3x2

双分量向量

i, i+1, i+2

(x, y, o, o), (x, y, o, o), (x, y, o, o)

mat3

三分量向量

i, i+1, i+2

(x, y, z, o), (x, y, z, o), (x, y, z, o)

mat3x4

四分量向量

i, i+1, i+2

(x, y, z, w), (x, y, z, w), (x, y, z, w)

mat4x2

双分量向量

i, i+1, i+2, i+3

(x, y, o, o), (x, y, o, o), (x, y, o, o), (x, y, o, o)

mat4x3

三分量向量

i, i+1, i+2, i+3

(x, y, z, o), (x, y, z, o), (x, y, z, o), (x, y, z, o)

mat4

四分量向量

i, i+1, i+2, i+3

(x, y, z, w), (x, y, z, w), (x, y, z, w), (x, y, z, w)

用 “o” 表示的组件可供来自同一属性的其他输入变量使用,如果使用,则会填充来自输入的相应组件(如果存在),或使用默认值。

当使用标量或向量 64 位数据类型声明的顶点着色器输入变量被分配 Location i 时,其值取自连续的输入属性,从相应的 VkVertexInputAttributeDescription::location 开始。使用的 Location 插槽和 Component 字取决于变量的类型和变量声明中指定的 Component 修饰符,如 64 位输入变量访问的输入属性位置和组件 中所述。对于 64 位数据类型,不提供默认属性值。输入变量不得使用超出属性提供的组件数量。

表 3. 64 位输入变量访问的输入属性位置和组件
输入格式 消耗的位置 64 位数据类型 Location 修饰符 Component 修饰 使用的 32 位组件

R64

i

标量

i

0 或未指定

(x, y, -, -)

R64G64

i

标量

i

0 或未指定

(x, y, o, o)

标量

i

2

(o, o, z, w)

双分量向量

i

0 或未指定

(x, y, z, w)

R64G64B64

i, i+1

标量

i

0 或未指定

(x, y, o, o), (o, o, -, -)

标量

i

2

(o, o, z, w), (o, o, -, -)

标量

i+1

0 或未指定

(o, o, o, o), (x, y, -, -)

双分量向量

i

0 或未指定

(x, y, z, w), (o, o, -, -)

三分量向量

i

未指定

(x, y, z, w), (x, y, -, -)

R64G64B64A64

i, i+1

标量

i

0 或未指定

(x, y, o, o), (o, o, o, o)

标量

i

2

(o, o, z, w), (o, o, o, o)

标量

i+1

0 或未指定

(o, o, o, o), (x, y, o, o)

标量

i+1

2

(o, o, o, o), (o, o, z, w)

双分量向量

i

0 或未指定

(x, y, z, w), (o, o, o, o)

双分量向量

i+1

0 或未指定

(o, o, o, o), (x, y, z, w)

三分量向量

i

未指定

(x, y, z, w), (x, y, o, o)

四分量向量

i

未指定

(x, y, z, w), (x, y, z, w)

用 “o” 表示的组件可供来自同一属性的其他输入变量使用。 用 “-” 表示的组件不适用于输入变量,因为 64 位数据类型没有提供默认值,并且输入格式不提供数据。

当使用 64 位浮点矩阵类型声明的顶点着色器输入变量被分配 Location i 时,其值取自连续的输入属性位置。此类矩阵被视为列向量数组,其值取自输入属性,如 64 位输入变量访问的输入属性位置和组件 中所示。每个列向量从紧跟前一个列向量的最后一个 LocationLocation 开始。分配给每个矩阵的属性和组件数量由矩阵维度决定,范围从两个到八个位置。

当使用数组类型声明的顶点着色器输入变量被分配位置时,其值取自连续的输入属性,从相应的 VkVertexInputAttributeDescription::location 开始。分配给每个元素的属性和组件的数量根据数组元素的类型和数组声明中指定的 Component 修饰符(如果有)确定,如上所述。数组的每个元素按顺序分配给连续的位置,但都在每个位置内的同一指定组件。

仅支持使用上述指定的数据类型和组件修饰符声明的输入变量。仅当两个变量的 Component 字不重叠时,才允许它们共享同一个 Location 插槽。如果多个变量共享同一个 Location 插槽,它们必须都具有相同的 SPIR-V 浮点组件类型或都具有相同宽度的标量类型组件。

顶点输入描述

应用程序通过将 VkGraphicsPipelineCreateInfo::pVertexInputState 指针设置为 VkPipelineVertexInputStateCreateInfo 结构,指定作为图形管线创建一部分的顶点输入属性和顶点输入绑定描述。或者,如果使用启用了 VK_DYNAMIC_STATE_VERTEX_INPUT_EXT 动态状态创建图形管线,则顶点输入属性和顶点输入绑定描述将使用 vkCmdSetVertexInputEXT 动态指定,并且 VkGraphicsPipelineCreateInfo::pVertexInputState 指针将被忽略。

VkPipelineVertexInputStateCreateInfo 结构的定义如下:

// Provided by VK_VERSION_1_0
typedef struct VkPipelineVertexInputStateCreateInfo {
    VkStructureType                             sType;
    const void*                                 pNext;
    VkPipelineVertexInputStateCreateFlags       flags;
    uint32_t                                    vertexBindingDescriptionCount;
    const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
    uint32_t                                    vertexAttributeDescriptionCount;
    const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
} VkPipelineVertexInputStateCreateInfo;
  • sType 是一个 VkStructureType 值,用于标识此结构。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • flags 保留供将来使用。

  • vertexBindingDescriptionCountpVertexBindingDescriptions 中提供的顶点绑定描述的数量。

  • pVertexBindingDescriptions 是指向 VkVertexInputBindingDescription 结构数组的指针。

  • vertexAttributeDescriptionCountpVertexAttributeDescriptions 中提供的顶点属性描述的数量。

  • pVertexAttributeDescriptions 是指向 VkVertexInputAttributeDescription 结构数组的指针。

有效用法
  • VUID-VkPipelineVertexInputStateCreateInfo-vertexBindingDescriptionCount-00613
    vertexBindingDescriptionCount 必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-VkPipelineVertexInputStateCreateInfo-vertexAttributeDescriptionCount-00614
    vertexAttributeDescriptionCount 必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputAttributes

  • VUID-VkPipelineVertexInputStateCreateInfo-binding-00615
    对于 pVertexAttributeDescriptions 的每个元素指定的每个 bindingpVertexBindingDescriptions必须存在具有相同 binding 值的 VkVertexInputBindingDescription

  • VUID-VkPipelineVertexInputStateCreateInfo-pVertexBindingDescriptions-00616
    pVertexBindingDescriptions 的所有元素必须描述不同的绑定编号

  • VUID-VkPipelineVertexInputStateCreateInfo-pVertexAttributeDescriptions-00617
    pVertexAttributeDescriptions 的所有元素必须描述不同的属性位置

有效用法(隐式)
  • VUID-VkPipelineVertexInputStateCreateInfo-sType-sType
    sType 必须VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO

  • VUID-VkPipelineVertexInputStateCreateInfo-pNext-pNext
    pNext 必须NULL 或者指向 VkPipelineVertexInputDivisorStateCreateInfo 的有效实例的指针

  • VUID-VkPipelineVertexInputStateCreateInfo-sType-unique
    pNext 链中每个结构的 sType必须是唯一的

  • VUID-VkPipelineVertexInputStateCreateInfo-flags-zerobitmask
    flags 必须0

  • VUID-VkPipelineVertexInputStateCreateInfo-pVertexBindingDescriptions-parameter
    如果 vertexBindingDescriptionCount 不是 0,则 pVertexBindingDescriptions 必须是指向 vertexBindingDescriptionCount 个有效的 VkVertexInputBindingDescription 结构的数组的有效指针

  • VUID-VkPipelineVertexInputStateCreateInfo-pVertexAttributeDescriptions-parameter
    如果 vertexAttributeDescriptionCount 不是 0,则 pVertexAttributeDescriptions 必须是指向 vertexAttributeDescriptionCount 个有效的 VkVertexInputAttributeDescription 结构的数组的有效指针

// Provided by VK_VERSION_1_0
typedef VkFlags VkPipelineVertexInputStateCreateFlags;

VkPipelineVertexInputStateCreateFlags 是一个用于设置掩码的位掩码类型,但目前保留供将来使用。

每个顶点输入绑定由 VkVertexInputBindingDescription 结构指定,定义如下:

// Provided by VK_VERSION_1_0
typedef struct VkVertexInputBindingDescription {
    uint32_t             binding;
    uint32_t             stride;
    VkVertexInputRate    inputRate;
} VkVertexInputBindingDescription;
  • binding 是此结构描述的绑定编号。

  • stride 是缓冲区中连续元素之间的字节步幅。

  • inputRate 是一个 VkVertexInputRate 值,指定顶点属性寻址是顶点索引的函数还是实例索引的函数。

有效用法
  • VUID-VkVertexInputBindingDescription-binding-00618
    binding 必须小于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-VkVertexInputBindingDescription-stride-00619
    stride 必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputBindingStride

  • VUID-VkVertexInputBindingDescription-stride-04456
    如果启用了 VK_KHR_portability_subset 扩展,则 stride 必须VkPhysicalDevicePortabilitySubsetPropertiesKHR::minVertexInputBindingStrideAlignment 的倍数,并且至少与其一样大

有效用法(隐式)
  • VUID-VkVertexInputBindingDescription-inputRate-parameter
    inputRate 必须是有效的 VkVertexInputRate

VkVertexInputBindingDescription::inputRate 的可能值,指定从缓冲区中提取顶点属性的速率,如下所示:

// Provided by VK_VERSION_1_0
typedef enum VkVertexInputRate {
    VK_VERTEX_INPUT_RATE_VERTEX = 0,
    VK_VERTEX_INPUT_RATE_INSTANCE = 1,
} VkVertexInputRate;
  • VK_VERTEX_INPUT_RATE_VERTEX 指定顶点属性寻址是顶点索引的函数。

  • VK_VERTEX_INPUT_RATE_INSTANCE 指定顶点属性寻址是实例索引的函数。

每个顶点输入属性由 VkVertexInputAttributeDescription 结构指定,定义如下:

// Provided by VK_VERSION_1_0
typedef struct VkVertexInputAttributeDescription {
    uint32_t    location;
    uint32_t    binding;
    VkFormat    format;
    uint32_t    offset;
} VkVertexInputAttributeDescription;
  • location 是此属性的着色器输入位置编号。

  • binding 是此属性从中获取数据的绑定编号。

  • format 是顶点属性数据的大小和类型。

  • offset 是此属性相对于顶点输入绑定中元素起点的字节偏移量。

有效用法
  • VUID-VkVertexInputAttributeDescription-location-00620
    location 必须小于 VkPhysicalDeviceLimits::maxVertexInputAttributes

  • VUID-VkVertexInputAttributeDescription-binding-00621
    binding 必须小于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-VkVertexInputAttributeDescription-offset-00622
    offset 必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputAttributeOffset

  • VUID-VkVertexInputAttributeDescription-format-00623
    format格式特性 必须包含 VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT

  • VUID-VkVertexInputAttributeDescription-vertexAttributeAccessBeyondStride-04457
    如果启用了 VK_KHR_portability_subset 扩展,并且 VkPhysicalDevicePortabilitySubsetFeaturesKHR::vertexAttributeAccessBeyondStrideVK_FALSE,则 offset 加上 format 描述的顶点属性数据大小的总和必须不大于 binding 中引用的 VkVertexInputBindingDescription 中的 stride

有效用法(隐式)
  • VUID-VkVertexInputAttributeDescription-format-parameter
    format 必须是有效的 VkFormat

动态设置顶点输入属性和顶点输入绑定描述,请调用:

// Provided by VK_EXT_shader_object, VK_EXT_vertex_input_dynamic_state
void vkCmdSetVertexInputEXT(
    VkCommandBuffer                             commandBuffer,
    uint32_t                                    vertexBindingDescriptionCount,
    const VkVertexInputBindingDescription2EXT*  pVertexBindingDescriptions,
    uint32_t                                    vertexAttributeDescriptionCount,
    const VkVertexInputAttributeDescription2EXT* pVertexAttributeDescriptions);
  • commandBuffer 是将记录命令的命令缓冲区。

  • vertexBindingDescriptionCountpVertexBindingDescriptions 中提供的顶点绑定描述的数量。

  • pVertexBindingDescriptions 是指向 VkVertexInputBindingDescription2EXT 结构数组的指针。

  • vertexAttributeDescriptionCountpVertexAttributeDescriptions 中提供的顶点属性描述的数量。

  • pVertexAttributeDescriptions 是指向 VkVertexInputAttributeDescription2EXT 结构数组的指针。

当使用 着色器对象 绘图时,或者当使用在 VkPipelineDynamicStateCreateInfo::pDynamicStates 中设置的 VK_DYNAMIC_STATE_VERTEX_INPUT_EXT 创建图形管线时,此命令为后续绘图命令设置顶点输入属性和顶点输入绑定描述状态。否则,此状态由用于创建当前活动的管线的 VkGraphicsPipelineCreateInfo::pVertexInputState 值指定。

如果使用 着色器对象 绘图,或者如果绑定的管线状态对象也是在启用了 VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE 动态状态的情况下创建的,则可以使用 vkCmdBindVertexBuffers2 来代替 vkCmdSetVertexInputEXT 以动态设置步幅。

pVertexAttributeDescriptions 数组中未指定的范围 [0,VkPhysicalDeviceLimits::maxVertexInputAttributes) 内任何位置的顶点属性描述都变为未定义

有效用法
  • VUID-vkCmdSetVertexInputEXT-None-08546
    必须启用 vertexInputDynamicState 功能或 shaderObject 功能,或同时启用两者

  • VUID-vkCmdSetVertexInputEXT-vertexBindingDescriptionCount-04791
    vertexBindingDescriptionCount 必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-vkCmdSetVertexInputEXT-vertexAttributeDescriptionCount-04792
    vertexAttributeDescriptionCount 必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputAttributes

  • VUID-vkCmdSetVertexInputEXT-binding-04793
    对于 pVertexAttributeDescriptions 中每个元素指定的每个 binding,在 pVertexBindingDescriptions必须 存在一个具有相同 binding 值的 VkVertexInputBindingDescription2EXT

  • VUID-vkCmdSetVertexInputEXT-pVertexBindingDescriptions-04794
    pVertexBindingDescriptions 的所有元素必须描述不同的绑定编号

  • VUID-vkCmdSetVertexInputEXT-pVertexAttributeDescriptions-04795
    pVertexAttributeDescriptions 的所有元素必须描述不同的属性位置

有效用法(隐式)
  • VUID-vkCmdSetVertexInputEXT-commandBuffer-parameter
    commandBuffer 必须 是一个有效的 VkCommandBuffer 句柄。

  • VUID-vkCmdSetVertexInputEXT-pVertexBindingDescriptions-parameter
    如果 vertexBindingDescriptionCount 不为 0,则 pVertexBindingDescriptions 必须 是指向 vertexBindingDescriptionCount 个有效 VkVertexInputBindingDescription2EXT 结构的有效指针。

  • VUID-vkCmdSetVertexInputEXT-pVertexAttributeDescriptions-parameter
    如果 vertexAttributeDescriptionCount 不为 0,则 pVertexAttributeDescriptions 必须 是指向 vertexAttributeDescriptionCount 个有效 VkVertexInputAttributeDescription2EXT 结构的有效指针。

  • VUID-vkCmdSetVertexInputEXT-commandBuffer-recording
    commandBuffer 必须 处于 记录状态

  • VUID-vkCmdSetVertexInputEXT-commandBuffer-cmdpool
    分配 commandBufferVkCommandPool 必须 支持图形操作。

  • VUID-vkCmdSetVertexInputEXT-videocoding
    此命令 必须 仅在视频编码范围之外调用。

主机同步
  • commandBuffer 的主机访问 必须 进行外部同步。

  • 对分配 commandBufferVkCommandPool 的主机访问 必须 进行外部同步。

命令属性
命令缓冲区级别 渲染通道范围 视频编码范围 支持的队列类型 命令类型

主要
次要

两者

外部

图形

状态

VkVertexInputBindingDescription2EXT 结构定义如下:

// Provided by VK_EXT_shader_object, VK_EXT_vertex_input_dynamic_state
typedef struct VkVertexInputBindingDescription2EXT {
    VkStructureType      sType;
    void*                pNext;
    uint32_t             binding;
    uint32_t             stride;
    VkVertexInputRate    inputRate;
    uint32_t             divisor;
} VkVertexInputBindingDescription2EXT;
  • sType 是一个 VkStructureType 值,用于标识此结构。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • binding 是此结构描述的绑定编号。

  • stride 是缓冲区中连续元素之间的字节步幅。

  • inputRate 是一个 VkVertexInputRate 值,指定顶点属性寻址是顶点索引的函数还是实例索引的函数。

  • 当启用实例化渲染时,divisor 是使用相同顶点属性值的连续实例的数量。如果启用了 vertexAttributeInstanceRateDivisor 特性,则此成员 可以1 以外的值。例如,如果除数为 N,则在移动到下一个顶点属性之前,相同的顶点属性将应用于 N 个连续实例。divisor 的最大值取决于实现,可以使用 VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT::maxVertexAttribDivisor 查询。如果启用了 vertexAttributeInstanceRateZeroDivisor 特性,则 divisor 的值 可以0。在这种情况下,相同的顶点属性将应用于所有实例。

有效用法
  • VUID-VkVertexInputBindingDescription2EXT-binding-04796
    binding 必须小于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-VkVertexInputBindingDescription2EXT-stride-04797
    stride 必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputBindingStride

  • VUID-VkVertexInputBindingDescription2EXT-divisor-04798
    如果未启用 vertexAttributeInstanceRateZeroDivisor 特性,则 divisor 必须 不为 0

  • VUID-VkVertexInputBindingDescription2EXT-divisor-04799
    如果未启用 vertexAttributeInstanceRateDivisor 特性,则 divisor 必须1

  • VUID-VkVertexInputBindingDescription2EXT-divisor-06226
    divisor 必须0VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT::maxVertexAttribDivisor(包括)之间的值。

  • VUID-VkVertexInputBindingDescription2EXT-divisor-06227
    如果 divisor 不为 1,则 inputRate 必须VK_VERTEX_INPUT_RATE_INSTANCE 类型。

有效用法(隐式)
  • VUID-VkVertexInputBindingDescription2EXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_VERTEX_INPUT_BINDING_DESCRIPTION_2_EXT

  • VUID-VkVertexInputBindingDescription2EXT-inputRate-parameter
    inputRate 必须是有效的 VkVertexInputRate

VkVertexInputAttributeDescription2EXT 结构定义如下:

// Provided by VK_EXT_shader_object, VK_EXT_vertex_input_dynamic_state
typedef struct VkVertexInputAttributeDescription2EXT {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           location;
    uint32_t           binding;
    VkFormat           format;
    uint32_t           offset;
} VkVertexInputAttributeDescription2EXT;
  • sType 是一个 VkStructureType 值,用于标识此结构。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • location 是此属性的着色器输入位置编号。

  • binding 是此属性从中获取数据的绑定编号。

  • format 是顶点属性数据的大小和类型。

  • offset 是此属性相对于顶点输入绑定中元素起点的字节偏移量。

有效用法
  • VUID-VkVertexInputAttributeDescription2EXT-location-06228
    location 必须小于 VkPhysicalDeviceLimits::maxVertexInputAttributes

  • VUID-VkVertexInputAttributeDescription2EXT-binding-06229
    binding 必须小于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-VkVertexInputAttributeDescription2EXT-offset-06230
    offset 必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputAttributeOffset

  • VUID-VkVertexInputAttributeDescription2EXT-format-04805
    format格式特性 必须包含 VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT

  • VUID-VkVertexInputAttributeDescription2EXT-vertexAttributeAccessBeyondStride-04806
    如果启用了 VK_KHR_portability_subset 扩展,并且 VkPhysicalDevicePortabilitySubsetFeaturesKHR::vertexAttributeAccessBeyondStrideVK_FALSE,则 offset 的总和加上 format 描述的顶点属性数据的大小 必须 不大于 binding 中引用的 VkVertexInputBindingDescription2EXT 中的 stride

有效用法(隐式)
  • VUID-VkVertexInputAttributeDescription2EXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT

  • VUID-VkVertexInputAttributeDescription2EXT-format-parameter
    format 必须是有效的 VkFormat

要将顶点缓冲区绑定到命令缓冲区以用于后续的绘制命令,请调用:

// Provided by VK_VERSION_1_0
void vkCmdBindVertexBuffers(
    VkCommandBuffer                             commandBuffer,
    uint32_t                                    firstBinding,
    uint32_t                                    bindingCount,
    const VkBuffer*                             pBuffers,
    const VkDeviceSize*                         pOffsets);
  • commandBuffer 是将命令记录到其中的命令缓冲区。

  • firstBinding 是第一个顶点输入绑定的索引,该绑定的状态由该命令更新。

  • bindingCount 是由该命令更新状态的顶点输入绑定的数量。

  • pBuffers 是指向缓冲区句柄数组的指针。

  • pOffsets 是指向缓冲区偏移数组的指针。

pBufferspOffsets 数组的第 i 个元素中取出的值将替换顶点输入绑定 firstBinding + i 的当前状态,其中 i 的取值范围是 [0, bindingCount)。顶点输入绑定的起始位置更新为 pBuffers[i] 缓冲区起始位置的偏移量 pOffsets[i] 处。所有使用这些绑定的顶点输入属性都将在后续的绘制命令中使用这些更新后的地址进行地址计算。如果启用了nullDescriptor特性,则 pBuffers 的元素可以VK_NULL_HANDLE,并且可以被顶点着色器使用。如果顶点输入属性绑定到一个为 VK_NULL_HANDLE 的顶点输入绑定,则从内存中取出的值被认为是零,并且缺失的 G、B 或 A 分量会(0填充。

有效用法
  • VUID-vkCmdBindVertexBuffers-firstBinding-00624
    firstBinding 必须小于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-vkCmdBindVertexBuffers-firstBinding-00625
    firstBindingbindingCount 的总和必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-vkCmdBindVertexBuffers-pOffsets-00626
    pOffsets 的所有元素必须小于 pBuffers 中相应元素的大小

  • VUID-vkCmdBindVertexBuffers-pBuffers-00627
    pBuffers 的所有元素必须已使用 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT 标志创建

  • VUID-vkCmdBindVertexBuffers-pBuffers-00628
    pBuffers 的每个非稀疏元素必须完全且连续地绑定到单个 VkDeviceMemory 对象

  • VUID-vkCmdBindVertexBuffers-pBuffers-04001
    如果未启用nullDescriptor特性,则 pBuffers 的所有元素必须不能是 VK_NULL_HANDLE

  • VUID-vkCmdBindVertexBuffers-pBuffers-04002
    如果 pBuffers 的某个元素是 VK_NULL_HANDLE,则 pOffsets 的相应元素必须为零

有效用法(隐式)
  • VUID-vkCmdBindVertexBuffers-commandBuffer-parameter
    commandBuffer 必须 是一个有效的 VkCommandBuffer 句柄。

  • VUID-vkCmdBindVertexBuffers-pBuffers-parameter
    pBuffers 必须是指向 bindingCount 个有效或 VK_NULL_HANDLE VkBuffer 句柄的数组的有效指针

  • VUID-vkCmdBindVertexBuffers-pOffsets-parameter
    pOffsets 必须是指向 bindingCountVkDeviceSize 值的数组的有效指针

  • VUID-vkCmdBindVertexBuffers-commandBuffer-recording
    commandBuffer 必须 处于 记录状态

  • VUID-vkCmdBindVertexBuffers-commandBuffer-cmdpool
    分配 commandBufferVkCommandPool 必须 支持图形操作。

  • VUID-vkCmdBindVertexBuffers-videocoding
    此命令 必须 仅在视频编码范围之外调用。

  • VUID-vkCmdBindVertexBuffers-bindingCount-arraylength
    bindingCount 必须大于 0

  • VUID-vkCmdBindVertexBuffers-commonparent
    commandBufferpBuffers 的有效句柄(非忽略参数)元素都必须已从同一个 VkDevice 创建、分配或检索

主机同步
  • commandBuffer 的主机访问 必须 进行外部同步。

  • 对分配 commandBufferVkCommandPool 的主机访问 必须 进行外部同步。

命令属性
命令缓冲区级别 渲染通道范围 视频编码范围 支持的队列类型 命令类型

主要
次要

两者

外部

图形

状态

或者,为了将顶点缓冲区及其大小和步幅绑定到命令缓冲区以供后续绘制命令使用,请调用

// Provided by VK_VERSION_1_3
void vkCmdBindVertexBuffers2(
    VkCommandBuffer                             commandBuffer,
    uint32_t                                    firstBinding,
    uint32_t                                    bindingCount,
    const VkBuffer*                             pBuffers,
    const VkDeviceSize*                         pOffsets,
    const VkDeviceSize*                         pSizes,
    const VkDeviceSize*                         pStrides);

或等效的命令

// Provided by VK_EXT_extended_dynamic_state, VK_EXT_shader_object
void vkCmdBindVertexBuffers2EXT(
    VkCommandBuffer                             commandBuffer,
    uint32_t                                    firstBinding,
    uint32_t                                    bindingCount,
    const VkBuffer*                             pBuffers,
    const VkDeviceSize*                         pOffsets,
    const VkDeviceSize*                         pSizes,
    const VkDeviceSize*                         pStrides);
  • commandBuffer 是将命令记录到其中的命令缓冲区。

  • firstBinding 是第一个顶点输入绑定的索引,该绑定的状态由该命令更新。

  • bindingCount 是由该命令更新状态的顶点输入绑定的数量。

  • pBuffers 是指向缓冲区句柄数组的指针。

  • pOffsets 是指向缓冲区偏移数组的指针。

  • pSizesNULL 或指向从 pBuffers 绑定顶点数据的字节大小的数组的指针。

  • pStridesNULL 或指向缓冲区步幅数组的指针。

pBufferspOffsets 数组的第 i 个元素中取出的值将替换顶点输入绑定 firstBinding + i 的当前状态,其中 i 的取值范围是 [0, bindingCount)。顶点输入绑定的起始位置更新为 pBuffers[i] 缓冲区起始位置的偏移量 pOffsets[i] 处。如果 pSizes 不为 NULL,则 pSizes[i] 指定从 pBuffers[i] 加上 pOffsets[i] 对应的元素开始的顶点缓冲区的绑定大小。如果 pSizes[i] 是 VK_WHOLE_SIZE,则绑定大小是从 pBuffers[i] 加上 pOffsets[i] 到缓冲区 pBuffers[i] 的末尾。所有使用这些绑定的顶点输入属性都将在后续的绘制命令中使用这些更新后的地址进行地址计算。如果启用了nullDescriptor特性,则 pBuffers 的元素可以VK_NULL_HANDLE,并且可以被顶点着色器使用。如果顶点输入属性绑定到一个为 VK_NULL_HANDLE 的顶点输入绑定,则从内存中取出的值被认为是零,并且缺失的 G、B 或 A 分量会(0填充。

此命令还动态设置缓冲区 pBuffers[i] 中连续元素之间的字节步幅为相应的 pStrides[i] 值,当使用着色器对象进行绘制时,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates 中设置了 VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE 时。否则,步幅由用于创建当前活动管线的 VkVertexInputBindingDescription::stride 值指定。

如果使用着色器对象进行绘制,或者如果绑定的管线状态对象也是通过启用 VK_DYNAMIC_STATE_VERTEX_INPUT_EXT 动态状态创建的,则可以使用 vkCmdSetVertexInputEXT 代替 vkCmdBindVertexBuffers2 来设置步幅。

与设置相同的静态状态不同,pStrides 必须介于 0 和绑定中属性的最大范围之间。vkCmdSetVertexInputEXT 没有此限制,因此如果需要其他步幅值,则可以使用它。

有效用法
  • VUID-vkCmdBindVertexBuffers2-firstBinding-03355
    firstBinding 必须小于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-vkCmdBindVertexBuffers2-firstBinding-03356
    firstBindingbindingCount 的总和必须小于或等于 VkPhysicalDeviceLimits::maxVertexInputBindings

  • VUID-vkCmdBindVertexBuffers2-pOffsets-03357
    如果 pSizes 不为 NULL,则 pOffsets 的所有元素必须小于 pBuffers 中相应元素的大小

  • VUID-vkCmdBindVertexBuffers2-pSizes-03358
    如果 pSizes 不为 NULL,则 pOffsets 加上 pSizes(其中 pSizes 不为 VK_WHOLE_SIZE)的所有元素必须小于或等于 pBuffers 中相应元素的大小

  • VUID-vkCmdBindVertexBuffers2-pBuffers-03359
    pBuffers 的所有元素必须已使用 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT 标志创建

  • VUID-vkCmdBindVertexBuffers2-pBuffers-03360
    pBuffers 的每个非稀疏元素必须完全且连续地绑定到单个 VkDeviceMemory 对象

  • VUID-vkCmdBindVertexBuffers2-pBuffers-04111
    如果未启用nullDescriptor特性,则 pBuffers 的所有元素必须不能是 VK_NULL_HANDLE

  • VUID-vkCmdBindVertexBuffers2-pBuffers-04112
    如果 pBuffers 的某个元素是 VK_NULL_HANDLE,则 pOffsets 的相应元素必须为零

  • VUID-vkCmdBindVertexBuffers2-pStrides-03362
    如果 pStrides 不为 NULL,则 pStrides 的每个元素**必须**小于或等于 VkPhysicalDeviceLimits::maxVertexInputBindingStride

  • VUID-vkCmdBindVertexBuffers2-pStrides-06209
    如果 pStrides 不为 NULL,则 pStrides 的每个元素**必须**为 0,或大于等于从对应绑定获取的所有顶点输入属性的最大范围,其中范围计算为 VkVertexInputAttributeDescription::offset 加上 VkVertexInputAttributeDescription::format 的大小。

有效用法(隐式)
  • VUID-vkCmdBindVertexBuffers2-commandBuffer-parameter
    commandBuffer 必须 是一个有效的 VkCommandBuffer 句柄。

  • VUID-vkCmdBindVertexBuffers2-pBuffers-parameter
    pBuffers 必须是指向 bindingCount 个有效或 VK_NULL_HANDLE VkBuffer 句柄的数组的有效指针

  • VUID-vkCmdBindVertexBuffers2-pOffsets-parameter
    pOffsets 必须是指向 bindingCountVkDeviceSize 值的数组的有效指针

  • VUID-vkCmdBindVertexBuffers2-pSizes-parameter
    如果 pSizes 不为 NULL,则 pSizes **必须**是指向 bindingCountVkDeviceSize 值的数组的有效指针。

  • VUID-vkCmdBindVertexBuffers2-pStrides-parameter
    如果 pStrides 不为 NULL,则 pStrides **必须**是指向 bindingCountVkDeviceSize 值的数组的有效指针。

  • VUID-vkCmdBindVertexBuffers2-commandBuffer-recording
    commandBuffer 必须 处于 记录状态

  • VUID-vkCmdBindVertexBuffers2-commandBuffer-cmdpool
    分配 commandBufferVkCommandPool 必须 支持图形操作。

  • VUID-vkCmdBindVertexBuffers2-videocoding
    此命令 必须 仅在视频编码范围之外调用。

  • VUID-vkCmdBindVertexBuffers2-bindingCount-arraylength
    如果 pSizespStrides 中的任何一个不为 NULL,则 bindingCount **必须**大于 0

  • VUID-vkCmdBindVertexBuffers2-commonparent
    commandBufferpBuffers 的有效句柄(非忽略参数)元素都必须已从同一个 VkDevice 创建、分配或检索

主机同步
  • commandBuffer 的主机访问 必须 进行外部同步。

  • 对分配 commandBufferVkCommandPool 的主机访问 必须 进行外部同步。

命令属性
命令缓冲区级别 渲染通道范围 视频编码范围 支持的队列类型 命令类型

主要
次要

两者

外部

图形

状态

实例化渲染中的顶点属性除数

如果启用了 vertexAttributeInstanceRateDivisor 功能,并且 VkPipelineVertexInputStateCreateInfopNext 链包含一个 VkPipelineVertexInputDivisorStateCreateInfo 结构,则该结构控制在启用实例化渲染时如何将顶点属性分配给实例。

VkPipelineVertexInputDivisorStateCreateInfo 结构定义如下

// Provided by VK_VERSION_1_4
typedef struct VkPipelineVertexInputDivisorStateCreateInfo {
    VkStructureType                                  sType;
    const void*                                      pNext;
    uint32_t                                         vertexBindingDivisorCount;
    const VkVertexInputBindingDivisorDescription*    pVertexBindingDivisors;
} VkPipelineVertexInputDivisorStateCreateInfo;

或等效的

// Provided by VK_KHR_vertex_attribute_divisor
typedef VkPipelineVertexInputDivisorStateCreateInfo VkPipelineVertexInputDivisorStateCreateInfoKHR;

或等效的

// Provided by VK_EXT_vertex_attribute_divisor
typedef VkPipelineVertexInputDivisorStateCreateInfo VkPipelineVertexInputDivisorStateCreateInfoEXT;
  • sType 是一个 VkStructureType 值,用于标识此结构。

  • pNextNULL 或指向扩展此结构的结构的指针。

  • vertexBindingDivisorCountpVertexBindingDivisors 数组中的元素数量。

  • pVertexBindingDivisors 是指向 VkVertexInputBindingDivisorDescription 结构数组的指针,该数组指定每个绑定的除数值。

有效用法(隐式)
  • VUID-VkPipelineVertexInputDivisorStateCreateInfo-sType-sType
    sType **必须**为 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO

  • VUID-VkPipelineVertexInputDivisorStateCreateInfo-pVertexBindingDivisors-parameter
    pVertexBindingDivisors **必须**是指向 vertexBindingDivisorCountVkVertexInputBindingDivisorDescription 结构的数组的有效指针

  • VUID-VkPipelineVertexInputDivisorStateCreateInfo-vertexBindingDivisorCount-arraylength
    vertexBindingDivisorCount **必须**大于 0

每个绑定的单独除数值使用 VkVertexInputBindingDivisorDescription 结构指定,该结构定义如下

// Provided by VK_VERSION_1_4
typedef struct VkVertexInputBindingDivisorDescription {
    uint32_t    binding;
    uint32_t    divisor;
} VkVertexInputBindingDivisorDescription;

或等效的

// Provided by VK_KHR_vertex_attribute_divisor
typedef VkVertexInputBindingDivisorDescription VkVertexInputBindingDivisorDescriptionKHR;

或等效的

// Provided by VK_EXT_vertex_attribute_divisor
typedef VkVertexInputBindingDivisorDescription VkVertexInputBindingDivisorDescriptionEXT;
  • binding 是指定除数的绑定编号。

  • divisor 是在启用实例化渲染时,将使用相同的顶点属性值的连续实例数。例如,如果除数是 N,则在移动到下一个顶点属性之前,相同的顶点属性将应用于 N 个连续的实例。divisor 的最大值取决于实现,可以使用 VkPhysicalDeviceVertexAttributeDivisorProperties::maxVertexAttribDivisor 查询。如果启用了 vertexAttributeInstanceRateZeroDivisor 功能,则 divisor 的值**可以**为 0。在这种情况下,相同的顶点属性将应用于所有实例。

如果未使用此结构为属性定义除数值,则除数具有 1 的逻辑默认值。

有效用法

顶点输入地址计算

每个 vertexIndexinstanceIndex 的每个属性的地址计算如下

bufferBindingAddress = buffer[binding].baseAddress + offset[binding];

if (bindingDesc.inputRate == VK_VERTEX_INPUT_RATE_VERTEX)
    effectiveVertexOffset = vertexIndex * stride;
else
    if (divisor == 0)
        effectiveVertexOffset = firstInstance * stride;
    else
        effectiveVertexOffset = (firstInstance + ((instanceIndex - firstInstance) / divisor)) * stride;

attribAddress = bufferBindingAddress + effectiveVertexOffset + attribDesc.offset;

顶点输入提取

对于每个属性,原始数据从 attribAddress 开始提取,并根据 数值类型,从 VkVertexInputAttributeDescriptionformat 转换为浮点数、无符号整数或有符号整数。format 的数值类型 **必须** 与着色器中输入变量的数值类型匹配。当且仅当 format 是 64 位数据类型时,着色器中的输入变量 **必须** 声明为 64 位数据类型。如果 format 是 64 位格式,或者 legacyVertexAttributes 功能未启用,并且 format 是打包格式,则 attribAddress **必须** 是 打包格式 中描述的格式大小(以字节为单位)的倍数。否则,如果 format 是 64 位格式,或者 legacyVertexAttributes 功能未启用,则 attribAddress **必须** 是 format 指示的组件类型大小(以字节为单位)的倍数(参见 格式)。对于不是 64 位数据类型的属性,每个分量都根据其类型和大小(如 格式定义 部分中为每个 VkFormat 定义的那样)转换为输入变量的格式,使用 16 位浮点数无符号 11 位浮点数无符号 10 位浮点数定点数据转换共享指数到 RGB 中的适当公式。小于 32 位的有符号整数分量进行符号扩展。不是 64 位数据类型的属性以与 转换为 RGBA 中描述的相同方式扩展为四个分量。顶点着色器输入变量中的分量数量不必与格式中的分量数量完全匹配。如果顶点着色器具有较少的分量,则丢弃额外的分量。