着色器

着色器指定在图形和计算管线的相应阶段中为每个顶点、控制点、细分顶点、图元、片段或工作组执行的可编程操作。

图形管线包括顶点着色器执行,这是图元装配的结果,如果启用,则后跟在patch上操作的细分控制和评估着色器、如果启用,则后跟在图元上操作的几何着色器,以及如果存在,则后跟在由光栅化生成的片段上操作的片段着色器。在本规范中,顶点、细分控制、细分评估和几何着色器统称为光栅化前着色器阶段,并在光栅化之前的逻辑管线中发生。片段着色器在逻辑上发生在光栅化之后。

计算管线中仅包含计算着色器阶段。计算着色器在工作组中对计算调用进行操作。

着色器可以从输入变量读取,以及读取和写入输出变量。输入和输出变量可以用于在着色器阶段之间传输数据,或者允许着色器与执行环境中存在的值进行交互。同样,执行环境提供了描述功能的常量。

着色器变量使用着色器中的内置装饰与执行环境提供的输入和输出相关联。以下小节中记录了每个阶段可用的装饰。

着色器对象

着色器可以管线章节所述,编译并链接到管线对象中,或者如果启用了shaderObject特性,则可以编译为独立的按阶段着色器对象,这些对象可以在命令缓冲区上彼此独立绑定。与管线不同,着色器对象本质上不与任何特定的状态集绑定。相反,状态在命令缓冲区中动态指定。

每个着色器对象都表示一个已编译的着色器阶段,该阶段可以选择性地与其他一个或多个阶段链接。

着色器对象由 VkShaderEXT 句柄表示

// Provided by VK_EXT_shader_object
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderEXT)

着色器对象创建

着色器对象可以从作为 SPIR-V 提供的着色器代码创建,或者从物理设备特有的不透明、实现定义的二进制格式创建。

要创建一个或多个着色器对象,请调用

// Provided by VK_EXT_shader_object
VkResult vkCreateShadersEXT(
    VkDevice                                    device,
    uint32_t                                    createInfoCount,
    const VkShaderCreateInfoEXT*                pCreateInfos,
    const VkAllocationCallbacks*                pAllocator,
    VkShaderEXT*                                pShaders);
  • device 是创建着色器对象的逻辑设备。

  • createInfoCountpCreateInfospShaders 数组的长度。

  • pCreateInfos 是指向 VkShaderCreateInfoEXT 结构的数组的指针。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

  • pShaders 是指向 VkShaderEXT 句柄数组的指针,将在其中返回生成的着色器对象。

当此函数返回时,无论是否成功,都保证 pShaders 的每个元素都已被 VK_NULL_HANDLE 或有效的 VkShaderEXT 句柄覆盖。

这意味着当着色器创建失败时,应用程序可以通过查找 pShaders 中第一个 VK_NULL_HANDLE 元素来确定返回的错误与哪个着色器相关。这也意味着应用程序可以通过迭代 pShaders 数组并销毁每个不是 VK_NULL_HANDLE 的元素,从而可靠地从失败的调用中清理。

有效用法
  • VUID-vkCreateShadersEXT-stage-09670
    如果 pCreateInfos 的任何元素的 stage 成员是 VK_SHADER_STAGE_COMPUTE_BIT,则 device 必须至少支持一个具有 VK_QUEUE_COMPUTE_BIT 功能的队列族

  • VUID-vkCreateShadersEXT-stage-09671
    如果 pCreateInfos 的任何元素的 stage 成员是 VK_SHADER_STAGE_TASK_BIT_EXTVK_SHADER_STAGE_MESH_BIT_EXTVK_SHADER_STAGE_VERTEX_BITVK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BITVK_SHADER_STAGE_GEOMETRY_BITVK_SHADER_STAGE_FRAGMENT_BIT,则 device 必须至少支持一个具有 VK_QUEUE_GRAPHICS_BIT 功能的队列族

  • VUID-vkCreateShadersEXT-None-08400
    shaderObject 功能必须启用

  • VUID-vkCreateShadersEXT-pCreateInfos-08402
    如果 pCreateInfos 中任何元素的 flags 成员包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,则 pCreateInfos 中所有 stageVK_SHADER_STAGE_VERTEX_BITVK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BITVK_SHADER_STAGE_GEOMETRY_BITVK_SHADER_STAGE_FRAGMENT_BIT 的其他元素的 flags 成员必须也包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT

  • VUID-vkCreateShadersEXT-pCreateInfos-08403
    如果 pCreateInfos 中任何元素的 flags 成员包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,则 pCreateInfos 中所有 stageVK_SHADER_STAGE_TASK_BIT_EXTVK_SHADER_STAGE_MESH_BIT_EXT 的其他元素的 flags 成员必须也包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT

  • VUID-vkCreateShadersEXT-pCreateInfos-08404
    如果 pCreateInfos 中任何 stageVK_SHADER_STAGE_TASK_BIT_EXTVK_SHADER_STAGE_MESH_BIT_EXT 的元素的 flags 成员包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,则必须不存在 pCreateInfosstageVK_SHADER_STAGE_VERTEX_BIT 且其 flags 成员包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT 的元素。

  • VUID-vkCreateShadersEXT-pCreateInfos-08405
    如果 pCreateInfos 中存在任何 stageVK_SHADER_STAGE_MESH_BIT_EXT 且其 flags 成员同时包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXTVK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT 的元素,则必须不存在 pCreateInfosstageVK_SHADER_STAGE_TASK_BIT_EXT 且其 flags 成员包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT 的元素。

  • VUID-vkCreateShadersEXT-pCreateInfos-08409
    对于 pCreateInfosflags 成员包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT 的每个元素,如果存在任何其他 pCreateInfos 的元素的 stage 在逻辑上晚于前者的 stage,并且其 flags 成员也包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,则前者的 nextStage 必须等于 stage 在逻辑上最早,并且在前者 stage 之后,且 flags 成员也包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT 的元素的 stage

  • VUID-vkCreateShadersEXT-pCreateInfos-08410
    pCreateInfos 中每个 flags 成员包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT 的元素的 stage 成员必须是唯一的。

  • VUID-vkCreateShadersEXT-pCreateInfos-08411
    pCreateInfos 中所有 flags 成员包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT 的元素的 codeType 成员必须相同。

  • VUID-vkCreateShadersEXT-pCreateInfos-08867
    如果 pCreateInfos 包含 VK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 的元素,并且这两个元素的 flags 都包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,并且这两个元素的 codeType 都是 VK_SHADER_CODE_TYPE_SPIRV_EXT,并且 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT 阶段的 pCode 包含一个指定细分类型的 OpExecutionMode 指令,则它必须VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 阶段中指定的细分类型匹配。

  • VUID-vkCreateShadersEXT-pCreateInfos-08868
    如果 pCreateInfos 包含 VK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 的元素,并且这两个元素的 flags 都包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,并且这两个元素的 codeType 都是 VK_SHADER_CODE_TYPE_SPIRV_EXT,并且 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT 阶段的 pCode 包含一个指定三角形方向的 OpExecutionMode 指令,则它必须VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 阶段中指定的三角形方向匹配。

  • VUID-vkCreateShadersEXT-pCreateInfos-08869
    如果 pCreateInfos 包含 VK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 的元素,并且这两个元素的 flags 都包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,并且这两个元素的 codeType 都是 VK_SHADER_CODE_TYPE_SPIRV_EXT,并且 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT 阶段的 pCode 包含一个指定 PointModeOpExecutionMode 指令,则 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 阶段必须也包含一个指定 PointModeOpExecutionMode 指令。

  • VUID-vkCreateShadersEXT-pCreateInfos-08870
    如果 pCreateInfos 包含 VK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 的元素,并且这两个元素的 flags 都包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,并且这两个元素的 codeType 都是 VK_SHADER_CODE_TYPE_SPIRV_EXT,并且 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT 阶段的 pCode 包含一个指定细分图元边缘上分段间距的 OpExecutionMode 指令,则它必须VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 阶段中指定的分段间距匹配。

  • VUID-vkCreateShadersEXT-pCreateInfos-08871
    如果 pCreateInfos 包含 VK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 的元素,并且这两个元素的 flags 都包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT,并且这两个元素的 codeType 都是 VK_SHADER_CODE_TYPE_SPIRV_EXT,并且 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT 阶段的 pCode 包含一个指定输出 patch 大小的 OpExecutionMode 指令,则它必须VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 阶段中指定的输出 patch 大小匹配。

  • VUID-vkCreateShadersEXT-pCreateInfos-09632
    如果 pCreateInfos 包含一个 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT 且未设置 VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXTVK_SHADER_STAGE_MESH_BIT_EXT,则网格着色器的入口点必须不声明带有 DrawIndex BuiltIn 修饰的变量。

有效使用(隐式)
  • VUID-vkCreateShadersEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkCreateShadersEXT-pCreateInfos-parameter
    pCreateInfos 必须是指向 createInfoCount 个有效 VkShaderCreateInfoEXT 结构的数组的有效指针。

  • VUID-vkCreateShadersEXT-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkCreateShadersEXT-pShaders-parameter
    pShaders 必须是一个指向 createInfoCountVkShaderEXT 句柄数组的有效指针

  • VUID-vkCreateShadersEXT-createInfoCount-arraylength
    createInfoCount 必须大于 0

返回码
成功
  • VK_SUCCESS

  • VK_INCOMPATIBLE_SHADER_BINARY_EXT

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_INITIALIZATION_FAILED

VkShaderCreateInfoEXT 结构定义如下

// Provided by VK_EXT_shader_object
typedef struct VkShaderCreateInfoEXT {
    VkStructureType                 sType;
    const void*                     pNext;
    VkShaderCreateFlagsEXT          flags;
    VkShaderStageFlagBits           stage;
    VkShaderStageFlags              nextStage;
    VkShaderCodeTypeEXT             codeType;
    size_t                          codeSize;
    const void*                     pCode;
    const char*                     pName;
    uint32_t                        setLayoutCount;
    const VkDescriptorSetLayout*    pSetLayouts;
    uint32_t                        pushConstantRangeCount;
    const VkPushConstantRange*      pPushConstantRanges;
    const VkSpecializationInfo*     pSpecializationInfo;
} VkShaderCreateInfoEXT;
  • sType 是一个 VkStructureType 值,用于标识此结构。

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

  • flags 是一个 VkShaderCreateFlagBitsEXT 的位掩码,描述着 shader 的附加参数。

  • stage 是一个 VkShaderStageFlagBits 值,指定单个 shader 阶段。

  • nextStage 是一个 VkShaderStageFlagBits 的位掩码,指定当 shader 绑定时,可以作为逻辑上下一个绑定阶段的零个或多个阶段。

  • codeType 是一个 VkShaderCodeTypeEXT 值,指定 pCode 指向的 shader 代码类型。

  • codeSizepCode 指向的 shader 代码的大小(以字节为单位)。

  • pCode 是一个指向用于创建 shader 的 shader 代码的指针。

  • pName 是一个指向以 null 结尾的 UTF-8 字符串的指针,该字符串指定此阶段的 shader 的入口点名称。

  • setLayoutCountpSetLayouts 指向的描述符集布局的数量。

  • pSetLayouts 是一个指向 shader 阶段使用的 VkDescriptorSetLayout 对象数组的指针。

  • pushConstantRangeCountpPushConstantRanges 指向的推送常量范围的数量。

  • pPushConstantRanges 是一个指向 shader 阶段使用的 VkPushConstantRange 结构数组的指针。

  • pSpecializationInfo 是一个指向 VkSpecializationInfo 结构的指针,如 特殊化常量 中所述,或者为 NULL

