The sequence of descriptor set layouts that can be used by a pipeline is specified in a pipeline layout. Each pipeline object can use up to maxBoundDescriptorSets (see Limits) descriptor sets

Shaders access resources via variables decorated with a descriptor set and binding number that link them to a descriptor in a descriptor set. The shader interface mapping to bound descriptor sets is described in the Shader Resource Interface section

Shaders can also access buffers without going through descriptors by using Physical Storage Buffer Access to access them through 64-bit addresses.

Storage Image

Sampler

Sampled Image

Combined Image Sampler

Uniform Texel Buffer

Storage Texel Buffer

Storage Buffer

Uniform Buffer

Dynamic Uniform Buffer

Dynamic Storage Buffer

Input Attachment

An input attachment (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) is a descriptor type associated with an image resource via an image view that can be used for framebuffer local load operations in fragment shaders.

All image formats that are supported for color attachments (VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) or depth/stencil attachments (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) for a given image tiling mode are also supported for input attachments.

The image subresources for an input attachment must be in a valid image layout in order to access its data in a shader.

VkResult vkCreateDescriptorSetLayout( VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout);

void FVulkanDescriptorSetsLayout::Compile(FVulkanDescriptorSetLayoutMap& DSetLayoutMap)

若干个descriptors被打组包进descriptor set object。一个descriptor set object包含若干个descriptor,descriptor的类型和数量被通过descriptor set layout定义。layout object可以被用于定义每个descriptor对应的memory或者其他资源。layout可以被用于定义descriptor set对应的资源,以及shader resource和shader stage之间的关系

一个descriptor set layout是一个数组,包含0个或者多个descriptor bindings。每个单独的descriptor binding由一个descriptor ype,一个数字表示binding对应的descriptors的数量,可以访问bind的shader stage,一个sampler descriptors数组

该API用于创建一个descriptor set layout object

第一个输入参数,为用于创建descriptor set layout object 的logical device

第二个输入参数,为一个 VkDescriptorSetLayoutCreateInfo 的结构体,用于表明该descriptor set layout object 的属性

第三个输入参数,对应 Memory Allocation 章节介绍的host memory allocation ,是一个指向 VkAllocationCallbacks 结构体的指针

第四个输入参数,用于获取生成的descriptor set layout object

