Vulkan Specification(Vulkan规范):第十三章 13.1 描述符类型

13.1. 描述符类型

如下几个小节简单讲解Vulkan支持的各种描述符类型。 每一小节定义了一种描述符类型,每一种类型在着色器语言和SPIR-V中都有详细讲解。 描述符类型和着色器语言中不透明类型的类别大多数情况下是一对一的,着色器语言中不透明类型必须指代 对应描述符类型的管线布局中的一个描述符。 但是,对于此规则,如下情形是一个例外 Combined Image Sampler

13.1.1. 存储图像

一个 storage image (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) 是一种描述符类型, 用于绑定到管线的着色器内部 对图像的装载、存储和原子操作。

从 storage images 中装载并不会使用采样器,且是unfiltered,并不支持 坐标折叠与截断。vkGetPhysicalDeviceFormatProperties 指定的 VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT 支持的图像格式都能在所有的着色器阶段中载入。

VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT 格式图像可以在计算着色器中 存储到 storage images 。

VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT 格式的图像可以支持在计算着色器中进行原子操作。

storage images 上的载入与存储操作,只能在 VK_IMAGE_LAYOUT_GENERAL 布局的图像上进行。

fragmentStoresAndAtomics 特征被启用,那么就可支持 对同一集合的图像格式的storage images 在 片元着色器阶段内执行 存储和原子操作。 当 vertexPipelineStoresAndAtomics 特征被启用时, 那么对 计算着色器阶段受支持的图像格式,同样也支持在顶点、细分、几何着色器阶段进行 存储和原子操作。

在着色器内,若变量被用于原子操作,Storage image 声明必须指定图像格式。

若 shaderStorageImageReadWithoutFormat 特征没有被启用,在着色器内,若变量被用于载入操作, storage image 声明必须指定图像格式。

若 shaderStorageImageWriteWithoutFormat 特征没有被启用,在着色器内,若变量被用于存储操作, storage image 声明必须指定图像格式。

Storage images 在GLSL着色器源代码中使用 uniform image 声明一个变量为合适的维度,同样与指定格式布局描述:

GLSL example

layout (set=m, binding=n, r32f) uniform image2D myStorageImage;

SPIR-V example

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "myStorageImage"
               OpDecorate %9 DescriptorSet m
               OpDecorate %9 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 2D 0 0 0 2 R32f
          %8 = OpTypePointer UniformConstant %7
          %9 = OpVariable %8 UniformConstant
               ...

13.1.2. 采样器

一个 sampler (VK_DESCRIPTOR_TYPE_SAMPLER) 代表一系列的参数,它控制了寻址计算,过滤行为,和其他的属性, 这可以被用于执行从一个 采样过的图像 进行过滤加载(参考 采样的图像)。

采样器时在GLSL着色器代码中使用 uniform sampler 来声明的变量,采样器类型并没有关联的纹理维度:

GLSL Example

layout (set=m, binding=n) uniform sampler mySampler;

SPIR-V example

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %8 "mySampler"
               OpDecorate %8 DescriptorSet m
               OpDecorate %8 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeSampler
          %7 = OpTypePointer UniformConstant %6
          %8 = OpVariable %7 UniformConstant
               ...

13.1.3. 采样的图像

一个 采样的图像 (VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) 可以: 被用于从采样过的图像数据中提取数据 (通常联合使用一个采样器)。 着色器使用一个采样的图像handle,与 一个采样器handle来采样数据,图像handle通常定义里内存的 形状和格式,采样器通常定义了如何进行坐标系寻址。 同一个采样器可以被用于对多个图像,且可以使用多个采样器对同一个采样的图像进行采样,每一个都包含不同的采样参数。

采样的图像在GLSL着色器源代码中使用uniform texture 变量来声明,有合适维度:

GLSL example

layout (set=m, binding=n) uniform texture2D mySampledImage;