有效用法
  • VUID-VkShaderCreateInfoEXT-codeSize-08735
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,则 codeSize 必须是 4 的倍数

  • VUID-VkShaderCreateInfoEXT-pCode-08736
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,则 pCode 必须指向有效的 SPIR-V 代码,其格式和打包方式如 Khronos SPIR-V 规范 所述

  • VUID-VkShaderCreateInfoEXT-pCode-08737
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,则 pCode 必须遵守 模块中的验证规则 部分中描述的验证规则,该部分位于 SPIR-V 环境 附录中

  • VUID-VkShaderCreateInfoEXT-pCode-08738
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,则 pCode 必须为 SPIR-V 代码声明 Shader 能力

  • VUID-VkShaderCreateInfoEXT-pCode-08739
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,则 pCode 必须不声明 API 不支持的任何能力,如 能力 部分所述,该部分位于 SPIR-V 环境 附录中

  • VUID-VkShaderCreateInfoEXT-pCode-08740
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT 并且 pCode 声明了 SPIR-V 环境 附录中列出的任何能力,则 必须满足相应的要求之一

  • VUID-VkShaderCreateInfoEXT-pCode-08741
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,则 pCode 必须不声明 API 不支持的任何 SPIR-V 扩展,如 扩展 部分所述,该部分位于 SPIR-V 环境 附录中

  • VUID-VkShaderCreateInfoEXT-pCode-08742
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT 并且 pCode 声明了 SPIR-V 环境 附录中列出的任何 SPIR-V 扩展,则 必须满足相应的要求之一

  • VUID-VkShaderCreateInfoEXT-flags-08412
    如果 stage 不是 VK_SHADER_STAGE_TASK_BIT_EXTVK_SHADER_STAGE_MESH_BIT_EXTVK_SHADER_STAGE_VERTEX_BITVK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BITVK_SHADER_STAGE_GEOMETRY_BITVK_SHADER_STAGE_FRAGMENT_BIT,则 flags 必须不包含 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT

  • VUID-VkShaderCreateInfoEXT-flags-08486
    如果 stage 不是 VK_SHADER_STAGE_FRAGMENT_BIT,则 flags 必须不包含 VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT

  • VUID-VkShaderCreateInfoEXT-flags-08487
    如果 attachmentFragmentShadingRate 功能未启用,则 flags 必须不包含 VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT

  • VUID-VkShaderCreateInfoEXT-flags-08488
    如果 stage 不是 VK_SHADER_STAGE_FRAGMENT_BIT,则 flags 必须不包含 VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT

  • VUID-VkShaderCreateInfoEXT-flags-08489
    如果 fragmentDensityMap 功能未启用,则 flags 必须不包含 VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT

  • VUID-VkShaderCreateInfoEXT-flags-09404
    如果 flags 包含 VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT,则 必须启用 subgroupSizeControl 功能

  • VUID-VkShaderCreateInfoEXT-flags-09405
    如果 flags 包含 VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT,则 必须启用 computeFullSubgroups 功能

  • VUID-VkShaderCreateInfoEXT-flags-11005
    如果 flags 包含 VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT,则 必须启用 VkPhysicalDeviceDeviceGeneratedCommandsFeaturesEXT::deviceGeneratedCommands 功能

  • VUID-VkShaderCreateInfoEXT-flags-11006
    如果 flags 包含 VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT,则已标识的入口点 必须不指定 Xfb 执行模式

  • VUID-VkShaderCreateInfoEXT-flags-08992
    如果 flags 包含 VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT,则 stage 必须VK_SHADER_STAGE_MESH_BIT_EXTVK_SHADER_STAGE_TASK_BIT_EXTVK_SHADER_STAGE_COMPUTE_BIT 之一

  • VUID-VkShaderCreateInfoEXT-flags-08485
    如果 stage 不是 VK_SHADER_STAGE_COMPUTE_BIT,则 flags 必须 不包含 VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT

  • VUID-VkShaderCreateInfoEXT-flags-08414
    如果 stage 不是 VK_SHADER_STAGE_MESH_BIT_EXT,则 flags 必须 不包含 VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT

  • VUID-VkShaderCreateInfoEXT-flags-08416
    如果 flags 同时包含 VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXTVK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT,则着色器 X 维度的本地工作组大小必须maxSubgroupSize 的倍数

  • VUID-VkShaderCreateInfoEXT-flags-08417
    如果 flags 包含 VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT 但不包含 VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT,并且 pNext 链中不包含 VkShaderRequiredSubgroupSizeCreateInfoEXT 结构,则着色器 X 维度的本地工作组大小必须subgroupSize 的倍数

  • VUID-VkShaderCreateInfoEXT-stage-08418
    stage 必须 不是 VK_SHADER_STAGE_ALL_GRAPHICSVK_SHADER_STAGE_ALL

  • VUID-VkShaderCreateInfoEXT-stage-08419
    如果 tessellationShader 功能未启用,则 stage 必须 不是 VK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT

  • VUID-VkShaderCreateInfoEXT-stage-08420
    如果 geometryShader 功能未启用,则 stage 必须 不是 VK_SHADER_STAGE_GEOMETRY_BIT

  • VUID-VkShaderCreateInfoEXT-stage-08421
    如果 taskShader 功能未启用,则 stage 必须 不是 VK_SHADER_STAGE_TASK_BIT_EXT

  • VUID-VkShaderCreateInfoEXT-stage-08422
    如果 meshShader 功能未启用,则 stage 必须 不是 VK_SHADER_STAGE_MESH_BIT_EXT

  • VUID-VkShaderCreateInfoEXT-stage-08425
    stage 必须 不是 VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI

  • VUID-VkShaderCreateInfoEXT-stage-08426
    stage 必须 不是 VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI

  • VUID-VkShaderCreateInfoEXT-nextStage-08427
    如果 stageVK_SHADER_STAGE_VERTEX_BIT,则 nextStage 必须 不包含除 VK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_GEOMETRY_BITVK_SHADER_STAGE_FRAGMENT_BIT 之外的任何位

  • VUID-VkShaderCreateInfoEXT-nextStage-08428
    如果 tessellationShader 功能未启用,则 nextStage 必须 不包含 VK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT

  • VUID-VkShaderCreateInfoEXT-nextStage-08429
    如果 geometryShader 功能未启用,则 nextStage 必须 不包含 VK_SHADER_STAGE_GEOMETRY_BIT

  • VUID-VkShaderCreateInfoEXT-nextStage-08430
    如果 stageVK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,则 nextStage 必须 不包含除 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 之外的任何位

  • VUID-VkShaderCreateInfoEXT-nextStage-08431
    如果 stageVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,则 nextStage 必须 不包含除 VK_SHADER_STAGE_GEOMETRY_BITVK_SHADER_STAGE_FRAGMENT_BIT 之外的任何位

  • VUID-VkShaderCreateInfoEXT-nextStage-08433
    如果 stageVK_SHADER_STAGE_GEOMETRY_BIT,则 nextStage 必须 不包含除 VK_SHADER_STAGE_FRAGMENT_BIT 之外的任何位

  • VUID-VkShaderCreateInfoEXT-nextStage-08434
    如果 stageVK_SHADER_STAGE_FRAGMENT_BITVK_SHADER_STAGE_COMPUTE_BIT,则 nextStage 必须 为 0

  • VUID-VkShaderCreateInfoEXT-nextStage-08435
    如果 stageVK_SHADER_STAGE_TASK_BIT_EXT,则 nextStage 必须 不包含除 VK_SHADER_STAGE_MESH_BIT_EXT 之外的任何位

  • VUID-VkShaderCreateInfoEXT-nextStage-08436
    如果 stageVK_SHADER_STAGE_MESH_BIT_EXT,则 nextStage 必须 不包含除 VK_SHADER_STAGE_FRAGMENT_BIT 之外的任何位

  • VUID-VkShaderCreateInfoEXT-pName-08440
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,则 pName 必须pCodeOpEntryPoint 的名称,其执行模型与 stage 相匹配

  • VUID-VkShaderCreateInfoEXT-pCode-08492
    如果 codeTypeVK_SHADER_CODE_TYPE_BINARY_EXT,则 pCode 必须16 字节对齐

  • VUID-VkShaderCreateInfoEXT-pCode-08493
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,则 pCode 必须4 字节对齐

  • VUID-VkShaderCreateInfoEXT-pCode-08448
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且标识的入口点在其接口中包含任何使用 ClipDistance BuiltIn 修饰符声明的变量,则该变量的数组大小必须不大于 VkPhysicalDeviceLimits::maxClipDistances

  • VUID-VkShaderCreateInfoEXT-pCode-08449
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且标识的入口点在其接口中包含任何使用 CullDistance BuiltIn 修饰符声明的变量,则该变量的数组大小必须不大于 VkPhysicalDeviceLimits::maxCullDistances

  • VUID-VkShaderCreateInfoEXT-pCode-08450
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且已识别的入口点在其接口中包含使用 ClipDistance BuiltIn 修饰符声明的变量,以及在其接口中包含使用 CullDistance BuiltIn 修饰符声明的变量,则这些变量的数组大小之和必须不超过 VkPhysicalDeviceLimits::maxCombinedClipAndCullDistances

  • VUID-VkShaderCreateInfoEXT-pCode-08451
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且已识别的入口点在其接口中包含任何使用 SampleMask BuiltIn 修饰符声明的变量,则该变量的数组大小必须不大于 VkPhysicalDeviceLimits::maxSampleMaskWords

  • VUID-VkShaderCreateInfoEXT-pCode-08453
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stageVK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,并且已识别的入口点具有一个 OpExecutionMode 指令,该指令使用 OutputVertices 指定了面片大小,则该面片大小必须大于 0 且小于或等于 VkPhysicalDeviceLimits::maxTessellationPatchSize

  • VUID-VkShaderCreateInfoEXT-pCode-08454
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stageVK_SHADER_STAGE_GEOMETRY_BIT,则已识别的入口点必须具有一个 OpExecutionMode 指令,该指令指定的最大输出顶点数大于 0 且小于或等于 VkPhysicalDeviceLimits::maxGeometryOutputVertices

  • VUID-VkShaderCreateInfoEXT-pCode-08455
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stageVK_SHADER_STAGE_GEOMETRY_BIT,则已识别的入口点必须具有一个 OpExecutionMode 指令,该指令指定一个大于 0 且小于或等于 VkPhysicalDeviceLimits::maxGeometryShaderInvocations 的调用计数。

  • VUID-VkShaderCreateInfoEXT-pCode-08456
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stage 是一个光栅化前着色器阶段,并且已识别的入口点为任何图元写入 Layer,则它必须为给定图元的所有顶点写入相同的 Layer 值。

  • VUID-VkShaderCreateInfoEXT-pCode-08457
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stage 是一个光栅化前着色器阶段,并且已识别的入口点为任何图元写入 ViewportIndex,则它必须为给定图元的所有顶点写入相同的 ViewportIndex 值。

  • VUID-VkShaderCreateInfoEXT-pCode-08459
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stageVK_SHADER_STAGE_FRAGMENT_BIT,并且已识别的入口点在任何执行路径中写入 FragDepth,则所有不专属于辅助调用的执行路径必须丢弃片段,或写入或初始化 FragDepth 的值。

  • VUID-VkShaderCreateInfoEXT-pCode-08460
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,则 pCode 中的着色器代码在应用 pSpecializationInfo 中提供的任何专业化,然后将所有专业化常量转换为固定常量之后,必须Khronos SPIR-V 规范中所述有效。

  • VUID-VkShaderCreateInfoEXT-codeType-08872
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stageVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,则 pCode 必须包含一个指定细分类型的 OpExecutionMode 指令。

  • VUID-VkShaderCreateInfoEXT-codeType-08873
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stageVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,则 pCode 必须包含一个指定由细分器生成的三角形方向的 OpExecutionMode 指令。

  • VUID-VkShaderCreateInfoEXT-codeType-08874
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stageVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,则 pCode 必须包含一个指定细分图元边缘上的分段间距的 OpExecutionMode 指令。

  • VUID-VkShaderCreateInfoEXT-codeType-08875
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且 stageVK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,则 pCode 必须包含一个指定输出面片大小的 OpExecutionMode 指令。

  • VUID-VkShaderCreateInfoEXT-pPushConstantRanges-10063
    pPushConstantRanges 的任何两个元素在其 stageFlags必须不包含相同的阶段。

  • VUID-VkShaderCreateInfoEXT-codeType-10064
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且如果着色器中声明了推送常量块,则 pPushConstantRanges::stageFlags 的一个元素必须stage 匹配。

  • VUID-VkShaderCreateInfoEXT-codeType-10065
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且如果着色器中声明了推送常量块,则该块必须包含在与该阶段匹配的 pPushConstantRanges 元素内。

  • VUID-VkShaderCreateInfoEXT-codeType-10383
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且着色器中声明了资源变量,则 pSetLayouts 中的相应描述符集必须与着色器阶段匹配。

  • VUID-VkShaderCreateInfoEXT-codeType-10384
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且着色器中声明了资源变量,并且描述符类型不是 VK_DESCRIPTOR_TYPE_MUTABLE_EXT,则 pSetLayouts 中的相应描述符集必须与描述符类型匹配。

  • VUID-VkShaderCreateInfoEXT-codeType-10385
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且着色器中将资源变量声明为数组,则 pSetLayouts 中的相应描述符集必须与描述符计数匹配。

  • VUID-VkShaderCreateInfoEXT-codeType-10386
    如果 codeTypeVK_SHADER_CODE_TYPE_SPIRV_EXT,并且着色器中将资源变量声明为描述符数组,则该变量的描述符类型必须不是 VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK

有效使用(隐式)
  • VUID-VkShaderCreateInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT

  • VUID-VkShaderCreateInfoEXT-pNext-pNext
    pNext 链中任何结构(包括此结构)的每个 pNext 成员必须NULL 或指向 VkPipelineShaderStageRequiredSubgroupSizeCreateInfoVkValidationFeaturesEXT 的有效实例的指针。

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

  • VUID-VkShaderCreateInfoEXT-flags-parameter
    flags 必须VkShaderCreateFlagBitsEXT 值的有效组合。

  • VUID-VkShaderCreateInfoEXT-stage-parameter
    stage 必须是有效的 VkShaderStageFlagBits 值。

  • VUID-VkShaderCreateInfoEXT-nextStage-parameter
    nextStage 必须VkShaderStageFlagBits 值的有效组合。

  • VUID-VkShaderCreateInfoEXT-codeType-parameter
    codeType 必须是有效的 VkShaderCodeTypeEXT 值。

  • VUID-VkShaderCreateInfoEXT-pCode-parameter
    pCode 必须是指向 codeSize 字节数组的有效指针。

  • VUID-VkShaderCreateInfoEXT-pName-parameter
    如果 pName 不是 NULL,则 pName 必须是以 null 结尾的 UTF-8 字符串。

  • VUID-VkShaderCreateInfoEXT-pSetLayouts-parameter
    如果 setLayoutCount 不为 0,并且 pSetLayouts 不为 NULL,则 pSetLayouts 必须是指向 setLayoutCount 个有效 VkDescriptorSetLayout 句柄数组的有效指针。

  • VUID-VkShaderCreateInfoEXT-pPushConstantRanges-parameter
    如果 pushConstantRangeCount 不为 0,并且 pPushConstantRanges 不为 NULL,则 pPushConstantRanges 必须是指向 pushConstantRangeCount 个有效 VkPushConstantRange 结构体数组的有效指针。

  • VUID-VkShaderCreateInfoEXT-pSpecializationInfo-parameter
    如果 pSpecializationInfo 不为 NULL,则 pSpecializationInfo 必须是指向有效 VkSpecializationInfo 结构体的有效指针。

  • VUID-VkShaderCreateInfoEXT-codeSize-arraylength
    codeSize 必须大于 0

// Provided by VK_EXT_shader_object
typedef VkFlags VkShaderCreateFlagsEXT;

VkShaderCreateFlagsEXT 是一个位掩码类型,用于设置零个或多个 VkShaderCreateFlagBitsEXT 的掩码。

VkShaderCreateInfoEXTflags 成员的可能值,指定如何创建着色器对象,如下:

// Provided by VK_EXT_shader_object
typedef enum VkShaderCreateFlagBitsEXT {
    VK_SHADER_CREATE_LINK_STAGE_BIT_EXT = 0x00000001,
  // Provided by VK_EXT_shader_object with VK_EXT_subgroup_size_control or VK_VERSION_1_3
    VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT = 0x00000002,
  // Provided by VK_EXT_shader_object with VK_EXT_subgroup_size_control or VK_VERSION_1_3
    VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT = 0x00000004,
  // Provided by VK_EXT_shader_object with VK_EXT_mesh_shader or VK_NV_mesh_shader
    VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT = 0x00000008,
  // Provided by VK_EXT_shader_object with VK_KHR_device_group or VK_VERSION_1_1
    VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT = 0x00000010,
  // Provided by VK_KHR_fragment_shading_rate with VK_EXT_shader_object
    VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT = 0x00000020,
  // Provided by VK_EXT_fragment_density_map with VK_EXT_shader_object
    VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT = 0x00000040,
  // Provided by VK_EXT_device_generated_commands
    VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT = 0x00000080,
} VkShaderCreateFlagBitsEXT;
  • VK_SHADER_CREATE_LINK_STAGE_BIT_EXT 指定着色器链接到同一 vkCreateShadersEXT 调用中创建的所有其他着色器,这些着色器的 VkShaderCreateInfoEXT 结构的 flags 包括 VK_SHADER_CREATE_LINK_STAGE_BIT_EXT

  • VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT 指定 SubgroupSize 可以在任务、网格或计算着色器中变化。

  • VK_SHADER_CREATE_REQUIRE_FULL_SUBGROUPS_BIT_EXT 指定子组大小必须在任务、网格或计算着色器中所有调用都处于活动状态时启动。

  • VK_SHADER_CREATE_NO_TASK_SHADER_BIT_EXT 指定网格着色器必须仅在没有任务着色器的情况下使用。否则,网格着色器必须仅在有任务着色器的情况下使用。

  • VK_SHADER_CREATE_DISPATCH_BASE_BIT_EXT 指定计算着色器可以与具有非零基础工作组的 vkCmdDispatchBase 一起使用。

  • VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXT 指定片段着色器可以与片段着色率附件一起使用。

  • VK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT 指定片段着色器可以与片段密度图附件一起使用。

  • VK_SHADER_CREATE_INDIRECT_BINDABLE_BIT_EXT 指定着色器可以设备生成的命令 结合使用。

VK_SHADER_CREATE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_EXTVK_SHADER_CREATE_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT 的行为与 VK_PIPELINE_CREATE_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHRVK_PIPELINE_CREATE_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT 的行为略有不同,因为着色器位允许但不需要该着色器与该类型的附件一起使用。这意味着当应用程序无法预先知道该着色器是否会与附件类型一起使用,或者当它需要相同的着色器与有附件和无附件的使用兼容时,则不需要创建多个着色器。这在某些实现上可能会带来一些性能损失,因此应用程序应该仍然只设置实际需要的位。

可以使用不同类型的着色器代码创建着色器对象。 VkShaderCreateInfoEXT::codeType 的可能值如下:

// Provided by VK_EXT_shader_object
typedef enum VkShaderCodeTypeEXT {
    VK_SHADER_CODE_TYPE_BINARY_EXT = 0,
    VK_SHADER_CODE_TYPE_SPIRV_EXT = 1,
} VkShaderCodeTypeEXT;
  • VK_SHADER_CODE_TYPE_BINARY_EXT 指定特定于物理设备的不透明、实现定义的二进制格式的着色器代码。

  • VK_SHADER_CODE_TYPE_SPIRV_EXT 指定 SPIR-V 格式的着色器代码。

二进制着色器代码

可以使用以下命令从着色器对象检索二进制着色器代码:

// Provided by VK_EXT_shader_object
VkResult vkGetShaderBinaryDataEXT(
    VkDevice                                    device,
    VkShaderEXT                                 shader,
    size_t*                                     pDataSize,
    void*                                       pData);
  • device 是创建着色器对象的逻辑设备。

  • shader 是要从中检索二进制着色器代码的着色器对象。

  • pDataSize 是一个指向与二进制着色器代码大小相关的 size_t 值的指针,如下所述。

  • pData 要么是 NULL,要么是指向缓冲区的指针。

如果 pDataNULL,则着色器对象的二进制着色器代码的大小(以字节为单位)将返回到 pDataSize 中。否则,pDataSize 必须指向一个由应用程序设置为 pData 指向的缓冲区大小(以字节为单位)的变量,并且在返回时,该变量将被实际写入到 pData 的数据量覆盖。如果 pDataSize 小于二进制着色器代码的大小,则不会向 pData 写入任何内容,并且将返回 VK_INCOMPLETE 而不是 VK_SUCCESS

pDataSize 太小时,此命令的行为与 Vulkan 中一些其他 getter 类型命令的工作方式不同。因为着色器二进制数据只能在其整体中使用,所以实现返回部分数据永远不会有用。因此,除非 pDataSize 足够大以容纳所有数据,否则不会向 pData 写入任何内容。

使用 vkGetShaderBinaryDataEXT 检索的二进制着色器代码可以通过在 VkShaderCreateInfoEXTcodeType 成员中指定 VK_SHADER_CODE_TYPE_BINARY_EXT,传递给兼容的物理设备上后续对 vkCreateShadersEXT 的调用。

对于同一个 VkShaderEXT 对象,重复调用此函数返回的着色器代码保证在其生命周期内是不变的。

有效用法
  • VUID-vkGetShaderBinaryDataEXT-None-08461
    shaderObject 功能必须启用

  • VUID-vkGetShaderBinaryDataEXT-None-08499
    如果 pData 不为 NULL,则它必须对齐到 16 字节。

有效使用(隐式)
  • VUID-vkGetShaderBinaryDataEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetShaderBinaryDataEXT-shader-parameter
    shader 必须是有效的 VkShaderEXT 句柄。

  • VUID-vkGetShaderBinaryDataEXT-pDataSize-parameter
    pDataSize 必须是指向 size_t 值的有效指针。

  • VUID-vkGetShaderBinaryDataEXT-pData-parameter
    如果 pDataSize 引用的值不为 0,并且 pData 不为 NULL,则 pData 必须是指向 pDataSize 字节数组的有效指针。

  • VUID-vkGetShaderBinaryDataEXT-shader-parent
    shader 必须是由 device 创建、分配或检索的。

返回码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

二进制着色器兼容性

二进制着色器兼容性是指从调用 vkGetShaderBinaryDataEXT 返回的二进制着色器代码可以传递给后续对 vkCreateShadersEXT 的调用,可能在不同的逻辑和/或物理设备上,并且这将导致成功创建功能上等同于最初查询该代码的着色器对象的着色器对象。

vkGetShaderBinaryDataEXT 查询的二进制着色器代码不能保证在所有设备上都兼容,但实现必须提供一些兼容性保证。应用程序可以使用以下两种机制之一(或两者兼有)来确定二进制着色器兼容性。

着色器二进制文件的保证兼容性通过从物理设备查询的 VkPhysicalDeviceShaderObjectPropertiesEXT 结构的 shaderBinaryUUIDshaderBinaryVersion 成员的组合来表达。从具有特定 shaderBinaryUUID 的物理设备检索的二进制着色器保证与所有报告相同 shaderBinaryUUID 和相同或更高 shaderBinaryVersion 的其他物理设备兼容。