typedef struct VkDescriptorSetLayoutCreateInfo { VkStructureType sType; //当前结构体的类型,必须是 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO const void* pNext; //NULL,或者扩展该结构体的另外一个结构体,必须是NULL 或者 VkDescriptorSetLayoutBindingFlagsCreateInfo VkDescriptorSetLayoutCreateFlags flags; //descriptor set layout 创建时用的属性 uint32_t bindingCount; //pBindings的数量 const VkDescriptorSetLayoutBinding* pBindings; //每个元素必须不同,如果某个元素被设置了 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT ,那么flgas中必须包含 VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT ,且其他所有元素的descriptorType不能是VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC } VkDescriptorSetLayoutCreateInfo;

typedef enum VkDescriptorSetLayoutCreateFlagBits { // Provided by VK_VERSION_1_2 VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 0x00000002, //带有这个标记的descirptor set必须由 带有 VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT 标记的descriptor pool创建。带有这个标记的descriptor set layout可以超过 per-stage和per0pipeline layout的descriptors数量限制。因为 non-UpdateAfterBind 只包含那些不带这个标记的descriptors,而 UpdateAfterBind 才包含所有的descriptors,不过 UpdateAfterBind 的限制比 UpdateAfterBind的限制要宽松 } VkDescriptorSetLayoutCreateFlagBits;

VkDescriptorSetLayoutCreateFlags 是一个 mask用于保存0个或者多个 VkDescriptorSetLayoutCreateFlagBits.

typedef struct VkDescriptorSetLayoutBinding { uint32_t binding; //是该entry的bind number,对应 shader stage 中拥有相同bind number的资源 VkDescriptorType descriptorType; //表明该binding中用到的descriptor的类型 uint32_t descriptorCount; //表明该binding包含的descriptors的数量,在shader中以一个array来访问。如果descriptortype是 VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK (需要开启 inlineUniformBlock feature) ,则 descriptorCount 是该 inline uniform block的尺寸(以bytes为单位,必须是4的倍数,必须小于或者等于 VkPhysicalDeviceInlineUniformBlockProperties ::maxInlineUniformBlockSize)。如果descriptorCount 为0,则该binding entry is reserverd,对应的资源必须不能被任何使用该set layout的pipeline通过这个binding在任何阶段访问 VkShaderStageFlags stageFlags; //表明哪个pipeline shader stage可以访问该binding对应的资源。 如果是 VK_SHADER_STAGE_ALL,则说明所有的shader stage都可以,包括extension定义的additionalstage都可以访问这个资源。如果某个shader stage没有在这里被表明,则在任何使用该layout的pipeline的该stage中都无法访问该resource。不像input attachment只能被fragment shader访问。descriptor binding没有限制,且graphics stage和compute stage都可以使用。如果 descriptorType 为 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,descriptorCount部位0,则 stageFlags 必须为0 或 VK_SHADER_STAGE_FRAGMENT_BIT const VkSampler* pImmutableSamplers; //影响samplers的初始化。如果 descriptorType 包含 VK_DESCRIPTOR_TYPE_SAMPLER 或者 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER。则 pImmutableSamplers 可以被用于初始化 immutable samplers。Immutable samplers 被永久的 bound into the set layout and must not be changed。不允许使用 immutable samplers update VK_DESCRIPTOR_TYPE_SAMPLER 的descriptor,使用 immutable samplers update VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 的descriptor 不会改变 samplers(image view会被update,sampler update则会被ignore)。如果 pImmutableSamplers 不是null,则是一个包含sampler handle的数组,会被copy到set layout中,被用于对应的binding。只有sampler handle被copy,在该set layout 以及用它创建的descriptor pool 和set 最后一次被使用之前sample object必须不能被destroy。如果 pImmutableSamplers 为null,则sampler slots为dynamic,sampler handles必须绑定到使用该layout的descriptor sets上。如果 descriptorType 不是上述的 descriptor,则 pImmutableSamplers 被忽略 } VkDescriptorSetLayoutBinding;

并非0-max bind number都需要定义在pBindings中。没有指定的binding会被认为是:descriptorCount 、 stageFlags 为 zero, descriptorType 为 undefined。然而即使并非所有descriptor bind都被使用, 0-max bind number可能会占用descirptor set layout的内存,而不应该占用descirptor pool的额外内存。

所以 maximum binding number specified 应该尽可能紧凑,来避免内存浪费

typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfo { VkStructureType sType; //当前结构体的类型,必须是 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO const void* pNext; //NULL,或者扩展该结构体的另外一个结构体 uint32_t bindingCount; //0或者 pBindingFlags的数量,如果不是0,则必须等于 VkDescriptorSetLayoutCreateInfo ::bindingCount const VkDescriptorBindingFlags* pBindingFlags; //每个元素对应一个descriptor set layout binding,如果某个元素的 pBindingFlags 包含 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT,则 VkDescriptorSetLayoutCreateInfo::pBindings 的其他元素的 binding必须比该元素小 } VkDescriptorSetLayoutBindingFlagsCreateInfo;

如果bindingCount为0,或者这个结构体没有被包含在 pNext 中,则每个 descriptor set layout binding 对应的 VkDescriptorBindingFlags会被认为是0。否则,VkDescriptorSetLayoutCreateInfo::pBindings[i]的descriptor set layout binding 对应pBindingFlags[i] 的 flags

如果 VkPhysicalDeviceDescriptorIndexingFeatures ::descriptorBindingUniformBufferUpdateAfterBind 没有开启,则拥有 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER descriptor type 的binding必须不能使用 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT

如果 VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingSampledImageUpdateAfterBind 没有开启,则拥有 VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, or VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE descriptor type 的binding必须不能使用 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT

如果 VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingStorageImageUpdateAfterBind 没有开启,则拥有 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE descriptor type 的binding必须不能使用 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT

如果 VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingStorageBufferUpdateAfterBind 没有开启,则拥有 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER descriptor type 的binding必须不能使用 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT

如果 VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingUniformTexelBufferUpdateAfterBind 没有开启,则拥有 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER descriptor type 的binding必须不能使用 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT

如果 VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingStorageTexelBufferUpdateAfterBind 没有开启,则拥有 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER descriptor type 的binding必须不能使用 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT

如果 VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingInlineUniformBlockUpdateAfterBind 没有开启,则拥有 VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK descriptor type 的binding必须不能使用 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT

拥有 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC descriptor type 的binding必须不能使用 VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT

如果 VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingUpdateUnusedWhilePending 没有开启,pBindingFlags 的所有元素的都必须不能使用 VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT

如果 VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingPartiallyBound 没有开启,pBindingFlags 的所有元素的都必须不能使用 VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT

如果 VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingVariableDescriptorCount 没有开启,pBindingFlags 的所有元素的都必须不能使用 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT

如果一个元素的 pBindingFlags 为 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT ,则该元素的 descriptorType 必须不能是 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC

// Provided by VK_VERSION_1_2 typedef enum VkDescriptorBindingFlagBits { VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 0x00000001, //表明,对应的descriptor在被bound到commandbuffer之后,以及command buffer被提交到queue之前,可以update,submission酱食用最近一次修改的descriptor,且这次update不会invalidate该command buffer。该 Descriptor bindings 将被豁免与 vkUpdateDescriptorSets 要求的显示同步。若干个被标记了这个flag的descriptor可以同时在多个线程被update,而一个descritpor不能同时被2个thread update。当 set 在另一个线程被绑定到 command buffer的时候可以同时更新descriptor ,但是当set被reset或者free的时候,不能同时更新。 VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 0x00000002, //indicates that descriptors in this binding can be updated after a command buffer has bound this descriptor set, or while a command buffer that uses this descriptor set is pending execution, as long as the descriptors that are updated are not used by those command buffers. If VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT is also set, then descriptors can be updated as long as they are not dynamically used by any shader invocations. If VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT is not set, then descriptors can be updated as long as they are not statically used by any shader invocations. VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 0x00000004, //indicates that descriptors in this binding that are not dynamically used need not contain valid descriptors at the time the descriptors are consumed. A descriptor is dynamically used if any shader invocation executes an instruction that performs any memory access using the descriptor. VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 0x00000008, //indicates that this is a variable-sized descriptor binding whose size will be specified when a descriptor set is allocated using this layout. The value of descriptorCount is treated as an upper bound on the size of the binding. This must only be used for the last binding in the descriptor set layout (i.e. the binding with the largest value of binding). For the purposes of counting against limits such as maxDescriptorSet* and maxPerStageDescriptor*, the full value of descriptorCount is counted, except for descriptor bindings with a descriptor type of VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK. In this case, descriptorCount specifies the upper bound on the byte size of the binding; thus it counts against the maxInlineUniformTotalSize limit instead. } VkDescriptorBindingFlagBits;

Note that while VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT and VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT both involve updates to descriptor sets after they are bound, VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT is a weaker requirement since it is only about descriptors that are not used, whereas VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT requires the implementation to observe updates to descriptors that are used.

VkDescriptorBindingFlags是一个 mask用于保存0个或者多个 VkDescriptorBindingFlagBits.

可能会出现的错误:VK_ERROR_OUT_OF_HOST_MEMORY、VK_ERROR_OUT_OF_DEVICE_MEMORY

void vkGetDescriptorSetLayoutSupport( VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, VkDescriptorSetLayoutSupport* pSupport);

void vkDestroyDescriptorSetLayout( VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator);

FVulkanPipelineStateCacheManager::~FVulkanPipelineStateCacheManager()

pipeline通过pipeline layout访问descriptor sets。若干个descriptor set layout和若干个push constant ranges组合在一起成为一个pipeline layout object,用于描述pipeline可以访问的完整版resources。pipeline layout包含一系列descriptor set,每个都有自己的layout。这些layout用来表示shader stage和shader resource之间的关联。pipeline是通过pipeline layout创建

VkResult vkCreatePipelineLayout( VkDevice const VkPipelineLayoutCreateInfo* const VkAllocationCallbacks* VkPipelineLayout* device, pCreateInfo, pAllocator, pPipelineLayout);

void FVulkanLayout::Compile(FVulkanDescriptorSetLayoutMap& DSetLayoutMap)

该API用于创建一个pipeline layout

第一个输入参数,为用于创建pipeline layout 的logical device

第二个输入参数,为一个 VkPipelineLayoutCreateInfo 的结构体,用于表明该pipeline layout object 的属性

第三个输入参数,对应 Memory Allocation 章节介绍的host memory allocation ,是一个指向 VkAllocationCallbacks 结构体的指针

第四个输入参数,用于获取生成的pipeline layout object

typedef struct VkPipelineLayoutCreateInfo { VkStructureType sType; //当前结构体的类型,必须是 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO const void* pNext; //NULL,或者扩展该结构体的另外一个结构体,必须是NULL VkPipelineLayoutCreateFlags flags; //暂未使用,必须为 0 uint32_t setLayoutCount; //该pipeline layout中包含的descriptor sets的数量,必须小于等于 VkPhysicalDeviceLimits ::maxBoundDescriptorSets const VkDescriptorSetLayout* pSetLayouts; //一个包含若干 VkDescriptorSetLayout object的数组 uint32_t pushConstantRangeCount; /该pipeline layout中包含的push constant ranges的数量 const VkPushConstantRange* pPushConstantRanges; //使用一个包含 VkPushConstantRange 结构体的数组,表明pipeline layout中会用到的push constant ranges。和descriptor set layout一样,pipeline layout可以用于指明pipeline 中的每个stage可以访问多少个push constants } VkPipelineLayoutCreateInfo;

push constants提供一种告诉修改pipeline中constant data的方式(胜过memory-backed resource updates)

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_SAMPLER and VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxPerStageDescriptorSamplers

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER and VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxPerStageDescriptorUniformBuffers

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_BUFFER and VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxPerStageDescriptorStorageBuffers

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits ::maxPerStageDescriptorSampledImages

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxPerStageDescriptorStorageImages

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits ::maxPerStageDescriptorInputAttachments

The total number of bindings in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceInlineUniformBlockProperties::maxPerStageDescriptorInlineUniformBlocks

The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_SAMPLER and VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageDescriptorUpdateAfterBindSamplers

The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER and VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties ::maxPerStageDescriptorUpdateAfterBindUniformBuffers

The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_BUFFER and VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties ::maxPerStageDescriptorUpdateAfterBindStorageBuffers

The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageDescriptorUpdateAfterBindSampledImages

The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties ::maxPerStageDescriptorUpdateAfterBindStorageImages

The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageDescriptorUpdateAfterBindInpu tAttachments

The total number of bindings with a descriptorType of VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceInlineUniformBlockProperties::maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_SAMPLER and VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxDescriptorSetSamplers

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits ::maxDescriptorSetUniformBuffers

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits ::maxDescriptorSetUniformBuffersDynamic

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits ::maxDescriptorSetStorageBuffers

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits ::maxDescriptorSetStorageBuffersDynamic

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits ::maxDescriptorSetSampledImages

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxDescriptorSetStorageImages

The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits ::maxDescriptorSetInputAttachments

The total number of bindings in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceInlineUniformBlockProperties::maxDescriptorSetInlineUniformBlocks

The total number of descriptors of the type VK_DESCRIPTOR_TYPE_SAMPLER and VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindSamplers

The total number of descriptors of the type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties ::maxDescriptorSetUpdateAfterBindUniformBuffers

The total number of descriptors of the type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties ::maxDescriptorSetUpdateAfterBindUniformBuffersDynamic

The total number of descriptors of the type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties ::maxDescriptorSetUpdateAfterBindStorageBuffers

The total number of descriptors of the type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties ::maxDescriptorSetUpdateAfterBindStorageBuffersDynamic

The total number of descriptors of the type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties ::maxDescriptorSetUpdateAfterBindSampledImages

The total number of descriptors of the type VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindStorageImages

The total number of descriptors of the type VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingProperties ::maxDescriptorSetUpdateAfterBindInputAttachments

The total number of bindings with a descriptorType of VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceInlineUniformBlockProperties::maxDescriptorSetUpdateAfterBindInlineUni formBlocks

Any two elements of pPushConstantRanges must not include the same stage in stageFlags

typedef struct VkPushConstantRange { VkShaderStageFlags stageFlags; //表明访问push constants的shader stage,这里没有覆盖的shader stage如果访问该范围内的push constants,会得到undefined,是 combination of VkShaderStageFlagBits ,不能为 0 uint32_t offset; //start offset,必须是4的倍数,必须小于 VkPhysicalDeviceLimits::maxPushConstantsSize uint32_t size; //必须大于0,且是4的倍数,必须小鱼等于 VkPhysicalDeviceLimits::maxPushConstantsSize - offset } VkPushConstantRange;

layout of the push constant在shader中被定义。

pipeline layout将被用于创建pipeline,用于绑定descriptor set和push constants。在创建pipeline的时候,使用pipeline layout作为输入,该layout用于map(set、binding、arrayElement)descriptor set中的资源或者memory location。资源assignment依赖于pipeline layout中的descriptor set,而非shader 代码

pipeline中shader statically used的resource variable必须使用(set、binding、arrayElement)在对应的descriptor set layout中声明,还要有对应的descriptor type,以及stageflag中生命所对应的shader stage。pipeline layout中可以包含该pipeline用不到的entries,或者是shader中的dead code。pipeline layout可以被多个pipeline共用,这样的话implementation可能可以通过减少reprogramming the binding的方式减少switch pipeline带来的消耗

类似的,the push constant block declared in each shader (if present) must only place variables at offsets that are each included in a push constant range with stageFlags including the bit corresponding to the shader stage that uses it. pipeline layout也可以包含该pipeline不用的range,或者shader dead-code中包含的变量

Pipeline Layout Resource Limits中展示了一个pipeline layout中所有descriptor set layout中每个类型的total number limit。左侧的 Total Resources Available 列表示pipeline layout中所有descriptor set中每个类型的number limit,一些类型可能有多个limit。每个pipeline stage所能接受的每个类型的number limit需要参考 shader resource limits表格

    	Total Resources Available:maxDescriptorSetSamplers or maxDescriptorSetUpdateAfterBindSamplers
    	Resource Types:sampler、combined image sampler

    	Total Resources maxDescriptorSetSampledImages or maxDescriptorSetUpdateAfterBindSampledImages
    	Resource Types:sampled image、combined image sampler、uniform texel buffer

    	Total Resources Available:maxDescriptorSetStorageImages or maxDescriptorSetUpdateAfterBindStorageImages
    	Resource Types:storage image、storage texel buffer

    	Total Resources Available:maxDescriptorSetUniformBuffers or maxDescriptorSetUpdateAfterBindUniformBuffers
    	Resource Types:uniform buffer、uniform buffer dynamic

    	Total Resources Available:maxDescriptorSetUniformBuffersDynamic or maxDescriptorSetUpdateAfterBindUniformBuffersDynamic
    	Resource Types:uniform buffer dynamic

    	Total Resources Available:maxDescriptorSetStorageBuffers or maxDescriptorSetUpdateAfterBindStorageBuffers
    	Resource Types:storage buffer、storage buffer dynamic

    	Total Resources Available:maxDescriptorSetStorageBuffersDynamic or maxDescriptorSetUpdateAfterBindStorageBuffersDynamic
    	Resource Types:storage buffer dynamic

    	Total Resources Available:maxDescriptorSetInputAttachments or maxDescriptorSetUpdateAfterBindInputAttachments
    	Resource Types:input attachment

    	Total Resources Available:maxDescriptorSetInlineUniformBlocks or maxDescriptorSetUpdateAfterBindInlineUniformBl ocks
    	Resource Types:inline uniform block
    

可能会出现的错误:VK_ERROR_OUT_OF_HOST_MEMORY、VK_ERROR_OUT_OF_DEVICE_MEMORY

void vkDestroyPipelineLayout( VkDevice VkPipelineLayout const VkAllocationCallbacks* device, pipelineLayout, pAllocator);

Place the least frequently changing descriptor sets near the start of the pipeline layout, and place the descriptor sets representing the most frequently changing resources near the end. When pipelines are switched, only the descriptor set bindings that have been invalidated will need to be updated and the remainder of the descriptor set bindings will remain in place.

VkResult vkCreateDescriptorPool( VkDevice const VkDescriptorPoolCreateInfo* const VkAllocationCallbacks* VkDescriptorPool* device, pCreateInfo, pAllocator, pDescriptorPool);

FVulkanDescriptorPool::FVulkanDescriptorPool(FVulkanDevice* InDevice, const FVulkanDescriptorSetsLayout& InLayout, uint32 MaxSetsAllocations)

FVulkanGenericDescriptorPool::FVulkanGenericDescriptorPool(FVulkanDevice* InDevice, uint32 InMaxDescriptorSets)

void vkDestroyDescriptorPool( VkDevice VkDescriptorPool const VkAllocationCallbacks* device, descriptorPool, pAllocator);

FVulkanDescriptorPool::~FVulkanDescriptorPool()

FVulkanGenericDescriptorPool::~FVulkanGenericDescriptorPool()

When a pool is destroyed, all descriptor sets allocated from the pool are implicitly freed and become invalid. Descriptor sets allocated from a given pool do not need to be freed before destroying that descriptor pool.

VkResult vkAllocateDescriptorSets( VkDevice const VkDescriptorSetAllocateInfo* VkDescriptorSet* device, pAllocateInfo, pDescriptorSets);

该API用于通过一个已经存在的 descriptor pool创建一个Descriptor sets,类型为 VkDescriptorSet

		 // Provided by VK_VERSION_1_0
  VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet)
	

第一个输入参数,为拥有 descriptor pool 的logical device

第二个输入参数,为一个 VkDescriptorSetAllocateInfo 的结构体,用于表明该Descriptor sets 的属性

第三个输入参数,用于获取生成的 Descriptor sets。必须是一个指向 个 VkDescriptorSet 元素的数组指针。每个被创建的 descriptor set 的初始状态大多为 uninitialized ,以及所有的descriptor都是 undefined。当对应的resource被destoryed的时候 Descriptor 将会变成undefined。 包含 undefined descriptors 的 Descriptor sets在如下条件下也可以被bound和使用

typedef struct VkCommandBufferAllocateInfo { VkStructureType sType; //当前结构体的类型,必须是 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO const void* pNext; //NULL,或者扩展该结构体的另外一个结构体,必须是NULL VkCommandPool commandPool; //用于分配command buffer的command pool VkCommandBufferLevel level; //是一个 VkCommandBufferLevel 数值,用于指定 command buffer的level uint32_t commandBufferCount; //从command pool中分配出来command buffers的数量,必须大于0 } VkCommandBufferAllocateInfo;

typedef enum VkCommandBufferLevel { VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0, //指定一个primary command buffer VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1, //指定一个secondary command buffer } VkCommandBufferLevel;

该API可以创建多个command buffers。如果任何一个command buffer创建失败,则必须free通过该api已经成功创建的其它command buffers,并将pCommandBuffers数组设置为NULL,并返回错误信息。

可能会出现的错误:VK_ERROR_OUT_OF_HOST_MEMORY、VK_ERROR_OUT_OF_DEVICE_MEMORY

在CTS中的使用:vkAllocateCommandBuffers(context.device, &cmd_buf_info, &per_frame.primary_command_buffer);

		Host access to pAllocateInfo->commandPool must be externally synchronized
	

bool FVulkanDescriptorPool::AllocateDescriptorSets(const VkDescriptorSetAllocateInfo& InDescriptorSetAllocateInfo, VkDescriptorSet* OutSets)

bool FVulkanGenericDescriptorPool::AllocateDescriptorSet(VkDescriptorSetLayout Layout, VkDescriptorSet& OutSet)

VkResult vkFreeDescriptorSets( VkDevice VkDescriptorPool uint32_t const VkDescriptorSet* device, descriptorPool, descriptorSetCount, pDescriptorSets);

VkResult vkResetDescriptorPool( VkDevice VkDescriptorPool VkDescriptorPoolResetFlags device, descriptorPool, flags);

void FVulkanDescriptorPool::Reset()

void FVulkanGenericDescriptorPool::Reset()

Resetting a descriptor pool recycles all of the resources from all of the descriptor sets allocated from the descriptor pool back to the descriptor pool, and the descriptor sets are implicitly freed.

void vkUpdateDescriptorSets( VkDevice uint32_t const VkWriteDescriptorSet* uint32_t const VkCopyDescriptorSet* device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);

bool FVulkanDescriptorSetCache::FCachedPool::CreateDescriptorSets(const FVulkanDSetsKey& DSetsKey, const FVulkanDescriptorSetsLayout& SetsLayout,

bool FVulkanComputePipelineDescriptorState::InternalUpdateDescriptorSets(FVulkanCommandListContext* CmdListContext, FVulkanCmdBuffer* CmdBuffer)

bool FVulkanGraphicsPipelineDescriptorState::InternalUpdateDescriptorSets(FVulkanCommandListContext* CmdListContext, FVulkanCmdBuffer* CmdBuffer)

Descriptor Update Templates

Updating a large VkDescriptorSet array can be an expensive operation since an application must specify one VkWriteDescriptorSet structure for each descriptor or descriptor array to update, each of which re-specifies the same state when updating the same descriptor in multiple descriptor sets. For cases when an application wishes to update the same set of descriptors in multiple descriptor sets allocated using the same VkDescriptorSetLayout, vkUpdateDescriptorSetWithTemplate can be used as a replacement for vkUpdateDescriptorSets.

VkDescriptorUpdateTemplate allows implementations to convert a set of descriptor update operations on a single descriptor set to an internal format that, in conjunction with vkUpdateDescriptorSetWithTemplate , can be more efficient compared to calling vkUpdateDescriptorSets . The descriptors themselves are not specified in the VkDescriptorUpdateTemplate, rather, offsets into an application provided pointer to host memory are specified, which are combined with a pointer passed to vkUpdateDescriptorSetWithTemplate . This allows large batches of updates to be executed without having to convert application data structures into a strictly-defined Vulkan data structure.

Descriptor Set Updates with Templates

VkResult vkCreateDescriptorUpdateTemplate( VkDevice device, const VkDescriptorUpdateTemplateCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorUpdateTemplate* pDescriptorUpdateTemplate);

void vkDestroyDescriptorUpdateTemplate( VkDevice VkDescriptorUpdateTemplate const VkAllocationCallbacks* device, descriptorUpdateTemplate, pAllocator);

void vkUpdateDescriptorSetWithTemplate( VkDevice VkDescriptorSet VkDescriptorUpdateTemplate const void* device, descriptorSet, descriptorUpdateTemplate, pData);

void vkCmdBindDescriptorSets( VkCommandBuffer VkPipelineBindPoint VkPipelineLayout uint32_t uint32_t const VkDescriptorSet* uint32_t const uint32_t* commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);

inline void Bind(VkCommandBuffer CmdBuffer, VkPipelineLayout PipelineLayout, VkPipelineBindPoint BindPoint)

Push constants represent a high speed path to modify constant data in pipelines that is expected to outperform memory-backed resource updates.

void vkCmdPushConstants( VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues);

Physical Storage Buffer Access

To query a 64-bit buffer device address value through which buffer memory can be accessed in a shader

VkDeviceAddress vkGetBufferDeviceAddress( VkDevice device, const VkBufferDeviceAddressInfo* pInfo);

To query a 64-bit buffer opaque capture address

uint64_t vkGetBufferOpaqueCaptureAddress( VkDevice device, const VkBufferDeviceAddressInfo* pInfo);

本节教程就到此结束,希望大家继续阅读我之后的教程。

谢谢大家,再见!


原创技术文章,撰写不易,转载请注明出处:电子设备中的画家|王烁 于 2021 年 5 月 10 日发表,原文链接(http://geekfaner.com/shineengine/blog24_Vulkanv1.2_10.html)