SPIR-V example

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "mySampledImage"
               OpDecorate %9 DescriptorSet m
               OpDecorate %9 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
          %8 = OpTypePointer UniformConstant %7
          %9 = OpVariable %8 UniformConstant
               ...

13.1.4. 联合图像采样器

一个 combined image sampler (VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 代表一个采样的图像,且带有一些采样参数。在逻辑上,他被认为是一个采样的图像,且绑定了一个采样器。

 

注意

在一些Vulkan实现上,可能: 使用采样器与采样的图像结合的方式从图像中采样可能更高效,采样器与采样的图像存储在联合的描述中的描述符集合。

在着色器源代码中使用 合适维度的 uniform sampler 变量 来声明 联合图像采样器:

GLSL example

layout (set=m, binding=n) uniform sampler2D myCombinedImageSampler;

SPIR-V example

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %10 "myCombinedImageSampler"
               OpDecorate %10 DescriptorSet m
               OpDecorate %10 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
          %8 = OpTypeSampledImage %7
          %9 = OpTypePointer UniformConstant %8
         %10 = OpVariable %9 UniformConstant
               ...

VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 描述符集合的入口 也可以 通过单独的采样器和采样图像着色器变量 来 访问。 此种变量指除了 描述中对应的一半,可以在着色器中与采样器或者采样的描述符联合,可以在着色器中与采样器或采样的图像联合,该图像来自于 同一个描述符,或者来自其他联合或独立描述符类型的同一个描述符。 在独立的采样器或采样的图像变量如何被使用来从一个联合描述符转换到另一个时,并不存在额外的限制条件。

13.1.5. 统一纹素缓冲区

一个 uniform texel buffer (VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) 代表一个紧致压缩的同构格式数据的数组,存储在一个缓冲区,且可被着色器访问。统一纹素缓冲区是只读的。

可在GLSL源代码中使用 统一samplerBuffer变量 声明统一纹素缓冲区: .GLSL example

layout (set=m, binding=n) uniform samplerBuffer myUniformTexelBuffer;

SPIR-V example

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %10 "myUniformTexelBuffer"
               OpDecorate %10 DescriptorSet m
               OpDecorate %10 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 Buffer 0 0 0 1 Unknown
          %8 = OpTypeSampledImage %7
          %9 = OpTypePointer UniformConstant %8
         %10 = OpVariable %9 UniformConstant
               ...

13.1.6. 仓库纹素缓冲区

一个 storage texel buffer (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER) 代表一个紧致压缩的同构格式数据数组,被存储在一个缓冲区,且着色器可访问。 仓库纹素缓冲区与 统一纹素缓冲区不同点在于它们支持存储和 着色器内原子操作,也支持不同的最大长度,亦可有不同的性能特征。

在GLSL源代码中,可使用统一imageBuffer变量来声明 仓储纹素缓冲区:

GLSL example

layout (set=m, binding=n, r32f) uniform imageBuffer myStorageTexelBuffer;

SPIR-V example

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "myStorageTexelBuffer"
               OpDecorate %9 DescriptorSet m
               OpDecorate %9 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 Buffer 0 0 0 2 R32f
          %8 = OpTypePointer UniformConstant %7
          %9 = OpVariable %8 UniformConstant
               ...

13.1.7. 统一缓冲区

一个 uniform buffer (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) 是一个结构化的存储区域, 对于着色器程序而言只能够只读访问。 它通常被用来初春中等字节大小的常量述祖,例如着色器参数,矩阵,其他相关的数据。

可在GLSL着色器源代码中使用 统一存储描述符和block语法来声明 统一缓冲区:

GLSL example

layout (set=m, binding=n) uniform myUniformBuffer
{
    vec4 myElement[32];
};

SPIR-V example

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %11 "myUniformBuffer"
               OpMemberName %11 0 "myElement"
               OpName %13 ""
               OpDecorate %10 ArrayStride 16
               OpMemberDecorate %11 0 Offset 0
               OpDecorate %11 Block
               OpDecorate %13 DescriptorSet m
               OpDecorate %13 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeVector %6 4
          %8 = OpTypeInt 32 0
          %9 = OpConstant %8 32
         %10 = OpTypeArray %7 %9
         %11 = OpTypeStruct %10
         %12 = OpTypePointer Uniform %11
         %13 = OpVariable %12 Uniform
               ...

13.1.8. 存储缓冲区

一个 storage buffer (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 是一个结构化存储的区域, 他支持着色器的读写访问。 除了常规读写操作,存储缓冲区的一些成员可被用于原子操作的对象。 总的来说,原子操作通常只支持有无符号整型格式的成员。

可在GLSL着色器源代码中使用缓冲区存储描述符和block语法来声明存储缓冲区:

GLSL example

layout (set=m, binding=n) buffer myStorageBuffer
{
    vec4 myElement[];
};

SPIR-V example

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "myStorageBuffer"
               OpMemberName %9 0 "myElement"
               OpName %11 ""
               OpDecorate %8 ArrayStride 16
               OpMemberDecorate %9 0 Offset 0
               OpDecorate %9 BufferBlock
               OpDecorate %11 DescriptorSet m
               OpDecorate %11 Binding n
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeVector %6 4
          %8 = OpTypeRuntimeArray %7
          %9 = OpTypeStruct %8
         %10 = OpTypePointer Uniform %9
         %11 = OpVariable %10 Uniform
               ...

13.1.9. 动态统一缓冲区

一个 dynamic uniform buffer (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) 与统一缓冲区的唯一区别在于它的地址与长度是如何被指定的。 统一缓冲区与一个缓冲区地址绑定,长度在描述符集合更新的缓冲区handle、偏移与区间来指定(参考 Descriptor Set Updates)。 使用动态统一缓冲区指定缓冲区句柄、偏移量和范围 在描述符集中定义基本地址和长度。 相对于这个基础地址的动态偏移是从pDynamicOffsets 参数取出到 vkCmdBindDescriptorSets (参考 Descriptor Set Binding)。 用于动态统一缓冲区的地址是缓冲区base 地址和相对偏移之和。 长度未被改变,且保持区间为描述符更新中指定的大小。 动态缓冲区着色器语法和统一缓冲区一样。

13.1.10. 动态仓储缓冲区

一个 dynamic storage buffer (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) 与仓储缓冲区的唯一不同点是它的地址与长度是如何被指定的。 不同之处和统一缓冲区与动态缓冲区之间的差别是一样的(参考 Dynamic Uniform Buffer). 动态仓储缓冲区着色器语法和仓储缓冲区的一样。

13.1.11. 输入附件

一个 input attachment (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) 是一个图像时图,可以被用于 绑定到管线的片元着色器内像素局部载入操作。 从输入附件中载入的内容是unfiltered。 对于一个给定图像的tiling模式 的颜色附件(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)或者深度/stencil (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) 附件支持的所有图像格式 都为输入附件所支持。

在着色器内,除了描述符集合和绑定数量,输入附件必须 被它们的输入附件所引所描述。

GLSL example

layout (input_attachment_index=i, set=m, binding=n) uniform subpassInput myInputAttachment;

SPIR-V example

               ...
          %1 = OpExtInstImport "GLSL.std.450"
               ...
               OpName %9 "myInputAttachment"
               OpDecorate %9 DescriptorSet m
               OpDecorate %9 Binding n
               OpDecorate %9 InputAttachmentIndex i
          %2 = OpTypeVoid
          %3 = OpTypeFunction %2
          %6 = OpTypeFloat 32
          %7 = OpTypeImage %6 SubpassData 0 0 0 2 Unknown
          %8 = OpTypePointer UniformConstant %7
          %9 = OpVariable %8 UniformConstant
               ...

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值