每当实现的新的版本包含任何影响 vkGetShaderBinaryDataEXT 输出的更改时,如果从旧版本检索的二进制着色器代码与新实现保持兼容,则实现该递增 shaderBinaryVersion;否则,如果向后兼容性被破坏,则将 shaderBinaryUUID 替换为新值。相对于调用 vkCreateShadersEXT 的设备,从具有匹配的 shaderBinaryUUID 和较低 shaderBinaryVersion 的设备查询的二进制着色器代码可能对于新设备而言不是最优的,这不会改变着色器功能,但它仍然保证可用于成功创建着色器对象。

鼓励实现尽可能在其硬件自然允许的最大程度上在设备和驱动程序版本之间共享 shaderBinaryUUID,并且强烈不建议在相同硬件上更改 shaderBinaryUUID,除非绝对必要。

除了上述描述的着色器兼容性保证之外,应用程序使用在具有不同或未知 shaderBinaryUUID 和/或更高 shaderBinaryVersion 的设备上创建的二进制着色器代码调用 vkCreateShadersEXT 是有效的。在这种情况下,实现可以使用其选择的任何未指定的方法来确定提供的二进制着色器代码是否可用。如果是,则 vkCreateShadersEXT 必须返回 VK_SUCCESS,并且保证创建的着色器对象有效。否则,在没有错误的情况下,vkCreateShadersEXT 必须返回 VK_INCOMPATIBLE_SHADER_BINARY_EXT,以表明提供的二进制着色器代码与该设备不兼容。

绑定着色器对象

一旦创建了着色器对象,就可以使用以下命令将其绑定到命令缓冲区:

// Provided by VK_EXT_shader_object
void vkCmdBindShadersEXT(
    VkCommandBuffer                             commandBuffer,
    uint32_t                                    stageCount,
    const VkShaderStageFlagBits*                pStages,
    const VkShaderEXT*                          pShaders);
  • commandBuffer 是着色器对象将绑定到的命令缓冲区。

  • stageCountpStagespShaders 数组的长度。

  • pStages 是指向 VkShaderStageFlagBits 值数组的指针,该数组指定每个数组索引一个受 pShaders 数组中相应值影响的阶段。

  • pShaders 是指向 VkShaderEXT 句柄和/或 VK_NULL_HANDLE 值数组的指针,该数组描述要在 pStages 中每个阶段执行的着色器绑定操作。

当绑定链接的着色器时,应用程序可以通过一次或多次调用 vkCmdBindShadersEXT 以任意组合绑定它们(即,链接在一起创建的着色器不需要在同一个 vkCmdBindShadersEXT 调用中绑定)。

可以通过将其在 pShaders 中的值设置为 VK_NULL_HANDLE 来解除绑定到特定阶段的任何着色器对象。如果 pShadersNULL,则 vkCmdBindShadersEXT 的行为就像 pShaders 是一个包含 stageCountVK_NULL_HANDLE 值的数组(即,绑定到 pStages 中指定阶段的任何着色器都将被解除绑定)。

有效用法
  • VUID-vkCmdBindShadersEXT-None-08462
    shaderObject 功能必须启用

  • VUID-vkCmdBindShadersEXT-pStages-08463
    pStages 的每个元素必须是唯一的。

  • VUID-vkCmdBindShadersEXT-pStages-08464
    pStages 不能包含 VK_SHADER_STAGE_ALL_GRAPHICSVK_SHADER_STAGE_ALL

  • VUID-vkCmdBindShadersEXT-pStages-08465
    pStages 不能包含 VK_SHADER_STAGE_RAYGEN_BIT_KHRVK_SHADER_STAGE_ANY_HIT_BIT_KHRVK_SHADER_STAGE_CLOSEST_HIT_BIT_KHRVK_SHADER_STAGE_MISS_BIT_KHRVK_SHADER_STAGE_INTERSECTION_BIT_KHRVK_SHADER_STAGE_CALLABLE_BIT_KHR

  • VUID-vkCmdBindShadersEXT-pStages-08467
    pStages 不能包含 VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI

  • VUID-vkCmdBindShadersEXT-pStages-08468
    pStages 不能包含 VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI

  • VUID-vkCmdBindShadersEXT-pShaders-08469
    对于 pStages 的每个元素,如果 pShaders 不为 NULL,并且 pShaders 数组中具有相同索引的元素不为 VK_NULL_HANDLE,则它必须是用等于 pStages 的相应元素的 stage 创建的。

  • VUID-vkCmdBindShadersEXT-pShaders-08470
    如果 pStages 同时包含 VK_SHADER_STAGE_TASK_BIT_EXTVK_SHADER_STAGE_VERTEX_BIT,并且 pShaders 不为 NULL,并且 pShaders 中与 pStagesVK_SHADER_STAGE_TASK_BIT_EXT 相同索引的元素不为 VK_NULL_HANDLE,则 pShaders 中与 pStagesVK_SHADER_STAGE_VERTEX_BIT 相同索引的元素必须VK_NULL_HANDLE

  • VUID-vkCmdBindShadersEXT-pShaders-08471
    如果 pStages 同时包含 VK_SHADER_STAGE_MESH_BIT_EXTVK_SHADER_STAGE_VERTEX_BIT,并且 pShaders 不为 NULL,并且 pShaders 中与 pStagesVK_SHADER_STAGE_MESH_BIT_EXT 相同索引的元素不为 VK_NULL_HANDLE,则 pShaders 中与 pStagesVK_SHADER_STAGE_VERTEX_BIT 相同索引的元素必须VK_NULL_HANDLE

  • VUID-vkCmdBindShadersEXT-pShaders-08476
    如果 pStages 包含 VK_SHADER_STAGE_COMPUTE_BIT,则分配 commandBufferVkCommandPool 必须支持计算操作。

  • VUID-vkCmdBindShadersEXT-pShaders-08477
    如果 pStages 包含 VK_SHADER_STAGE_VERTEX_BITVK_SHADER_STAGE_TESSELLATION_CONTROL_BITVK_SHADER_STAGE_TESSELLATION_EVALUATION_BITVK_SHADER_STAGE_GEOMETRY_BITVK_SHADER_STAGE_FRAGMENT_BIT,则分配 commandBufferVkCommandPool 必须支持图形操作。

  • VUID-vkCmdBindShadersEXT-pShaders-08478
    如果 pStages 包含 VK_SHADER_STAGE_MESH_BIT_EXTVK_SHADER_STAGE_TASK_BIT_EXT,则分配 commandBufferVkCommandPool 必须支持图形操作。

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

  • VUID-vkCmdBindShadersEXT-pStages-parameter
    pStages 必须是一个指向 stageCount 个有效 VkShaderStageFlagBits 值数组的有效指针。

  • VUID-vkCmdBindShadersEXT-pShaders-parameter
    如果 pShaders 不为 NULL,则 pShaders 必须是一个指向 stageCount 个有效或 VK_NULL_HANDLE VkShaderEXT 句柄的数组的有效指针。

  • VUID-vkCmdBindShadersEXT-commandBuffer-recording
    commandBuffer 必须处于录制状态

  • VUID-vkCmdBindShadersEXT-commandBuffer-cmdpool
    分配 commandBufferVkCommandPool 必须支持图形或计算操作。

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

  • VUID-vkCmdBindShadersEXT-stageCount-arraylength
    stageCount 必须大于 0

  • VUID-vkCmdBindShadersEXT-commonparent
    commandBuffer 以及 pShaders 中有效且非忽略参数的句柄元素,必须是从同一个 VkDevice 创建、分配或检索的。

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

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

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

主要
次要

两者

外部

图形
计算

状态

设置状态

每当使用着色器对象发出绘制命令时,在绘制之前,必须调用适当的 动态状态 设置命令,以在命令缓冲区中设置相关状态。

如果着色器绑定到 VK_SHADER_STAGE_VERTEX_BIT 阶段,则在绘制之前,必须在命令缓冲区中调用以下命令:

如果着色器绑定到 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT 阶段,则在绘制之前,必须在命令缓冲区中调用以下命令:

如果着色器绑定到 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT 阶段,则在绘制之前,必须在命令缓冲区中调用以下命令:

如果 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令:

如果着色器绑定到 VK_SHADER_STAGE_FRAGMENT_BIT 阶段,并且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令:

如果启用了 pipelineFragmentShadingRate 功能,并且着色器绑定到 VK_SHADER_STAGE_FRAGMENT_BIT 阶段,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 geometryStreams 功能,并且着色器绑定到 VK_SHADER_STAGE_GEOMETRY_BIT 阶段,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 VK_EXT_discard_rectangles 扩展,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 VK_EXT_conservative_rasterization 扩展,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 depthClipEnable 功能,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 VK_EXT_sample_locations 扩展,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 VK_EXT_provoking_vertex 扩展,且 rasterizerDiscardEnableVK_FALSE,并且着色器绑定到 VK_SHADER_STAGE_VERTEX_BIT 阶段,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了任何 <features-stippledRectangularLines, stippledRectangularLines>>、<features-stippledBresenhamLines, stippledBresenhamLines>> 或 <features-stippledSmoothLines, stippledSmoothLines>> 功能,且 rasterizerDiscardEnableVK_FALSE,并且如果 polygonModeVK_POLYGON_MODE_LINE,或者着色器绑定到 VK_SHADER_STAGE_VERTEX_BIT 阶段并且 primitiveTopology 是线拓扑,或者输出线图元的着色器绑定到 VK_SHADER_STAGE_TESSELLATION_EVALUATION_BITVK_SHADER_STAGE_GEOMETRY_BIT 阶段,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 depthClipControl 功能,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 colorWriteEnable 功能,并且着色器绑定到 VK_SHADER_STAGE_FRAGMENT_BIT 阶段,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 attachmentFeedbackLoopDynamicState 功能,并且着色器绑定到 VK_SHADER_STAGE_FRAGMENT_BIT 阶段,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 VK_NV_clip_space_w_scaling 扩展,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 depthClampdepthClampControl 功能,且 depthClampEnableVK_TRUE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 VK_NV_viewport_swizzle 扩展,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 VK_NV_fragment_coverage_to_color 扩展,并且着色器绑定到 VK_SHADER_STAGE_FRAGMENT_BIT 阶段,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 VK_NV_framebuffer_mixed_samples 扩展,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 coverageReductionMode 功能,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,必须在命令缓冲区中调用以下命令

如果启用了 representativeFragmentTest 功能,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,命令缓冲区中必须已调用以下命令

如果启用了 shadingRateImage 功能,且 rasterizerDiscardEnableVK_FALSE,则在绘制之前,命令缓冲区中必须已调用以下命令

如果启用了 exclusiveScissor 功能,则在绘制之前,命令缓冲区中必须已调用以下命令

状态可以在绑定着色器对象之前或之后的任何时间设置,但所有必需的状态必须在发出绘制命令之前设置。

如果启用了 commandBufferInheritance 功能,则图形和计算状态将从队列中先前执行的命令缓冲区继承。 以这种方式继承的任何有效状态都不需要在当前命令缓冲区中再次设置。

与管线的交互

调用 vkCmdBindShadersEXT 会干扰 pStages 中每个阶段对应的管线绑定点,这意味着先前绑定到这些管线绑定点的任何管线都不再绑定。

如果 VK_PIPELINE_BIND_POINT_GRAPHICS 受到干扰(即,如果 pStages 包含任何图形阶段),则先前绑定的管线未指定为动态的任何图形管线状态将变为未定义,并且必须在使用着色器对象发出绘制命令之前在命令缓冲区中设置。

调用 vkCmdBindPipeline 同样会干扰与 pipelineBindPoint 对应的着色器阶段,这意味着先前绑定到任何这些阶段的任何着色器都不再绑定,即使在创建管线时,某些阶段没有着色器。

着色器对象销毁

要销毁着色器对象,请调用

// Provided by VK_EXT_shader_object
void vkDestroyShaderEXT(
    VkDevice                                    device,
    VkShaderEXT                                 shader,
    const VkAllocationCallbacks*                pAllocator);
  • device 是销毁着色器对象的逻辑设备。

  • shader 是要销毁的着色器对象的句柄。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

销毁记录或可执行状态中一个或多个命令缓冲区使用的着色器对象会导致这些命令缓冲区进入无效状态

有效用法
  • VUID-vkDestroyShaderEXT-None-08481
    shaderObject 功能必须启用

  • VUID-vkDestroyShaderEXT-shader-08482
    所有引用 shader 的已提交命令必须已完成执行

  • VUID-vkDestroyShaderEXT-pAllocator-08483
    如果在创建 shader 时提供了 VkAllocationCallbacks,则此处必须提供兼容的回调集

  • VUID-vkDestroyShaderEXT-pAllocator-08484
    如果在创建 shader 时未提供 VkAllocationCallbacks,则 pAllocator必须NULL

有效使用(隐式)
  • VUID-vkDestroyShaderEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkDestroyShaderEXT-shader-parameter
    如果 shader 不是 VK_NULL_HANDLE,则 shader必须是有效的 VkShaderEXT 句柄

  • VUID-vkDestroyShaderEXT-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkDestroyShaderEXT-shader-parent
    如果 shader 是有效的句柄,则它必须已从 device 创建、分配或检索

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

着色器模块

着色器模块包含着色器代码和一个或多个入口点。通过在管线创建过程中指定一个入口点,从着色器模块中选择着色器。管线的各个阶段可以使用来自不同模块的着色器。定义着色器模块的着色器代码必须采用 SPIR-V 格式,如适用于 SPIR-V 的 Vulkan 环境附录中所述。

着色器模块由 VkShaderModule 句柄表示

// Provided by VK_VERSION_1_0
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule)

要创建着色器模块,请调用

// Provided by VK_VERSION_1_0
VkResult vkCreateShaderModule(
    VkDevice                                    device,
    const VkShaderModuleCreateInfo*             pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkShaderModule*                             pShaderModule);
  • device 是创建着色器模块的逻辑设备。

  • pCreateInfo 是指向 VkShaderModuleCreateInfo 结构的指针。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

  • pShaderModule 是指向 VkShaderModule 句柄的指针,其中返回生成的着色器模块对象。

创建着色器模块后,其中包含的任何入口点可以在管线着色器阶段中使用,如计算管线图形管线中所述。

如果启用了 maintenance5 功能,则可以完全省略着色器模块的创建。相反,应用程序应直接在通过将其链接到VkPipelineShaderStageCreateInfo的管线创建中提供VkShaderModuleCreateInfo结构。这样可以避免创建和管理额外对象的开销。

有效用法
有效使用(隐式)
  • VUID-vkCreateShaderModule-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkCreateShaderModule-pCreateInfo-parameter
    pCreateInfo必须是指向有效 VkShaderModuleCreateInfo 结构的有效指针

  • VUID-vkCreateShaderModule-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkCreateShaderModule-pShaderModule-parameter
    pShaderModule必须是指向 VkShaderModule 句柄的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

  • VK_ERROR_INVALID_SHADER_NV

VkShaderModuleCreateInfo 结构定义为

// Provided by VK_VERSION_1_0
typedef struct VkShaderModuleCreateInfo {
    VkStructureType              sType;
    const void*                  pNext;
    VkShaderModuleCreateFlags    flags;
    size_t                       codeSize;
    const uint32_t*              pCode;
} VkShaderModuleCreateInfo;
  • sType 是一个 VkStructureType 值,用于标识此结构。

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

  • flags 保留供将来使用。

  • codeSizepCode 指向的代码的大小,以字节为单位。

  • pCode 是指向用于创建着色器模块的代码的指针。代码的类型和格式由 pCode 指向的内存内容确定。

有效用法
  • VUID-VkShaderModuleCreateInfo-codeSize-08735
    如果 pCode 是指向 SPIR-V 代码的指针,则 codeSize 必须是 4 的倍数

  • VUID-VkShaderModuleCreateInfo-pCode-08736
    如果 pCode 是指向 SPIR-V 代码的指针,则 pCode 必须指向有效的 SPIR-V 代码,其格式和打包方式如 Khronos SPIR-V 规范所述

  • VUID-VkShaderModuleCreateInfo-pCode-08737
    如果 pCode 是指向 SPIR-V 代码的指针,则 pCode 必须遵守 模块中的验证规则 部分的描述,该部分在 SPIR-V 环境 附录中

  • VUID-VkShaderModuleCreateInfo-pCode-08738
    如果 pCode 是指向 SPIR-V 代码的指针,则 pCode 必须为 SPIR-V 代码声明 Shader 功能

  • VUID-VkShaderModuleCreateInfo-pCode-08739
    如果 pCode 是指向 SPIR-V 代码的指针,则 pCode 必须不声明任何 API 不支持的功能,如 功能 部分的描述,该部分在 SPIR-V 环境 附录中

  • VUID-VkShaderModuleCreateInfo-pCode-08740
    如果 pCode 是指向 SPIR-V 代码的指针,并且 pCode 声明了 SPIR-V 环境 附录中列出的任何功能,则必须满足相应的要求之一

  • VUID-VkShaderModuleCreateInfo-pCode-08741
    如果 pCode 是指向 SPIR-V 代码的指针,则 pCode 必须不声明任何 API 不支持的 SPIR-V 扩展,如 扩展 部分的描述,该部分在 SPIR-V 环境 附录中

  • VUID-VkShaderModuleCreateInfo-pCode-08742
    如果 pCode 是指向 SPIR-V 代码的指针,并且 pCode 声明了 SPIR-V 环境 附录中列出的任何 SPIR-V 扩展,则必须满足相应的要求之一

  • VUID-VkShaderModuleCreateInfo-pCode-07912
    如果未启用 VK_NV_glsl_shader 扩展,则 pCode 必须是指向 SPIR-V 代码的指针

  • VUID-VkShaderModuleCreateInfo-pCode-01379
    如果 pCode 是指向 GLSL 代码的指针,则它必须是根据 GL_KHR_vulkan_glsl GLSL 扩展规范编写的有效 GLSL 代码

  • VUID-VkShaderModuleCreateInfo-codeSize-01085
    codeSize 必须大于 0

有效使用(隐式)
  • VUID-VkShaderModuleCreateInfo-sType-sType
    sType 必须VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO

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

  • VUID-VkShaderModuleCreateInfo-pCode-parameter
    pCode必须是指向 uint32_t 值的数组的有效指针。

// Provided by VK_VERSION_1_0
typedef VkFlags VkShaderModuleCreateFlags;

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

要使用 VkValidationCacheEXT 来缓存着色器验证结果,请将 VkShaderModuleValidationCacheCreateInfoEXT 结构添加到 VkShaderModuleCreateInfo 结构的 pNext 链中,指定要使用的缓存对象。

VkShaderModuleValidationCacheCreateInfoEXT 结构的定义如下

// Provided by VK_EXT_validation_cache
typedef struct VkShaderModuleValidationCacheCreateInfoEXT {
    VkStructureType         sType;
    const void*             pNext;
    VkValidationCacheEXT    validationCache;
} VkShaderModuleValidationCacheCreateInfoEXT;
  • sType 是一个 VkStructureType 值,用于标识此结构。

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

  • validationCache 是验证缓存对象,先前验证尝试的结果将从该对象写入,并且此 VkShaderModule 的新验证结果将写入该对象(如果尚未存在)。

有效使用(隐式)
  • VUID-VkShaderModuleValidationCacheCreateInfoEXT-sType-sType
    sType必须VK_STRUCTURE_TYPE_SHADER_MODULE_VALIDATION_CACHE_CREATE_INFO_EXT

  • VUID-VkShaderModuleValidationCacheCreateInfoEXT-validationCache-parameter
    validationCache必须是有效的 VkValidationCacheEXT 句柄

要销毁着色器模块,请调用

// Provided by VK_VERSION_1_0
void vkDestroyShaderModule(
    VkDevice                                    device,
    VkShaderModule                              shaderModule,
    const VkAllocationCallbacks*                pAllocator);
  • device 是销毁着色器模块的逻辑设备。

  • shaderModule 是要销毁的着色器模块的句柄。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

着色器模块可以在仍在使用其着色器创建的管道时销毁。

有效用法
  • VUID-vkDestroyShaderModule-shaderModule-01092
    如果在创建 shaderModule 时提供了 VkAllocationCallbacks,则此处必须提供一组兼容的回调

  • VUID-vkDestroyShaderModule-shaderModule-01093
    如果在创建 shaderModule 时未提供 VkAllocationCallbacks,则 pAllocator必须NULL

有效使用(隐式)
  • VUID-vkDestroyShaderModule-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkDestroyShaderModule-shaderModule-parameter
    如果 shaderModule 不是 VK_NULL_HANDLE,则 shaderModule必须是有效的 VkShaderModule 句柄

  • VUID-vkDestroyShaderModule-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkDestroyShaderModule-shaderModule-parent
    如果 shaderModule 是有效句柄,则它必须已从 device 创建、分配或检索

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

着色器模块标识符

着色器模块具有与其关联的唯一标识符。要查询实现提供的标识符,请调用

// Provided by VK_EXT_shader_module_identifier
void vkGetShaderModuleIdentifierEXT(
    VkDevice                                    device,
    VkShaderModule                              shaderModule,
    VkShaderModuleIdentifierEXT*                pIdentifier);
  • device 是创建着色器模块的逻辑设备。

  • shaderModule 是着色器模块的句柄。

  • pIdentifier 是指向返回的 VkShaderModuleIdentifierEXT 的指针。

实现返回的标识符必须仅取决于 shaderIdentifierAlgorithmUUID 以及创建 shaderModuleVkShaderModuleCreateInfo 中提供的信息。如果差异不影响管道编译,则实现可以为两个不同的 VkShaderModuleCreateInfo 结构返回相同的标识符。仅当查询标识符的设备的 shaderModuleIdentifierAlgorithmUUID 与使用标识符的设备相同时,标识符在不同的 VkDevice 对象上才有意义。

有效用法
有效使用(隐式)
  • VUID-vkGetShaderModuleIdentifierEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetShaderModuleIdentifierEXT-shaderModule-parameter
    shaderModule 必须 是一个有效的 VkShaderModule 句柄

  • VUID-vkGetShaderModuleIdentifierEXT-pIdentifier-parameter
    pIdentifier 必须 是一个指向 VkShaderModuleIdentifierEXT 结构的有效指针

  • VUID-vkGetShaderModuleIdentifierEXT-shaderModule-parent
    shaderModule 必须 是从 device 创建、分配或检索的

VkShaderModuleCreateInfo 结构具有与其关联的唯一标识符。要查询实现提供的标识符,请调用

// Provided by VK_EXT_shader_module_identifier
void vkGetShaderModuleCreateInfoIdentifierEXT(
    VkDevice                                    device,
    const VkShaderModuleCreateInfo*             pCreateInfo,
    VkShaderModuleIdentifierEXT*                pIdentifier);

实现返回的标识符必须仅依赖于 shaderIdentifierAlgorithmUUIDVkShaderModuleCreateInfo 中提供的信息。如果两个不同的 VkShaderModuleCreateInfo 结构之间的差异不影响管线编译,则实现可以为它们返回相同的标识符。只有当查询标识符的设备与使用该标识符的设备具有相同的 shaderModuleIdentifierAlgorithmUUID 时,标识符在不同的 VkDevice 对象上才有意义。

给定等效的 VkShaderModuleCreateInfo 定义和任何链接的 pNext 结构,vkGetShaderModuleCreateInfoIdentifierEXT 返回的标识符必须等于 vkGetShaderModuleIdentifierEXT 返回的标识符。

有效用法
  • VUID-vkGetShaderModuleCreateInfoIdentifierEXT-shaderModuleIdentifier-06885
    shaderModuleIdentifier 功能必须启用

有效使用(隐式)
  • VUID-vkGetShaderModuleCreateInfoIdentifierEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetShaderModuleCreateInfoIdentifierEXT-pCreateInfo-parameter
    pCreateInfo必须是指向有效 VkShaderModuleCreateInfo 结构的有效指针

  • VUID-vkGetShaderModuleCreateInfoIdentifierEXT-pIdentifier-parameter
    pIdentifier 必须 是一个指向 VkShaderModuleIdentifierEXT 结构的有效指针

VkShaderModuleIdentifierEXT 表示由实现返回的着色器模块标识符。

// Provided by VK_EXT_shader_module_identifier
typedef struct VkShaderModuleIdentifierEXT {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           identifierSize;
    uint8_t            identifier[VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT];
} VkShaderModuleIdentifierEXT;
  • sType 是一个 VkStructureType 值,用于标识此结构。

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

  • identifierSizeidentifier 中返回的有效数据的大小(以字节为单位)。

  • identifier 是一个指定标识符的不透明数据缓冲区。

任何返回的值超出前 identifierSize 个字节都是未定义的。实现必须返回大于 0 且小于等于 VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXTidentifierSize

如果 identifierSize 相等,并且 identifier 的前 identifierSize 个字节比较相等,则认为两个标识符相等。

对于不同的模块,实现可以返回不同的 identifierSize。实现应该确保 identifierSize 足够大,可以唯一地定义一个着色器模块。

有效使用(隐式)
  • VUID-VkShaderModuleIdentifierEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_SHADER_MODULE_IDENTIFIER_EXT

  • VUID-VkShaderModuleIdentifierEXT-pNext-pNext
    pNext 必须NULL

VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT 是着色器模块标识符的长度(以字节为单位),如 VkShaderModuleIdentifierEXT::identifierSize 中返回的那样。

#define VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT 32U

绑定着色器

在着色器可以使用之前,必须先将其绑定到命令缓冲区。

调用 vkCmdBindPipeline 会绑定与 VkPipelineBindPoint 对应的所有阶段。调用 vkCmdBindShadersEXT 会绑定 pStages 中的所有阶段

下表描述了着色器阶段和管线绑定点之间的关系

着色器阶段 管线绑定点 行为控制
  • VK_SHADER_STAGE_VERTEX_BIT

  • VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT

  • VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT

  • VK_SHADER_STAGE_GEOMETRY_BIT

  • VK_SHADER_STAGE_FRAGMENT_BIT

  • VK_SHADER_STAGE_TASK_BIT_EXT

  • VK_SHADER_STAGE_MESH_BIT_EXT

VK_PIPELINE_BIND_POINT_GRAPHICS

所有绘图命令

  • VK_SHADER_STAGE_COMPUTE_BIT

VK_PIPELINE_BIND_POINT_COMPUTE

所有调度命令

  • VK_SHADER_STAGE_ANY_HIT_BIT_KHR

  • VK_SHADER_STAGE_CALLABLE_BIT_KHR

  • VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR

  • VK_SHADER_STAGE_INTERSECTION_BIT_KHR

  • VK_SHADER_STAGE_MISS_BIT_KHR

  • VK_SHADER_STAGE_RAYGEN_BIT_KHR

VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR

vkCmdTraceRaysNV vkCmdTraceRaysKHRvkCmdTraceRaysIndirectKHR

  • VK_SHADER_STAGE_SUBPASS_SHADING_BIT_HUAWEI

  • VK_SHADER_STAGE_CLUSTER_CULLING_BIT_HUAWEI

VK_PIPELINE_BIND_POINT_SUBPASS_SHADING_HUAWEI

vkCmdSubpassShadingHUAWEI

  • VK_SHADER_STAGE_COMPUTE_BIT

VK_PIPELINE_BIND_POINT_EXECUTION_GRAPH_AMDX

所有执行图命令

着色器执行

在管线的每个阶段,着色器的多个调用可能同时执行。此外,由不同命令产生的单个着色器的调用可能同时执行。相同着色器类型的调用的相对执行顺序是未定义的。着色器调用可能以与它们所源自的图元被应用程序绘制或调度的顺序不同的顺序完成。但是,片段着色器输出以光栅化顺序写入附件。

不同着色器类型的调用的相对执行顺序在很大程度上是未定义的。但是,当调用其输入是从先前管线阶段生成的着色器时,保证先前阶段的着色器调用已执行足够长的时间,以为所有必需的输入生成输入值。

着色器终止

终止的着色器调用已完成指令的执行。

在入口点执行 OpReturn,或在任何函数中执行 OpTerminateInvocation 将终止调用。当在任何函数中执行 OpKill 时,实现也可能终止着色器调用;否则它会变成一个辅助调用

除了上述条件外,当同一导数组中的所有非辅助调用终止或变成辅助调用时,辅助调用可能被终止。

当该阶段的所有调用都已终止时,给定命令的着色器阶段完成执行。

根据实现的不同,OpKill 在功能上将等同于 OpTerminateInvocationOpDemoteToHelperInvocation。为了获得最可预测的行为,着色器作者应尽可能使用 OpTerminateInvocationOpDemoteToHelperInvocation 而不是 OpKill

着色器内存访问排序

着色器读取或写入图像或缓冲区内存的顺序在很大程度上是未定义的。对于某些着色器类型(顶点、细分评估和某些情况下的片段),甚至可能执行加载和存储的着色器调用数量也是未定义的。

特别是,以下规则适用

  • 顶点细分评估着色器将为每个唯一的顶点至少调用一次,如这些部分所定义。

  • 片段着色器将被调用零次或多次,如该部分所定义。

  • 同一着色器类型的调用的相对执行顺序是未定义的。当处理图元 B 时,着色器发出的存储可能在图元 A 的存储之前完成,即使图元 A 在图元 B 之前指定也是如此。这甚至适用于片段着色器;虽然片段着色器输出始终按光栅化顺序写入帧缓冲区,但片段着色器调用执行的存储不是。

  • 不同着色器类型的调用的相对执行顺序在很大程度上是未定义的。

上述对着色器调用顺序的限制使得在单个图元集中无法实现着色器调用之间的某些形式的同步。例如,让一个调用轮询另一个调用写入的内存,假设另一个调用已启动并将在有限时间内完成其写入。

内存模型附录定义了术语和规则,用于如何在着色器调用之间正确通信,例如写入何时读取可见,以及什么构成数据竞争

应用程序必须不引起数据竞争。

SPIR-V 的 SubgroupMemoryCrossWorkgroupMemoryAtomicCounterMemory 内存语义被忽略。不支持顺序一致的原子操作和屏障,并且 SequentiallyConsistent 被视为 AcquireRelease应该不使用 SequentiallyConsistent

着色器输入和输出

数据分别通过具有输入或输出存储类的变量传递到着色器中和从着色器中传出。用户定义的输入和输出通过匹配它们的 Location 装饰在阶段之间连接。此外,数据可以通过使用 BuiltIn 装饰提供的执行环境提供的特殊函数提供或与之通信。

在许多情况下,相同的 BuiltIn 装饰可以在多个着色器阶段中使用,具有相似的含义。装饰为 BuiltIn 的变量的具体行为在以下部分中记录。

任务着色器

任务着色器与网格着色器结合运行,以生成一组图元,这些图元将由图形管道的后续阶段处理。其主要目的是创建可变数量的后续网格着色器调用。

任务着色器通过执行可编程网格着色管道调用。

任务着色器没有固定功能的输入,除了标识特定工作组和调用的变量。在 TaskNV Execution Model 中,要创建的网格着色器工作组的数量通过 TaskCountNV 装饰的输出变量指定。在 TaskEXT Execution Model 中,要创建的网格着色器工作组的数量通过 OpEmitMeshTasksEXT 指令指定。

任务着色器可以将其他输出写入任务内存,这些内存可以由它创建的所有网格着色器工作组读取。

任务着色器执行

任务工作负载由称为工作组的工作项组组成,并由当前图形管道中的任务着色器处理。工作组是执行相同着色器的一组着色器调用,可能并行执行。任务着色器在 全局工作组 中执行,全局工作组被分成多个 局部工作组,局部工作组的大小可以通过为 LocalSizeLocalSizeId 执行模式赋值或通过由 WorkgroupSize 装饰装饰的对象设置。局部工作组中的调用可以通过共享变量与其他局部工作组的成员共享数据,并发出内存和控制流屏障以与其他局部工作组的成员同步。如果子通道在其视图掩码中包含多个视图,则使用 TaskEXT Execution Model 的任务着色器可能会为每个视图单独调用。

网格着色器

网格着色器在工作组中运行,以生成一组图元,这些图元将由图形管道的后续阶段处理。每个工作组发出零个或多个输出图元,以及每个输出图元所需的一组顶点及其关联数据。

网格着色器通过执行可编程网格着色管道调用。

网格着色器可用的唯一输入是标识特定工作组和调用的变量,以及如果适用,任务着色器写入任务内存的任何输出,该任务着色器生成了网格着色器的工作组。网格着色器也可以在没有任务着色器的情况下运行。

网格着色器工作组的调用写入输出网格,包括一组具有每个图元属性的图元、一组具有每个顶点属性的顶点,以及一个标识属于每个图元的网格顶点的索引数组。然后,此网格的图元由后续的图形管道阶段处理,其中网格着色器的输出形成与片段着色器的接口。

网格着色器执行

网格工作负载由称为工作组的工作项组构成,并由当前图形管线中的网格着色器处理。工作组是执行相同着色器的着色器调用的集合,可能并行执行。网格着色器在全局工作组中执行,这些工作组被划分为多个局部工作组,其大小可以通过为 LocalSizeLocalSizeId 执行模式赋值,或通过使用 WorkgroupSize 修饰的对象来设置。局部工作组内的调用可以通过共享变量与其他局部工作组成员共享数据,并发出内存和控制流屏障以与其他局部工作组成员同步。

全局工作组可以通过 API 显式生成,也可以通过任务着色器的工作创建机制隐式生成。如果子通道在其视图掩码中包含多个视图,则使用 MeshEXT Execution Model 的网格着色器可以为每个视图单独调用。

集群剔除着色器

集群剔除着色器通过执行可编程集群剔除着色管线来调用。

集群剔除着色器唯一可用的输入是标识特定工作组和调用的变量。

集群剔除着色器在工作组中操作,以执行基于集群的剔除,并生成零个或多个集群绘制命令,这些命令将由图形管线的后续阶段处理。

集群绘制命令 (CDC) 与 MDI 命令非常相似,工作组中的调用可以发出零个或多个 CDC 以绘制零个或多个可见集群。

集群剔除着色器执行

集群剔除工作负载由称为工作组的工作项组构成,并由当前图形管线中的集群剔除着色器处理。工作组是执行相同着色器的着色器调用的集合,可能并行执行。集群剔除着色器在全局工作组中执行,这些工作组被划分为多个局部工作组,其大小可以通过为 LocalSizeLocalSizeId 执行模式赋值,或通过使用 WorkgroupSize 修饰的对象来设置。局部工作组内的调用可以通过共享变量与其他局部工作组成员共享数据,并发出内存和控制流屏障以与其他局部工作组成员同步。

顶点着色器

每个顶点着色器调用操作于一个顶点及其相关的顶点属性数据,并输出一个顶点和相关数据。使用原始着色的图形管线必须包含顶点着色器,并且顶点着色器阶段始终是图形管线中的第一个着色器阶段。

顶点着色器执行

对于绘制命令指定的每个顶点,必须至少执行一次顶点着色器。如果子通道在其视图掩码中包含多个视图,则可以为每个视图单独调用着色器。在执行期间,着色器会接收到其被调用的顶点和实例的索引。在顶点着色器中声明的输入变量由实现填充,并使用与正在执行的调用相关的顶点属性的值。

如果同一个顶点在绘制命令中多次指定(例如,通过在索引缓冲区中多次包含相同的索引值),如果实现可以静态地确定顶点着色器调用将产生相同的结果,则实现可以重用顶点着色的结果。

何时以及是否重用顶点着色的结果是与实现相关的,因此顶点着色器将执行多少次也是如此。如果顶点着色器包含存储或原子操作(请参阅vertexPipelineStoresAndAtomics),情况也是如此。

细分控制着色器

细分控制着色器用于读取应用程序提供的输入面片并生成输出面片。每个细分控制着色器调用操作于输入面片(在面片中的所有控制点都由顶点着色器处理之后)及其相关数据,并输出输出面片的单个控制点及其相关数据,并且可以输出额外的每个面片数据。输入面片的大小根据VkPipelineTessellationStateCreateInfopatchControlPoints 成员在输入汇编中确定。

输入面片也可以使用vkCmdSetPatchControlPointsEXTpatchControlPoints 参数动态调整大小。

动态设置每个面片的控制点数,请调用

// Provided by VK_EXT_extended_dynamic_state2, VK_EXT_shader_object
void vkCmdSetPatchControlPointsEXT(
    VkCommandBuffer                             commandBuffer,
    uint32_t                                    patchControlPoints);
  • commandBuffer 是将记录命令的命令缓冲区。

  • patchControlPoints 指定每个面片的控制点数。

当使用着色器对象进行绘制时,或当使用VkPipelineDynamicStateCreateInfo::pDynamicStates 中设置的 VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT 创建图形管线时,此命令为后续绘制命令设置每个面片的控制点数。否则,此状态由用于创建当前活动管线的VkPipelineTessellationStateCreateInfo::patchControlPoints 值指定。

有效用法
  • VUID-vkCmdSetPatchControlPointsEXT-None-09422
    以下条件中必须至少有一个为真

  • VUID-vkCmdSetPatchControlPointsEXT-patchControlPoints-04874
    patchControlPoints必须大于零且小于或等于 VkPhysicalDeviceLimits::maxTessellationPatchSize

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

  • VUID-vkCmdSetPatchControlPointsEXT-commandBuffer-recording
    commandBuffer 必须处于录制状态

  • VUID-vkCmdSetPatchControlPointsEXT-commandBuffer-cmdpool
    commandBuffer 分配自的 VkCommandPool 必须支持图形操作

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

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

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

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

主要
次要

两者

外部

图形

状态

输出面片的大小由细分控制着色器或细分评估着色器中指定的 OpExecutionMode OutputVertices 控制,并且必须在至少一个着色器中指定。输入和输出面片的大小必须都大于零且小于或等于 VkPhysicalDeviceLimits::maxTessellationPatchSize

细分控制着色器执行

对于面片中的每个输出顶点,必须至少调用一次细分控制着色器。如果子通道在其视图掩码中包含多个视图,则可以为每个视图单独调用着色器。

细分控制着色器的输入由顶点着色器生成。每次调用细分控制着色器可以读取任何传入顶点的属性及其关联数据。与给定补丁对应的调用在逻辑上并行执行,相对执行顺序未定义。但是,可以使用 OpControlBarrier 指令通过同步补丁内的调用来提供对执行顺序的有限控制,从而有效地将细分控制着色器执行划分为一组阶段。如果在同一阶段中,一个调用读取了另一个调用写入的每个顶点或每个补丁的输出,或者如果两个调用尝试在单个阶段中将不同的值写入相同的每个补丁的输出,则细分控制着色器将读取未定义的值。

细分评估着色器

细分评估着色器对控制点的输入补丁及其关联数据进行操作,以及一个指示调用在细分补丁内的相对位置的单个输入重心坐标,并输出单个顶点及其关联数据。

细分评估着色器执行

对于细分器生成的每个唯一顶点,至少会调用一次细分评估着色器。如果子通道在其视图掩码中包含多个视图,则可能会为每个视图单独调用着色器。

几何着色器

几何着色器对从单个输入图元组装的一组顶点及其关联数据进行操作,并发出零个或多个输出图元以及每个输出图元所需的一组顶点及其关联数据。

几何着色器执行

对于细分阶段生成的每个图元,或在不使用细分时,对于图元组装生成的每个图元,至少会调用一次几何着色器。着色器可以请求几何着色器运行多个实例。对于每个实例,至少会调用一次几何着色器。如果子通道在其视图掩码中包含多个视图,则可能会为每个视图单独调用着色器。

片段着色器

片段着色器作为图形管道中的片段操作调用。每个片段着色器调用对单个片段及其关联数据进行操作。除了少数例外,片段着色器无法访问与任何其他片段关联的任何数据,并且被认为与其他片段关联的片段着色器调用隔离执行。

计算着色器

计算着色器通过_调度命令调用。通常,它们可以访问与作为图形管道一部分执行的着色器阶段类似的资源。

计算工作负载由称为工作组的工作项组组成,并由当前计算管道中的计算着色器处理。工作组是执行相同着色器的一组着色器调用,可能会并行执行。计算着色器在全局工作组中执行,全局工作组被划分为多个本地工作组,其大小可以通过为 LocalSizeLocalSizeId 执行模式赋值或通过 WorkgroupSize 修饰的对象来设置。本地工作组中的调用可以通过共享变量与其他本地工作组成员共享数据,并发出内存和控制流屏障以与其他本地工作组成员同步。

光线生成着色器

光线生成着色器类似于计算着色器。其主要目的是使用管道跟踪光线指令(例如 OpTraceRayKHR)执行光线跟踪查询并处理结果。

光线生成着色器执行

每个光线跟踪调度执行一个光线生成着色器。它在着色器绑定表中的位置(详见着色器绑定表)通过 pRaygenShaderBindingTable 参数直接传递到 vkCmdTraceRaysKHR,或通过 raygenShaderBindingTableBufferraygenShaderBindingOffset 参数传递到 vkCmdTraceRaysNV

相交着色器

相交着色器允许实现任意、应用程序定义的几何图元。每当光线击中其轴对齐边界框时,就会执行图元的相交着色器。

与其他光线跟踪着色器域一样,相交着色器一次处理一根光线。它还一次处理一个图元。因此,相交着色器的目的是计算光线-图元相交并报告它们。要报告相交,着色器会调用 OpReportIntersectionKHR 指令。

相交着色器通过生成它们可以读取的属性值与任何命中和最近着色器通信。相交着色器不能读取或修改光线有效负载。

相交着色器执行

沿光线找到相交的顺序,以及因此执行相交着色器的顺序是未指定的。

保证在遍历期间的某个时候执行与光线相交的最近 AABB 的相交着色器,除非光线被强制终止。

任何命中着色器

在相交着色器报告位于光线的当前 [tmin,tmax] 内的相交后,执行任何命中着色器。任何命中着色器的主要用途是按程序决定是否接受相交。除非着色器调用 OpIgnoreIntersectionKHR 指令,否则将接受相交。任何命中着色器都对相应相交着色器生成的属性具有只读访问权限,并且可以读取或修改光线有效负载。

任何命中着色器执行

沿光线找到相交的顺序,以及因此执行任何命中着色器的顺序是未指定的。

保证在遍历期间的某个时候执行最近命中的任何命中着色器,除非光线被强制终止。

最近命中着色器

最近命中着色器拥有对相应交点着色器生成的属性的只读访问权限,并且可以读取或修改射线载荷。它们还可以访问一些系统生成的值。最近命中着色器可以调用管线跟踪射线指令来递归跟踪射线。

最近命中着色器执行

当遍历完成并且找到并接受了一个交点时,会执行恰好一个最近命中着色器。

未命中着色器

未命中着色器可以访问射线载荷,并且可以通过管线跟踪射线指令跟踪新射线,但是由于它们不与交点关联,因此不能访问属性。

未命中着色器执行

如果在遍历期间没有找到交点,则会执行未命中着色器,而不是最近命中着色器。

可调用着色器

可调用着色器可以访问类似于射线载荷的可调用载荷,以进行子例程工作。

可调用着色器执行

可调用着色器通过从允许的着色器阶段调用 OpExecuteCallableKHR 来执行。

插值修饰符

片段着色器接口中 Input 存储类中的变量是从正在光栅化的图元指定的值插值而来的。

插值修饰符可以存在于预光栅化着色器的输入和输出变量中,但对执行的插值没有影响。

未修饰的输入变量将根据正在光栅化的图元类型进行透视校正插值。线多边形的插值方式与图元的裁剪坐标相同。如果存在 NoPerspective 修饰符,则对线多边形使用线性插值。对于点,由于只有一个顶点,因此输入值永远不会被插值,而是采用为单个顶点写入的值。

如果输入变量上存在 Flat 修饰符,则该值不会被插值,而是直接从触发顶点获取其值。片段着色器输入(有符号或无符号整数、整数向量或任何双精度浮点类型)必须使用 Flat 修饰符。

输入变量的插值是在被着色的片段区域内实现定义的某个位置执行的。该位置进一步约束如下:

  • 如果使用 Centroid 修饰符,则用于该变量的插值位置必须也落在正在光栅化的图元的边界内。

  • 如果使用 Sample 修饰符,则用于该变量的插值位置必须是当前片段着色器调用正在着色的样本的位置。

  • 如果使用 1 的样本计数,则插值位置必须位于片段区域的中心。

由于 Centroid 将插值位置限制在图元的覆盖区域内,因此当位置本来不会不同时,使用它可能会导致相邻片段之间的位置不同。与未修饰的输入相比,基于这些不同位置计算的导数可能会产生不一致的结果。因此,不建议将 Centroid 与用于导数计算的输入变量一起使用。

如果输入变量上存在 PerVertexKHR 修饰符,则该值不会被插值,而是可以在数组中使用来自所有输入顶点的值。数组的每个索引对应于生成片段的图元的顶点之一。

如果输入变量上存在 CustomInterpAMD 修饰符,则不能直接访问该值;而是必须使用扩展指令 InterpolateAtVertexAMD 从输入顶点获取值。

静态使用

SPIR-V 模块使用 OpVariable 指令在内存中声明一个全局对象,这将导致指向该对象的指针 x。如果 SPIR-V 模块中特定入口点的调用树包含一个包含 x 作为 id 操作数的指令的函数,则该入口点称为静态使用该对象。着色器入口点也静态使用在其接口中显式声明的任何变量。

作用域

作用域描述了一组着色器调用,其中每个这样的集合都是一个作用域实例。每个调用属于一个或多个作用域实例,但每个作用域最多属于一个作用域实例。

给定作用域实例中调用之间的可用操作有所不同,较小的作用域通常能够执行更多操作,并且具有更高的效率。

跨设备

在 Vulkan 实例中执行的所有调用都属于单个跨设备作用域实例

虽然 CrossDevice 作用域在 SPIR-V 中定义,但在 Vulkan 中是不允许的。API 同步命令可以用于在设备之间进行通信。

设备

在单个设备上执行的所有调用构成一个设备作用域实例

如果启用了vulkanMemoryModelvulkanMemoryModelDeviceScope功能,则此作用域在 SPIR-V 中由 Device Scope 表示,它可以用作屏障和原子操作的 Memory Scope

如果同时启用了shaderDeviceClockvulkanMemoryModelDeviceScope功能,则将 Device ScopeOpReadClockKHR 指令一起使用将从在同一设备作用域实例中的调用之间一致的时钟读取。

没有在 SPIR-V 中同步这些调用的执行的方法,这只能通过 API 同步原语来完成。

在设备组中不同设备上执行的调用在单独的设备作用域实例中运行。

队列族

给定队列族中队列执行的调用形成一个队列族作用域实例

如果启用了 vulkanMemoryModel 特性,则此作用域在 SPIR-V 中标识为 QueueFamily Scope;否则,标识为 Device Scope,它可以用作屏障和原子操作的 Memory Scope

如果启用了 shaderDeviceClock 特性,但未启用 vulkanMemoryModelDeviceScope 特性,则将 Device ScopeOpReadClockKHR 指令一起使用将从同一队列族作用域实例中调用之间一致的时钟读取。

没有在 SPIR-V 中同步这些调用的执行的方法,这只能通过 API 同步原语来完成。

队列族作用域实例中的每个调用必须在相同的设备作用域实例中。

命令

作为单个命令(例如 vkCmdDispatchvkCmdDraw)的结果而执行的任何着色器调用都形成一个命令作用域实例。对于 drawCount 大于 1 的间接绘制命令,来自单独绘制的调用位于单独的命令作用域实例中。对于光线追踪着色器,调用组是由单个跟踪光线命令生成的给定着色器阶段的着色器调用集合的实现定义的子集。

在命令作用域实例中跨调用进行通信没有特定的 Scope。由于这在 API 级别有一个清晰的边界,因此此处的协调可以在 API 中执行,而不是在 SPIR-V 中执行。

命令作用域实例中的每个调用必须在相同的队列族作用域实例中。

对于没有定义工作组的着色器,此调用集合形成SPIR-V 规范中定义的调用组

图元

作为单个图元光栅化的结果而执行的任何片段着色器调用都形成一个图元作用域实例

在图元作用域实例中跨调用进行通信没有特定的 Scope

任何生成的辅助调用都包含在此作用域实例中。

图元作用域实例中的每个调用必须在相同的命令作用域实例中。

任何使用 Flat 修饰的输入变量在图元作用域实例中都是统一的。

着色器调用

在一个或多个光线追踪执行模型中执行的任何与着色器调用相关的调用都形成一个着色器调用作用域实例

ShaderCallKHR Scope 可用作屏障和原子操作的 Memory Scope

着色器调用作用域实例中的每个调用必须在相同的队列族作用域实例中。

工作组

本地工作组是一组调用,它们可以使用 Workgroup 存储类中的内存相互同步和共享数据。

Workgroup Scope 可以用作屏障和原子操作的 Execution ScopeMemory Scope

本地工作组中的每个调用必须在相同的命令作用域实例中。

只有任务、网格和计算着色器定义了工作组 - 其他着色器类型不能使用工作组功能。对于定义了工作组的着色器,此调用集合形成SPIR-V 规范中定义的调用组

当使用 Workgroup 存储类声明的变量显式布局时(因此它们也使用 Block 修饰),所消耗的存储量是最大 Block 变量的大小,不计算末尾的任何填充。使用 Workgroup 存储类声明的非 Block 变量所消耗的存储量是实现定义的。但是,所消耗的存储量可能不会超过通过以下方式获得的最大块大小:如果所有使用 Workgroup 存储类声明的活动非 Block 变量按照标准存储缓冲区布局规则,并按任意顺序连续取得最小有效偏移量,并且在此计算中将 Boolean 值视为 32 位整数值(这相当于使用 GLSL std430 布局规则)。

子组

子组(请参阅 SPIR-V 1.3 修订版 1 规范第 2 节的“控制流”小节)是一组调用,它们可以相互有效地同步和共享数据。

Subgroup Scope 可用作屏障和原子操作的 Execution ScopeMemory Scope。其他子组特性允许将组操作与子组范围一起使用。

如果启用了 shaderSubgroupClock 特性,则将 Subgroup ScopeOpReadClockKHR 指令一起使用将从同一子组中的调用之间一致的时钟读取。

对于定义了工作组的着色器,子组中的每个调用必须在相同的本地工作组中。

在其他着色器阶段,子组中的每个调用必须在相同的设备作用域实例中。

只有支持子组操作的着色器阶段定义了子组。

不能保证子组是没有定义工作组的着色器中单个命令的子集。保证对于给定命令或子命令统一的值可能对于子组不统一,反之亦然。因此,应用程序在处理混合均匀性时必须小心。

一个比较常见的例子是尝试使用子组操作来优化对每次绘制数据的访问。

buffer { uint draw_data[]; };

flat in int vDrawID; // Passed through from vertex shader

void main()
{
    uint local_draw_data = subgroupBroadcastFirst(draw_data[local_draw_data]);
}

这可以通过尝试优化着色器以仅为每个子组执行一次加载来完成。但是,如果实现将多次绘制打包到单个子组中,则来自具有不同 drawID 的绘制的调用现在将从错误的调用接收数据。应用程序应该依赖于实现自动执行这种优化(如果实现可以执行),而不是试图强制执行。

四边形

四边形作用域实例由四个着色器调用组成。

在片段着色器中,四边形作用域实例中的每个调用都由相邻帧缓冲区位置 (xi, yi) 中的调用组成,其中

  • i 是调用在作用域实例中的索引。

  • wh 是片段在 xy 轴上覆盖的像素数。

  • 对于所有参与的调用,wh 都是相同的。

  • (x0) = (x1 - w) = (x2) = (x3 - w)

  • (y0) = (y1) = (y2 - h) = (y3 - h)

  • 每次调用都具有相同的层和采样索引。

在网格着色器、任务着色器或计算着色器中,如果指定了 DerivativeGroupQuadsKHR 执行模式,则四边形范围实例中的每次调用都由局部调用 ID 相邻的调用组成 (xi, yi),其中

  • i 是四边形范围实例中调用的索引。

  • (x0) = (x1 - 1) = (x2) = (x3 - 1)

  • (y0) = (y1) = (y2 - 1) = (y3 - 1)

  • x0y0 是 2 的整数倍。

  • 每次调用都具有相同的 z 坐标。

在网格着色器、任务着色器或计算着色器中,如果指定了 DerivativeGroupLinearKHR 执行模式,则四边形范围实例中的每次调用都由局部调用索引相邻的调用组成 (li),其中

  • i 是四边形范围实例中调用的索引。

  • (l0) = (l1 - 1) = (l2 - 2) = (l3 - 3)

  • l0 是 4 的整数倍。

在所有着色器中,四边形范围实例中的每次调用都由相邻子组调用索引中的调用组成 (si),其中

  • i 是四边形范围实例中调用的索引。

  • (s0) = (s1 - 1) = (s2 - 2) = (s3 - 3)

  • s0 是 4 的整数倍。

四边形范围实例中的每次调用必须在同一个 子组中。

在片段着色器中,四边形范围实例中的每次调用必须在同一个 图元范围实例中。

片段着色器、网格着色器、任务着色器和计算着色器都定义了四边形范围实例。如果支持 quadOperationsInAllStages 限制,则任何支持子组操作的着色器阶段也都有定义的四边形范围实例。

片段互锁

片段互锁范围实例是由片段着色器调用根据其帧缓冲区位置 (x,y,layer,sample) 形成的,由单个 子通道 内的命令执行。

所包含的特定调用集会根据执行模式的不同而有所不同,如下所示

  • 如果使用 SampleInterlockOrderedEXTSampleInterlockUnorderedEXT 执行模式,则仅包含具有相同帧缓冲区位置 (x,y,layer,sample) 的调用。

  • 如果使用 PixelInterlockOrderedEXTPixelInterlockUnorderedEXT 执行模式,则还会包括具有不同采样 ID 的片段。

  • 如果使用 ShadingRateInterlockOrderedEXTShadingRateInterlockUnorderedEXT 执行模式,则还会包括来自相邻帧缓冲区位置的片段。着色率图像片段着色率 确定这些片段。

只有具有上述执行模式之一的片段着色器才具有定义的片段互锁范围实例。

在片段互锁范围实例中,跨调用的通信没有特定的 Scope 值。但是,这被隐式地用作 OpBeginInvocationInterlockEXTOpEndInvocationInterlockEXT 的内存范围。

片段互锁范围实例中的每次调用必须在同一个 队列族范围实例中。

调用

最小的范围是单个调用;这在 SPIR-V 中由 Invocation Scope 表示。

片段着色器调用必须图元范围实例中。

具有已定义子组范围的着色器中的调用必须子组中。

所有阶段中的所有调用必须命令范围实例中。

组操作

组操作范围实例内的多个调用执行;其中每个调用都参与计算结果。这为特定范围实例中的调用之间的有效通信提供了一种机制。

组操作都采用一个 Scope,用于定义要操作的所需 范围实例。只有 Subgroup 范围可以用于这些操作;subgroupSupportedOperations 限制定义了哪些类型的操作可以使用。

基本组操作

基本组操作包括使用 OpGroupNonUniformElectOpControlBarrierOpMemoryBarrier 和原子操作。

可以使用 OpGroupNonUniformElect 来选择单个调用为整个组执行任务。只有组中 ID 最低的调用才会返回 true

内存模型附录定义了屏障和原子操作的执行方式。

投票组操作

投票组操作允许组内的调用跨组比较值。启用的投票类型为

  • 所有活动组调用是否都同意某个表达式为真?

  • 是否有任何活动组调用将某个表达式计算为真?

  • 所有活动组调用是否具有相同的表达式值?

这些操作与控制流结合使用时非常有用,因为它们允许开发人员检查组内的条件是否匹配,并在这些情况下选择可能更快的代码路径。

算术组操作

算术组操作允许调用在组中执行扫描和缩减。支持的运算符有加、乘、最小、最大、与、或、异或。

对于缩减,组中的每个调用都将获得这些运算符应用于组中所有值的累积结果。对于独占扫描,组中的每个调用都将获得这些运算符应用于组中索引较低的调用中的所有值的累积结果。包含扫描与独占扫描相同,只是累积结果包括应用于当前调用中值的运算符。

这些运算符的应用顺序取决于实现。

投票组操作

投票组操作允许调用在组中执行更复杂的投票。投票功能允许组内的所有调用提供一个布尔值,并获取每个调用提供的布尔值的结果。广播功能允许将值从一个调用广播到组内的所有其他调用。

混洗组操作

混洗组操作允许调用读取组内其他调用的值。

相对混洗组操作

相对混洗组操作允许调用从组内相对于当前调用的其他调用中读取值。支持的相对操作允许数据在组内的调用中向上和向下移动。

集群组操作

集群组操作允许调用在组的分区之间执行操作,使得该操作仅在分区内的组调用中执行。集群组操作的分区是连续的 2 的幂次大小的调用组,并且集群大小必须在管道创建时已知。支持的操作有加法 (add)、乘法 (mul)、最小值 (min)、最大值 (max)、与 (and)、或 (or)、异或 (xor)。

旋转组操作

旋转组操作允许调用读取组内其他调用的值,这些值相对于当前调用并以组的大小为模。集群旋转组操作在组的各个分区内执行相同的操作。

集群旋转组操作的分区是连续的 2 的幂次大小的调用组,并且集群大小必须在管道创建时已知。

四元组组操作

四元组组操作 (OpGroupNonUniformQuad*) 是一种特殊的组操作,仅在四元组范围实例上运行。尽管这些指令确实包含一个 Scope 参数,但此范围始终被覆盖;在其执行范围中仅包含四元组范围实例

静态执行 OpGroupNonUniformQuadBroadcastOpGroupNonUniformQuadSwap 的片段着色器必须启动足够的调用以确保其正确运行;如果需要,会为光栅化片段未覆盖的帧缓冲区位置启动额外的辅助调用

用于选择参与调用的索引是 i,如四元组范围实例所述,在SPIR-V 规范中定义为四元组索引

对于 OpGroupNonUniformQuadBroadcast,此值等于 Index。对于 OpGroupNonUniformQuadSwap,它等于每个参与调用使用的隐式 Index

导数操作

导数操作计算表达式 P 相对于调用 xy 坐标的偏导数。

导数操作作用于一组称为导数组的调用,如SPIR-V 规范中所定义。

如果指定了 QuadDerivativesKHR 执行模式,则片段着色器中的导数组等效于四元组范围实例,否则等效于图元范围实例。网格、任务或计算着色器中的导数组等效于四元组范围实例

计算导数时假设 P 在导数组内是分段线性且连续的。

以下控制流限制适用于导数操作:

  • 如果指定了 QuadDerivativesKHR 执行模式,任何导数操作的动态实例必须在当前四元组范围实例内统一的控制流中执行。

  • 如果未指定 QuadDerivativesKHR 执行模式:

    • 显式导数指令(OpDPdx*OpDPdy*OpFwidth*)的动态实例必须在导数组内统一的控制流中执行。

    • 隐式导数操作的动态实例可以在导数组内不统一的控制流中执行,但结果是未定义的

静态执行导数操作的片段着色器必须启动足够的调用以确保其正确运行;如果需要,会为光栅化片段未覆盖的帧缓冲区位置启动额外的辅助调用

在网格、任务或计算着色器中,应用程序有责任确保启动足够的调用。

导数操作计算其结果为四元组中调用之间 P 的结果之差。对于精细导数操作 (OpDPdxFineOpDPdyFine),DPdx(Pi) 的值计算为:

DPdx(P0) = DPdx(P1) = P1 - P0

DPdx(P2) = DPdx(P3) = P3 - P2

并且 DPdy(Pi) 的值计算为:

DPdy(P0) = DPdy(P2) = P2 - P0

DPdy(P1) = DPdy(P3) = P3 - P1

其中 i 是每个调用的索引,如四元组中所述。

粗略导数操作 (OpDPdxCoarseOpDPdyCoarse) 以大致相同的方式计算其结果,但可能只计算两个值而不是四个(每个 DPdxDPdy 一个),无论原始调用如何,都重用相同的结果。如果实现这样做,它应该使用为 P0 描述的精细导数计算。

导数值是在片段之间而不是像素之间计算的。如果计算中涉及的片段着色器调用覆盖多个像素,则这些操作会覆盖更广泛的区域,从而产生更大的导数值。反过来,这将导致为使用导数的图像采样操作选择更粗糙的 LOD。

应用程序可能需要在使用多像素片段时考虑这一点;如果需要像素导数,应用程序应使用显式导数操作并将结果除以每个维度中片段的大小,如下所示:

DPdx(Pn)' = DPdx(Pn) / w

DPdy(Pn)' = DPdy(Pn) / h

其中 wh 是四元组中片段的大小,DPdx(Pn)'DPdy(Pn)' 是像素导数。

OpDPdxOpDPdy 的结果可以计算为精细导数或粗略导数,实现优先选择最有效的方法。实现必须在这两者之间一致地选择粗略或精细。

执行 OpFwidthFineOpFwidthCoarseOpFwidth 等效于执行相应的 OpDPdx*OpDPdy* 指令,取结果的绝对值并将它们相加。

执行 OpImage*Sample*ImplicitLod 指令等效于执行 OpDPdx(Coordinate) 和 OpDPdy(Coordinate),并将结果作为 Grad 操作数 dxdy 传递。

预计使用采样函数的 ImplicitLod 变体将比使用带有显式生成的导数的 ExplicitLod 变体效率高得多。

辅助调用

在片段着色器中执行导数四元组组操作时,可以生成额外的调用以确保正确的结果。这些额外的调用称为辅助调用,可以通过 HelperInvocation 内置的非零值来识别。辅助调用执行的存储和原子操作必须对内存没有任何影响,除了 FunctionPrivateOutput 存储类,并且辅助调用中原子指令返回的值是未定义的

虽然对 Output 存储类的存储即使在辅助调用中也有效,但这并不意味着辅助调用对帧缓冲区有影响。片段着色器中的 Output 变量也可以从中读取,并且在着色器调用期间它们的行为更像是 Private 变量。

如果将 MaximallyReconvergesKHR 执行模式应用于入口点,则辅助调用必须在其所属的四方范围实例的整个生命周期内对所有指令保持活动状态。 如果未将 MaximallyReconvergesKHR 执行模式应用于入口点,则对于 组操作导数四方组操作除外),辅助调用可能被视为不活动。 一旦四方范围实例中仅剩的调用是辅助调用,则该四方范围实例中的所有调用可能在任何时候永久变为不活动状态。

协同矩阵

协同矩阵类型是一种 SPIR-V 类型,其中矩阵的存储和执行的计算分布在范围实例中的调用之间。 这些类型为实现如何在优化矩阵乘法方面提供了自由。

SPIR-V 定义了类型和指令,但未指定有关哪些大小/组合有效的规则,并且预期不同的实现可能支持不同的大小。

要枚举支持的协同矩阵类型和操作,请调用

// Provided by VK_KHR_cooperative_matrix
VkResult vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR(
    VkPhysicalDevice                            physicalDevice,
    uint32_t*                                   pPropertyCount,
    VkCooperativeMatrixPropertiesKHR*           pProperties);
  • physicalDevice 是物理设备。

  • pPropertyCount 是一个指向整数的指针,该整数与可用或查询的协同矩阵属性的数量有关。

  • pPropertiesNULL 或指向 VkCooperativeMatrixPropertiesKHR 结构数组的指针。

如果 pPropertiesNULL,则可用协同矩阵属性的数量将在 pPropertyCount 中返回。 否则,pPropertyCount 必须指向应用程序设置为 pProperties 数组中元素数量的变量,并且在返回时,该变量将被实际写入 pProperties 的结构数量覆盖。 如果 pPropertyCount 小于可用协同矩阵属性的数量,则最多将写入 pPropertyCount 个结构,并且将返回 VK_INCOMPLETE 而不是 VK_SUCCESS,以指示并非返回了所有可用的协同矩阵属性。

有效使用(隐式)
  • VUID-vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR-physicalDevice-parameter
    physicalDevice 必须是有效的 VkPhysicalDevice 句柄

  • VUID-vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR-pPropertyCount-parameter
    pPropertyCount 必须是指向 uint32_t 值的有效指针

  • VUID-vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR-pProperties-parameter
    如果 pPropertyCount 引用的值不是 0,并且 pProperties 不是 NULL,则 pProperties 必须是指向 pPropertyCountVkCooperativeMatrixPropertiesKHR 结构数组的有效指针

返回码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

要枚举其他支持的协同矩阵类型和操作,请调用

// Provided by VK_NV_cooperative_matrix2
VkResult vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV(
    VkPhysicalDevice                            physicalDevice,
    uint32_t*                                   pPropertyCount,
    VkCooperativeMatrixFlexibleDimensionsPropertiesNV* pProperties);
  • physicalDevice 是物理设备。

  • pPropertyCount 是一个指向整数的指针,该整数与可用或查询的协同矩阵属性的数量有关。

  • pPropertiesNULL 或指向 VkCooperativeMatrixFlexibleDimensionsPropertiesNV 结构数组的指针。

如果 pPropertiesNULL,则可用的灵活维度属性的数量将在 pPropertyCount 中返回。 否则,pPropertyCount 必须指向应用程序设置为 pProperties 数组中元素数量的变量,并且在返回时,该变量将被实际写入 pProperties 的结构数量覆盖。 如果 pPropertyCount 小于可用的灵活维度属性的数量,则最多将写入 pPropertyCount 个结构,并且将返回 VK_INCOMPLETE 而不是 VK_SUCCESS,以指示并非返回了所有可用的灵活维度属性。

如果不支持 cooperativeMatrixFlexibleDimensions 功能,则实现必须声明零个属性。

有效使用(隐式)
  • VUID-vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV-physicalDevice-parameter
    physicalDevice 必须是有效的 VkPhysicalDevice 句柄

  • VUID-vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV-pPropertyCount-parameter
    pPropertyCount 必须是指向 uint32_t 值的有效指针

  • VUID-vkGetPhysicalDeviceCooperativeMatrixFlexibleDimensionsPropertiesNV-pProperties-parameter
    如果 pPropertyCount 引用的值不是 0,并且 pProperties 不是 NULL,则 pProperties 必须是指向 pPropertyCountVkCooperativeMatrixFlexibleDimensionsPropertiesNV 结构数组的有效指针

返回码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

要枚举支持的协同矩阵类型和操作,请调用

// Provided by VK_NV_cooperative_matrix
VkResult vkGetPhysicalDeviceCooperativeMatrixPropertiesNV(
    VkPhysicalDevice                            physicalDevice,
    uint32_t*                                   pPropertyCount,
    VkCooperativeMatrixPropertiesNV*            pProperties);
  • physicalDevice 是物理设备。

  • pPropertyCount 是一个指向整数的指针,该整数与可用或查询的协同矩阵属性的数量有关。

  • pPropertiesNULL 或指向 VkCooperativeMatrixPropertiesNV 结构数组的指针。

如果 pPropertiesNULL,则可用协同矩阵属性的数量将在 pPropertyCount 中返回。 否则,pPropertyCount 必须指向应用程序设置为 pProperties 数组中元素数量的变量,并且在返回时,该变量将被实际写入 pProperties 的结构数量覆盖。 如果 pPropertyCount 小于可用协同矩阵属性的数量,则最多将写入 pPropertyCount 个结构,并且将返回 VK_INCOMPLETE 而不是 VK_SUCCESS,以指示并非返回了所有可用的协同矩阵属性。

有效使用(隐式)
  • VUID-vkGetPhysicalDeviceCooperativeMatrixPropertiesNV-physicalDevice-parameter
    physicalDevice 必须是有效的 VkPhysicalDevice 句柄

  • VUID-vkGetPhysicalDeviceCooperativeMatrixPropertiesNV-pPropertyCount-parameter
    pPropertyCount 必须是指向 uint32_t 值的有效指针

  • VUID-vkGetPhysicalDeviceCooperativeMatrixPropertiesNV-pProperties-parameter
    如果 pPropertyCount 引用的值不是 0,并且 pProperties 不是 NULL,则 pProperties 必须是指向 pPropertyCountVkCooperativeMatrixPropertiesNV 结构数组的有效指针

返回码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

每个 VkCooperativeMatrixPropertiesKHRVkCooperativeMatrixPropertiesNV 结构都描述了矩阵乘/加运算 (OpCooperativeMatrixMulAddKHROpCooperativeMatrixMulAddNV) 支持的类型的单个组合。 乘法可以用以下变量和类型(在 SPIR-V 伪代码中)描述

    %A is of type OpTypeCooperativeMatrixKHR %AType %scope %MSize %KSize %MatrixAKHR
    %B is of type OpTypeCooperativeMatrixKHR %BType %scope %KSize %NSize %MatrixBKHR
    %C is of type OpTypeCooperativeMatrixKHR %CType %scope %MSize %NSize %MatrixAccumulatorKHR
    %Result is of type OpTypeCooperativeMatrixKHR %ResultType %scope %MSize %NSize %MatrixAccumulatorKHR

    %Result = %A * %B + %C // using OpCooperativeMatrixMulAddKHR
    %A is of type OpTypeCooperativeMatrixNV %AType %scope %MSize %KSize
    %B is of type OpTypeCooperativeMatrixNV %BType %scope %KSize %NSize
    %C is of type OpTypeCooperativeMatrixNV %CType %scope %MSize %NSize
    %D is of type OpTypeCooperativeMatrixNV %DType %scope %MSize %NSize

    %D = %A * %B + %C // using OpCooperativeMatrixMulAddNV

具有这些维度的矩阵乘法称为 MxNxK 矩阵乘法。

VkCooperativeMatrixPropertiesKHR 结构的定义如下

// Provided by VK_KHR_cooperative_matrix
typedef struct VkCooperativeMatrixPropertiesKHR {
    VkStructureType       sType;
    void*                 pNext;
    uint32_t              MSize;
    uint32_t              NSize;
    uint32_t              KSize;
    VkComponentTypeKHR    AType;
    VkComponentTypeKHR    BType;
    VkComponentTypeKHR    CType;
    VkComponentTypeKHR    ResultType;
    VkBool32              saturatingAccumulation;
    VkScopeKHR            scope;
} VkCooperativeMatrixPropertiesKHR;
  • sType 是一个 VkStructureType 值,用于标识此结构。

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

  • MSize 是矩阵 ACResult 中的行数。

  • KSize 是矩阵 A 中的列数和矩阵 B 中的行数。

  • NSize 是矩阵 BCResult 中的列数。

  • AType 是矩阵 A 的组件类型,类型为 VkComponentTypeKHR

  • BType 是矩阵 B 的组件类型,类型为 VkComponentTypeKHR

  • CType 是矩阵 C 的组件类型,类型为 VkComponentTypeKHR

  • ResultType 是矩阵 Result 的组件类型,类型为 VkComponentTypeKHR

  • saturatingAccumulation 指示 OpCooperativeMatrixMulAddKHRSaturatingAccumulation 操作数是否必须存在。如果为 VK_TRUE,则 SaturatingAccumulation 操作数必须存在。如果为 VK_FALSE,则 SaturatingAccumulation 操作数必须不存在。

  • scope 是所有矩阵类型的范围,类型为 VkScopeKHR

如果某些类型比其他类型更受偏爱(例如,为了性能),它们应该vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR 枚举的列表中较早出现。

列表中至少有一个条目的 MSizeKSizeNSize 的所有值必须是 2 的幂。

如果不支持 cooperativeMatrixWorkgroupScope 功能,则 scope必须VK_SCOPE_SUBGROUP_KHR

有效使用(隐式)
  • VUID-VkCooperativeMatrixPropertiesKHR-sType-sType
    sType必须VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_KHR

  • VUID-VkCooperativeMatrixPropertiesKHR-pNext-pNext
    pNext 必须NULL

VkCooperativeMatrixFlexibleDimensionsPropertiesNV 结构定义如下:

// Provided by VK_NV_cooperative_matrix2
typedef struct VkCooperativeMatrixFlexibleDimensionsPropertiesNV {
    VkStructureType       sType;
    void*                 pNext;
    uint32_t              MGranularity;
    uint32_t              NGranularity;
    uint32_t              KGranularity;
    VkComponentTypeKHR    AType;
    VkComponentTypeKHR    BType;
    VkComponentTypeKHR    CType;
    VkComponentTypeKHR    ResultType;
    VkBool32              saturatingAccumulation;
    VkScopeKHR            scope;
    uint32_t              workgroupInvocations;
} VkCooperativeMatrixFlexibleDimensionsPropertiesNV;
  • sType 是一个 VkStructureType 值,用于标识此结构。

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

  • MGranularity 是矩阵 ACResult 中行数的粒度。行数必须是该值的整数倍。

  • KGranularity 是矩阵 A 中的列数和矩阵 B 中的行数的粒度。列/行数必须是该值的整数倍。

  • NGranularity 是矩阵 BCResult 中列数的粒度。列数必须是该值的整数倍。

  • AType 是矩阵 A 的组件类型,类型为 VkComponentTypeKHR

  • BType 是矩阵 B 的组件类型,类型为 VkComponentTypeKHR

  • CType 是矩阵 C 的组件类型,类型为 VkComponentTypeKHR

  • ResultType 是矩阵 Result 的组件类型,类型为 VkComponentTypeKHR

  • saturatingAccumulation 指示 OpCooperativeMatrixMulAddKHRSaturatingAccumulation 操作数是否必须存在。如果为 VK_TRUE,则 SaturatingAccumulation 操作数必须存在。如果为 VK_FALSE,则 SaturatingAccumulation 操作数必须不存在。

  • scope 是所有矩阵类型的范围,类型为 VkScopeKHR

  • workgroupInvocations 是支持此值组合时本地工作组中的调用次数。

VkCooperativeMatrixFlexibleDimensionsPropertiesNV 不是显式枚举支持的大小列表,而是声明了大小粒度,其中矩阵必须是声明大小的倍数。M 和 K 粒度适用于 UseMatrixA 的矩阵的行和列,K 和 N 适用于 UseMatrixB 的矩阵的行和列,M 和 N 适用于 UseMatrixAccumulator 的矩阵的行和列。

对于给定的类型组合,如果支持多个工作组大小,则可能存在多个具有不同粒度的 VkCooperativeMatrixFlexibleDimensionsPropertiesNV 结构。

所有粒度值必须是 2 的幂。

不同的 A/B 类型可能需要不同的粒度,但共享相同的累加器类型。在这种情况下,具有累加器类型的矩阵的受支持粒度将是声明的最小粒度。

有效使用(隐式)
  • VUID-VkCooperativeMatrixFlexibleDimensionsPropertiesNV-sType-sType
    sType必须VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_FLEXIBLE_DIMENSIONS_PROPERTIES_NV

  • VUID-VkCooperativeMatrixFlexibleDimensionsPropertiesNV-pNext-pNext
    pNext 必须NULL

VkCooperativeMatrixPropertiesNV 结构定义如下:

// Provided by VK_NV_cooperative_matrix
typedef struct VkCooperativeMatrixPropertiesNV {
    VkStructureType      sType;
    void*                pNext;
    uint32_t             MSize;
    uint32_t             NSize;
    uint32_t             KSize;
    VkComponentTypeNV    AType;
    VkComponentTypeNV    BType;
    VkComponentTypeNV    CType;
    VkComponentTypeNV    DType;
    VkScopeNV            scope;
} VkCooperativeMatrixPropertiesNV;
  • sType 是一个 VkStructureType 值,用于标识此结构。

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

  • MSize 是矩阵 A、C 和 D 中的行数。

  • KSize 是矩阵 A 中的列数和矩阵 B 中的行数。

  • NSize 是矩阵 B、C、D 中的列数。

  • AType 是矩阵 A 的组件类型,类型为 VkComponentTypeNV

  • BType 是矩阵 B 的组件类型,类型为 VkComponentTypeNV

  • CType 是矩阵 C 的组件类型,类型为 VkComponentTypeNV

  • DType 是矩阵 D 的组件类型,类型为 VkComponentTypeNV

  • scope 是所有矩阵类型的范围,类型为 VkScopeNV

如果某些类型比其他类型更受偏爱(例如,为了性能),它们应该vkGetPhysicalDeviceCooperativeMatrixPropertiesNV 枚举的列表中较早出现。

列表中至少有一个条目的 MSizeKSizeNSize 的所有值必须是 2 的幂。

有效使用(隐式)
  • VUID-VkCooperativeMatrixPropertiesNV-sType-sType
    sType必须VK_STRUCTURE_TYPE_COOPERATIVE_MATRIX_PROPERTIES_NV

  • VUID-VkCooperativeMatrixPropertiesNV-pNext-pNext
    pNext 必须NULL

VkScopeKHR 的可能值包括:

// Provided by VK_KHR_cooperative_matrix
typedef enum VkScopeKHR {
    VK_SCOPE_DEVICE_KHR = 1,
    VK_SCOPE_WORKGROUP_KHR = 2,
    VK_SCOPE_SUBGROUP_KHR = 3,
    VK_SCOPE_QUEUE_FAMILY_KHR = 5,
  // Provided by VK_NV_cooperative_matrix
    VK_SCOPE_DEVICE_NV = VK_SCOPE_DEVICE_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_SCOPE_WORKGROUP_NV = VK_SCOPE_WORKGROUP_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_SCOPE_SUBGROUP_NV = VK_SCOPE_SUBGROUP_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_SCOPE_QUEUE_FAMILY_NV = VK_SCOPE_QUEUE_FAMILY_KHR,
} VkScopeKHR;

或等效值

// Provided by VK_NV_cooperative_matrix
typedef VkScopeKHR VkScopeNV;
  • VK_SCOPE_DEVICE_KHR 对应于 SPIR-V Device 范围。

  • VK_SCOPE_WORKGROUP_KHR 对应于 SPIR-V Workgroup 范围。

  • VK_SCOPE_SUBGROUP_KHR 对应于 SPIR-V Subgroup 范围。

  • VK_SCOPE_QUEUE_FAMILY_KHR 对应于 SPIR-V QueueFamily 范围。

所有枚举值都与相应的 SPIR-V 值匹配。

VkComponentTypeKHR 的可能值包括:

// Provided by VK_KHR_cooperative_matrix
typedef enum VkComponentTypeKHR {
    VK_COMPONENT_TYPE_FLOAT16_KHR = 0,
    VK_COMPONENT_TYPE_FLOAT32_KHR = 1,
    VK_COMPONENT_TYPE_FLOAT64_KHR = 2,
    VK_COMPONENT_TYPE_SINT8_KHR = 3,
    VK_COMPONENT_TYPE_SINT16_KHR = 4,
    VK_COMPONENT_TYPE_SINT32_KHR = 5,
    VK_COMPONENT_TYPE_SINT64_KHR = 6,
    VK_COMPONENT_TYPE_UINT8_KHR = 7,
    VK_COMPONENT_TYPE_UINT16_KHR = 8,
    VK_COMPONENT_TYPE_UINT32_KHR = 9,
    VK_COMPONENT_TYPE_UINT64_KHR = 10,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_FLOAT16_NV = VK_COMPONENT_TYPE_FLOAT16_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_FLOAT32_NV = VK_COMPONENT_TYPE_FLOAT32_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_FLOAT64_NV = VK_COMPONENT_TYPE_FLOAT64_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_SINT8_NV = VK_COMPONENT_TYPE_SINT8_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_SINT16_NV = VK_COMPONENT_TYPE_SINT16_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_SINT32_NV = VK_COMPONENT_TYPE_SINT32_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_SINT64_NV = VK_COMPONENT_TYPE_SINT64_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_UINT8_NV = VK_COMPONENT_TYPE_UINT8_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_UINT16_NV = VK_COMPONENT_TYPE_UINT16_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_UINT32_NV = VK_COMPONENT_TYPE_UINT32_KHR,
  // Provided by VK_NV_cooperative_matrix
    VK_COMPONENT_TYPE_UINT64_NV = VK_COMPONENT_TYPE_UINT64_KHR,
} VkComponentTypeKHR;

或等效值

// Provided by VK_NV_cooperative_matrix
typedef VkComponentTypeKHR VkComponentTypeNV;
  • VK_COMPONENT_TYPE_FLOAT16_KHR 对应于 SPIR-V OpTypeFloat 16。

  • VK_COMPONENT_TYPE_FLOAT32_KHR 对应于 SPIR-V OpTypeFloat 32。

  • VK_COMPONENT_TYPE_FLOAT64_KHR 对应于 SPIR-V OpTypeFloat 64。

  • VK_COMPONENT_TYPE_SINT8_KHR 对应于 SPIR-V OpTypeInt 8 0/1。

  • VK_COMPONENT_TYPE_SINT16_KHR 对应于 SPIR-V OpTypeInt 16 0/1。

  • VK_COMPONENT_TYPE_SINT32_KHR 对应于 SPIR-V OpTypeInt 32 0/1。

  • VK_COMPONENT_TYPE_SINT64_KHR 对应于 SPIR-V OpTypeInt 64 0/1。

  • VK_COMPONENT_TYPE_UINT8_KHR 对应于 SPIR-V OpTypeInt 8 0/1。

  • VK_COMPONENT_TYPE_UINT16_KHR 对应于 SPIR-V OpTypeInt 16 0/1。

  • VK_COMPONENT_TYPE_UINT32_KHR 对应于 SPIR-V OpTypeInt 32 0/1。

  • VK_COMPONENT_TYPE_UINT64_KHR 对应于 SPIR-V OpTypeInt 64 0/1。

验证缓存

验证缓存对象允许重用内部验证的结果,包括在单个应用程序运行期间和多次运行之间。通过在创建受支持的 Vulkan 对象时传递相同的验证缓存对象来实现在单次运行中的重用。通过在一次应用程序运行中检索验证缓存内容、保存内容,并在后续运行中使用它们来预初始化验证缓存来实现跨应用程序运行的重用。验证缓存对象的内容由验证层管理。应用程序可以管理验证缓存对象消耗的主机内存,并控制从验证缓存对象中检索的数据量。

验证缓存对象由 VkValidationCacheEXT 句柄表示。

// Provided by VK_EXT_validation_cache
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkValidationCacheEXT)

要创建验证缓存对象,请调用

// Provided by VK_EXT_validation_cache
VkResult vkCreateValidationCacheEXT(
    VkDevice                                    device,
    const VkValidationCacheCreateInfoEXT*       pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkValidationCacheEXT*                       pValidationCache);
  • device 是创建验证缓存对象的逻辑设备。

  • pCreateInfo 是指向 VkValidationCacheCreateInfoEXT 结构的指针,该结构包含验证缓存对象的初始参数。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

  • pValidationCache 是指向 VkValidationCacheEXT 句柄的指针,将在其中返回结果验证缓存对象。

应用程序可以使用 pAllocator 跟踪和管理验证缓存对象的总主机内存大小。应用程序可以vkGetValidationCacheDataEXT 中限制从验证缓存对象中检索的数据量。实现应该不内部限制添加到验证缓存对象的总条目数或消耗的总主机内存。

创建后,验证缓存可以通过将此对象添加到 VkShaderModuleCreateInfo 结构的 pNext 链传递给 vkCreateShaderModule 命令。如果 VkShaderModuleValidationCacheCreateInfoEXT 对象包含在 VkShaderModuleCreateInfo::pNext 链中,并且其 validationCache 字段不是 VK_NULL_HANDLE,则实现将查询它以寻找可能的重用机会并使用新内容更新它。在这些命令中使用验证缓存对象是内部同步的,并且同一验证缓存对象可以在多个线程中同时使用。

实现应该尽一切努力将任何临界区限制在对缓存的实际访问上,这预计会比 vkCreateShaderModule 命令的持续时间短得多。

有效使用(隐式)
  • VUID-vkCreateValidationCacheEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkCreateValidationCacheEXT-pCreateInfo-parameter
    pCreateInfo 必须是一个指向有效的 VkValidationCacheCreateInfoEXT 结构的有效指针

  • VUID-vkCreateValidationCacheEXT-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkCreateValidationCacheEXT-pValidationCache-parameter
    pValidationCache 必须是一个指向 VkValidationCacheEXT 句柄的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

VkValidationCacheCreateInfoEXT 结构定义如下

// Provided by VK_EXT_validation_cache
typedef struct VkValidationCacheCreateInfoEXT {
    VkStructureType                    sType;
    const void*                        pNext;
    VkValidationCacheCreateFlagsEXT    flags;
    size_t                             initialDataSize;
    const void*                        pInitialData;
} VkValidationCacheCreateInfoEXT;
  • sType 是一个 VkStructureType 值,用于标识此结构。

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

  • flags 保留供将来使用。

  • initialDataSizepInitialData 中的字节数。如果 initialDataSize 为零,则验证缓存最初将为空。

  • pInitialData 是一个指向先前检索的验证缓存数据的指针。如果验证缓存数据与设备不兼容(如下定义),则验证缓存最初将为空。如果 initialDataSize 为零,则忽略 pInitialData

有效用法
  • VUID-VkValidationCacheCreateInfoEXT-initialDataSize-01534
    如果 initialDataSize 不为 0,则它必须等于 pInitialData 的大小,该大小由 vkGetValidationCacheDataEXT 在最初检索 pInitialData 时返回

  • VUID-VkValidationCacheCreateInfoEXT-initialDataSize-01535
    如果 initialDataSize 不为 0,则 pInitialData 必须是从先前调用 vkGetValidationCacheDataEXT 检索的

有效使用(隐式)
  • VUID-VkValidationCacheCreateInfoEXT-sType-sType
    sType 必须VK_STRUCTURE_TYPE_VALIDATION_CACHE_CREATE_INFO_EXT

  • VUID-VkValidationCacheCreateInfoEXT-pNext-pNext
    pNext 必须NULL

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

  • VUID-VkValidationCacheCreateInfoEXT-pInitialData-parameter
    如果 initialDataSize 不为 0,则 pInitialData 必须是指向 initialDataSize 字节数组的有效指针

// Provided by VK_EXT_validation_cache
typedef VkFlags VkValidationCacheCreateFlagsEXT;

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

可以使用以下命令合并验证缓存对象

// Provided by VK_EXT_validation_cache
VkResult vkMergeValidationCachesEXT(
    VkDevice                                    device,
    VkValidationCacheEXT                        dstCache,
    uint32_t                                    srcCacheCount,
    const VkValidationCacheEXT*                 pSrcCaches);
  • device 是拥有验证缓存对象的逻辑设备。

  • dstCache 是要将结果合并到的验证缓存的句柄。

  • srcCacheCountpSrcCaches 数组的长度。

  • pSrcCaches 是指向验证缓存句柄数组的指针,这些句柄将合并到 dstCache 中。合并后,将包括 dstCache 的先前内容。

合并操作的详细信息取决于实现,但实现应该合并指定的验证缓存的内容并修剪重复的条目。

有效用法
  • VUID-vkMergeValidationCachesEXT-dstCache-01536
    dstCache 必须不要出现在源缓存列表中

有效使用(隐式)
  • VUID-vkMergeValidationCachesEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkMergeValidationCachesEXT-dstCache-parameter
    dstCache 必须是一个有效的 VkValidationCacheEXT 句柄

  • VUID-vkMergeValidationCachesEXT-pSrcCaches-parameter
    pSrcCaches 必须是指向 srcCacheCount 个有效 VkValidationCacheEXT 句柄的数组的有效指针

  • VUID-vkMergeValidationCachesEXT-srcCacheCount-arraylength
    srcCacheCount 必须大于 0

  • VUID-vkMergeValidationCachesEXT-dstCache-parent
    dstCache 必须已从 device 创建、分配或检索

  • VUID-vkMergeValidationCachesEXT-pSrcCaches-parent
    pSrcCaches 的每个元素必须已从 device 创建、分配或检索

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

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

可以使用以下命令从验证缓存对象检索数据

// Provided by VK_EXT_validation_cache
VkResult vkGetValidationCacheDataEXT(
    VkDevice                                    device,
    VkValidationCacheEXT                        validationCache,
    size_t*                                     pDataSize,
    void*                                       pData);
  • device 是拥有验证缓存的逻辑设备。

  • validationCache 是要从中检索数据的验证缓存。

  • pDataSize 是指向与验证缓存中的数据量相关的值的指针,如下所述。

  • pData 要么是 NULL,要么是指向缓冲区的指针。

如果 pDataNULL,则在 pDataSize 中返回可以从验证缓存中检索的最大数据大小(以字节为单位)。否则,pDataSize 必须指向应用程序设置为由 pData 指向的缓冲区大小(以字节为单位)的变量,并且在返回时,该变量将被实际写入 pData 的数据量覆盖。如果 pDataSize 小于验证缓存可以检索的最大大小,则最多将 pDataSize 字节写入 pData,并且 vkGetValidationCacheDataEXT 将返回 VK_INCOMPLETE 而不是 VK_SUCCESS,以指示没有返回所有验证缓存。

写入 pData 的任何数据都有效,并且可以作为传递给 vkCreateValidationCacheEXTVkValidationCacheCreateInfoEXT 结构的 pInitialData 成员提供。

除非在两次调用之间调用了修改缓存内容的命令,否则两次使用相同参数调用 vkGetValidationCacheDataEXT 必须检索相同的数据。

应用程序可以存储从验证缓存检索的数据,并使用这些数据(可能在应用程序的将来运行中)来填充新的验证缓存对象。但是,验证的结果可能取决于供应商 ID、设备 ID、驱动程序版本以及设备的其它详细信息。为了使应用程序能够检测到先前检索的数据何时与设备不兼容,写入 pData 的初始字节必须是包含以下成员的标头

表 1. 验证缓存标头版本 VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT 的布局
偏移量 大小 含义

0

4

整个验证缓存标头的长度(以字节为单位),以字节流的形式写入,最小有效字节在前

4

4

一个 VkValidationCacheHeaderVersionEXT 值,以字节流的形式写入,最小有效字节在前

8

VK_UUID_SIZE

一个层提交 ID,以 UUID 的形式表示,唯一标识用于生成这些验证结果的验证层版本。

前四个字节编码整个验证缓存头部的长度,以字节为单位。此值包括头部中的所有字段,包括验证缓存版本字段和长度字段的大小。

接下来的四个字节编码验证缓存版本,如 VkValidationCacheHeaderVersionEXT 所述。验证缓存的消费者应该使用缓存版本来解释缓存头部的其余部分。

如果 pDataSize 小于存储此头部所需的空间,则不会写入任何内容到 pData 中,并且会将零写入到 pDataSize

有效使用(隐式)
  • VUID-vkGetValidationCacheDataEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetValidationCacheDataEXT-validationCache-parameter
    validationCache必须是有效的 VkValidationCacheEXT 句柄

  • VUID-vkGetValidationCacheDataEXT-pDataSize-parameter
    pDataSize 必须是指向 size_t 值的有效指针。

  • VUID-vkGetValidationCacheDataEXT-pData-parameter
    如果 pDataSize 引用的值不为 0,并且 pData 不为 NULL,则 pData 必须是指向 pDataSize 字节数组的有效指针。

  • VUID-vkGetValidationCacheDataEXT-validationCache-parent
    validationCache 必须已从 device 创建、分配或检索。

返回码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_OUT_OF_HOST_MEMORY

  • VK_ERROR_OUT_OF_DEVICE_MEMORY

vkGetValidationCacheDataEXT 返回的头部中第二组四个字节的可能值,编码验证缓存版本,如下所示:

// Provided by VK_EXT_validation_cache
typedef enum VkValidationCacheHeaderVersionEXT {
    VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT = 1,
} VkValidationCacheHeaderVersionEXT;
  • VK_VALIDATION_CACHE_HEADER_VERSION_ONE_EXT 指定验证缓存的版本一。

要销毁验证缓存,请调用:

// Provided by VK_EXT_validation_cache
void vkDestroyValidationCacheEXT(
    VkDevice                                    device,
    VkValidationCacheEXT                        validationCache,
    const VkAllocationCallbacks*                pAllocator);
  • device 是销毁验证缓存对象的逻辑设备。

  • validationCache 是要销毁的验证缓存的句柄。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

有效用法
  • VUID-vkDestroyValidationCacheEXT-validationCache-01537
    如果在创建 validationCache 时提供了 VkAllocationCallbacks,则此处必须提供一组兼容的回调。

  • VUID-vkDestroyValidationCacheEXT-validationCache-01538
    如果在创建 validationCache 时没有提供 VkAllocationCallbacks,则 pAllocator 必须NULL

有效使用(隐式)
  • VUID-vkDestroyValidationCacheEXT-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkDestroyValidationCacheEXT-validationCache-parameter
    如果 validationCache 不是 VK_NULL_HANDLE,则 validationCache 必须是有效的 VkValidationCacheEXT 句柄。

  • VUID-vkDestroyValidationCacheEXT-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkDestroyValidationCacheEXT-validationCache-parent
    如果 validationCache 是一个有效的句柄,它必须已从 device 创建、分配或检索。

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

CUDA 模块

创建 CUDA 模块

CUDA 模块必须包含一些内核代码,并且必须至少公开一个函数入口点。

CUDA 模块由 VkCudaModuleNV 句柄表示。

// Provided by VK_NV_cuda_kernel_launch
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaModuleNV)

要创建 CUDA 模块,请调用:

// Provided by VK_NV_cuda_kernel_launch
VkResult vkCreateCudaModuleNV(
    VkDevice                                    device,
    const VkCudaModuleCreateInfoNV*             pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkCudaModuleNV*                             pModule);
  • device 是创建着色器模块的逻辑设备。

  • pCreateInfo 是指向 VkCudaModuleCreateInfoNV 结构的指针。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

  • pModule 是指向 VkCudaModuleNV 句柄的指针,其中返回生成的 CUDA 模块对象。

创建 CUDA 模块后,应用程序可以创建函数入口点,该入口点必须引用模块中的一个函数。

有效使用(隐式)
  • VUID-vkCreateCudaModuleNV-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkCreateCudaModuleNV-pCreateInfo-parameter
    pCreateInfo 必须是指向有效 VkCudaModuleCreateInfoNV 结构的有效指针。

  • VUID-vkCreateCudaModuleNV-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkCreateCudaModuleNV-pModule-parameter
    pModule 必须是指向 VkCudaModuleNV 句柄的有效指针。

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_INITIALIZATION_FAILED

  • VK_ERROR_OUT_OF_HOST_MEMORY

VkCudaModuleCreateInfoNV 结构的定义如下:

// Provided by VK_NV_cuda_kernel_launch
typedef struct VkCudaModuleCreateInfoNV {
    VkStructureType    sType;
    const void*        pNext;
    size_t             dataSize;
    const void*        pData;
} VkCudaModuleCreateInfoNV;
  • sType 是一个 VkStructureType 值,用于标识此结构。

  • pNext 可以NULL,或者可以是指向扩展此结构的结构的指针。

  • dataSizepData 数组的长度。

  • pData 是指向 CUDA 代码的指针。

有效用法
  • VUID-VkCudaModuleCreateInfoNV-dataSize-09413
    dataSize 必须是传递给 pData 的 PTX 文件或二进制缓存的总字节大小。

有效使用(隐式)
  • VUID-VkCudaModuleCreateInfoNV-sType-sType
    sType 必须VK_STRUCTURE_TYPE_CUDA_MODULE_CREATE_INFO_NV

  • VUID-VkCudaModuleCreateInfoNV-pNext-pNext
    pNext 必须NULL

  • VUID-VkCudaModuleCreateInfoNV-pData-parameter
    pData 必须是指向 dataSize 字节数组的有效指针。

  • VUID-VkCudaModuleCreateInfoNV-dataSize-arraylength
    dataSize 必须大于 0

创建 CUDA 函数句柄

CUDA 函数由 VkCudaFunctionNV 句柄表示。然后,可以使用指向 global 函数的句柄从命令缓冲区发出内核启动(即调度)。请参阅调度 CUDA PTX 内核的命令

// Provided by VK_NV_cuda_kernel_launch
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaFunctionNV)

要创建 CUDA 函数,请调用:

// Provided by VK_NV_cuda_kernel_launch
VkResult vkCreateCudaFunctionNV(
    VkDevice                                    device,
    const VkCudaFunctionCreateInfoNV*           pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkCudaFunctionNV*                           pFunction);
  • device 是创建着色器模块的逻辑设备。

  • pCreateInfo 是指向 VkCudaFunctionCreateInfoNV 结构的指针。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

  • pFunction 是指向 VkCudaFunctionNV 句柄的指针,其中返回生成的 CUDA 函数对象。

有效使用(隐式)
  • VUID-vkCreateCudaFunctionNV-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkCreateCudaFunctionNV-pCreateInfo-parameter
    pCreateInfo 必须是指向有效 VkCudaFunctionCreateInfoNV 结构的有效指针。

  • VUID-vkCreateCudaFunctionNV-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkCreateCudaFunctionNV-pFunction-parameter
    pFunction 必须是指向 VkCudaFunctionNV 句柄的有效指针

返回码
成功
  • VK_SUCCESS

失败
  • VK_ERROR_INITIALIZATION_FAILED

  • VK_ERROR_OUT_OF_HOST_MEMORY

VkCudaFunctionCreateInfoNV 结构定义如下

// Provided by VK_NV_cuda_kernel_launch
typedef struct VkCudaFunctionCreateInfoNV {
    VkStructureType    sType;
    const void*        pNext;
    VkCudaModuleNV     module;
    const char*        pName;
} VkCudaFunctionCreateInfoNV;
  • sType 是一个 VkStructureType 值,用于标识此结构。

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

  • module 是函数所在的 CUDA VkCudaModuleNV 模块。

  • pName 是一个以 null 结尾的 UTF-8 字符串,其中包含此阶段的着色器入口点名称。

有效使用(隐式)
  • VUID-VkCudaFunctionCreateInfoNV-sType-sType
    sType 必须VK_STRUCTURE_TYPE_CUDA_FUNCTION_CREATE_INFO_NV

  • VUID-VkCudaFunctionCreateInfoNV-pNext-pNext
    pNext 必须NULL

  • VUID-VkCudaFunctionCreateInfoNV-module-parameter
    module 必须是有效的 VkCudaModuleNV 句柄

  • VUID-VkCudaFunctionCreateInfoNV-pName-parameter
    pName 必须是以 null 结尾的 UTF-8 字符串

销毁 CUDA 函数

要销毁 CUDA 函数句柄,请调用

// Provided by VK_NV_cuda_kernel_launch
void vkDestroyCudaFunctionNV(
    VkDevice                                    device,
    VkCudaFunctionNV                            function,
    const VkAllocationCallbacks*                pAllocator);
  • device 是销毁函数的逻辑设备。

  • function 是要销毁的 CUDA 函数的句柄。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

有效使用(隐式)
  • VUID-vkDestroyCudaFunctionNV-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkDestroyCudaFunctionNV-function-parameter
    function 必须是有效的 VkCudaFunctionNV 句柄

  • VUID-vkDestroyCudaFunctionNV-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkDestroyCudaFunctionNV-function-parent
    function 必须是从 device 创建、分配或检索的

销毁 CUDA 模块

要销毁 CUDA 着色器模块,请调用

// Provided by VK_NV_cuda_kernel_launch
void vkDestroyCudaModuleNV(
    VkDevice                                    device,
    VkCudaModuleNV                              module,
    const VkAllocationCallbacks*                pAllocator);
  • device 是销毁着色器模块的逻辑设备。

  • module 是要销毁的 CUDA 模块的句柄。

  • pAllocator 控制主机内存分配,如内存分配章节中所述。

有效使用(隐式)
  • VUID-vkDestroyCudaModuleNV-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkDestroyCudaModuleNV-module-parameter
    module 必须是有效的 VkCudaModuleNV 句柄

  • VUID-vkDestroyCudaModuleNV-pAllocator-parameter
    如果 pAllocator 不为 NULL,则 pAllocator 必须是指向有效 VkAllocationCallbacks 结构的有效指针。

  • VUID-vkDestroyCudaModuleNV-module-parent
    module 必须是从 device 创建、分配或检索的

读取 CUDA 模块缓存

上传 PTX 内核代码后,模块会编译代码以生成二进制缓存,其中包含设备执行所需的所有必要信息。 可以读取回此缓存以供以后使用,例如加速进一步执行的初始化。

要获取 CUDA 模块缓存,请调用

// Provided by VK_NV_cuda_kernel_launch
VkResult vkGetCudaModuleCacheNV(
    VkDevice                                    device,
    VkCudaModuleNV                              module,
    size_t*                                     pCacheSize,
    void*                                       pCacheData);
  • device 是销毁函数的逻辑设备。

  • module 是 CUDA 模块。

  • pCacheSize 是一个指针,其中包含要复制到 pCacheData 中的字节数

  • pCacheData 是一个指针,指向要复制二进制缓存的缓冲区

如果 pCacheDataNULL,则二进制缓存的大小(以字节为单位)将返回到 pCacheSize 中。 否则,pCacheSize 必须指向由应用程序设置为缓冲区大小的变量(以字节为单位),该缓冲区由 pCacheData 指向,并且在返回时,变量将被实际写入 pCacheData 的数据量覆盖。如果 pCacheSize 小于二进制着色器代码的大小,则不会向 pCacheData 写入任何内容,并且将返回 VK_INCOMPLETE 而不是 VK_SUCCESS

然后,可以将返回的缓存用于以后初始化 CUDA 模块,方法是在使用 vkCreateCudaModuleNV 时,发送此缓存而不是 PTX 代码。

给定整个编译和验证不是必要的,使用二进制缓存而不是原始 PTX 代码应该显著加快 CUDA 模块的初始化速度。

VkPipelineCache 一样,二进制缓存取决于特定的实现。 应用程序必须假设缓存上传可能在许多情况下失败,因此可能必须准备好在必要时回退到原始 PTX 代码。 通常,如果在从 PTX 生成缓存和使用此缓存之间使用相同的设备驱动程序和架构,则缓存可能会成功。 如果是新的驱动程序版本或使用不同的设备架构,则此缓存可能会失效。

有效使用(隐式)
  • VUID-vkGetCudaModuleCacheNV-device-parameter
    device 必须是有效的 VkDevice 句柄。

  • VUID-vkGetCudaModuleCacheNV-module-parameter
    module 必须是有效的 VkCudaModuleNV 句柄

  • VUID-vkGetCudaModuleCacheNV-pCacheSize-parameter
    pCacheSize 必须是指向 size_t 值的有效指针

  • VUID-vkGetCudaModuleCacheNV-pCacheData-parameter
    如果 pCacheSize 引用的值不是 0,并且 pCacheData 不是 NULL,则 pCacheData 必须是指向 pCacheSize 个字节数组的有效指针

  • VUID-vkGetCudaModuleCacheNV-module-parent
    module 必须是从 device 创建、分配或检索的

返回码
成功
  • VK_SUCCESS

  • VK_INCOMPLETE

失败
  • VK_ERROR_INITIALIZATION_FAILED

限制

CUDA 和 Vulkan 不在相同的配置中使用设备。必须考虑以下限制

  • 无法从 Vulkan 读取或写入全局参数。与 PTX 内核共享资源或发送值的唯一方法是将其作为函数的参数传递。有关更多详细信息,请参见 CUDA 内核和 Vulkan 之间的资源共享

  • 不支持对模块 PTX 外部的函数进行任何调用。

  • Vulkan 禁用了一些着色器/内核异常,这可能会破坏依赖于异常的 CUDA 内核。

  • 提交到 Vulkan 的 CUDA 内核受限于共享内存量,可以从物理功能中查询。它可能小于 CUDA 可以提供的内存量。

  • CUDA 指令级抢占 (CILP) 不起作用。

  • 此扩展中 CUDA 统一内存不起作用。

  • 不支持 CUDA 动态并行性。

  • vk*DispatchIndirect 不可用。