图像操作

图像操作概述

Vulkan 图像操作是由那些使用 OpTypeImage(表示 VkImageView)或 OpTypeSampledImage(表示(VkImageViewVkSampler)对)的 SPIR-V 图像指令执行的操作。读取、写入和原子操作也使用纹理坐标作为操作数,并根据图像内纹理元素(纹素)的邻域返回一个值。查询操作返回绑定的图像或查找本身的属性。OpTypeImage 的“深度”操作数被忽略。

纹素是纹理和元素这两个词的组合。早期的交互式计算机图形支持纹理上的纹理操作,这是此处描述的图像上的一小部分图像操作。离散样本仍然基本等效,因此我们保留历史术语纹素来指代它们。

图像操作包括以下 SPIR-V 图像指令的功能

  • OpImageSample*OpImageSparseSample* 读取图像的一个或多个相邻纹素,并根据采样器的状态过滤纹素值。

    • 名称中带有 ImplicitLod 的指令确定采样操作中使用的 LOD,该 LOD 基于相邻片段中使用的坐标。

    • 名称中带有 ExplicitLod 的指令确定采样操作中使用的 LOD,该 LOD 基于附加坐标。

    • 名称中带有 Proj 的指令将同质投影应用于坐标。

  • OpImageFetchOpImageSparseFetch 返回图像的单个纹素。不使用采样器。

  • OpImage*GatherOpImageSparse*Gather 读取相邻的纹素,并返回每个纹素的单个分量

  • OpImageRead(和 OpImageSparseRead)和 OpImageWrite 分别读取和写入图像中的纹素。不使用采样器。

  • OpImageSampleFootprintNV 识别并返回有关与等效的 OpImageSample* 指令将访问的图像中的纹素集的信息。

  • OpImage*Dref* 指令在纹素值上应用深度比较

  • OpImageSparse* 指令还会返回一个稀疏驻留代码。

  • OpImageQuerySizeOpImageQuerySizeLodOpImageQueryLevelsOpImageQuerySamples 返回将被访问的图像描述符的属性。不会访问图像本身。

  • OpImageQueryLod 返回将在采样操作中使用的 LOD 参数。不执行实际操作。

  • OpImageWeightedSampleQCOM 读取纹素的 2D 邻域,并使用来自单独的权重纹理的权重值计算加权平均值。

  • opImageBlockMatchSADQCOMopTextureBlockMatchSSD 比较来自两个纹理的纹素的 2D 邻域。

  • OpImageBoxFilterQCOM 读取纹素的 2D 邻域,并计算纹素的加权平均值。

  • opImageBlockMatchWindowSADQCOMopImageBlockMatchWindowSSDQCOM 比较来自两个纹理的纹素的 2D 邻域,并在目标纹理的窗口区域中重复比较。

  • opImageBlockMatchGatherSADQCOMopImageBlockMatchWindowSSDQCOM 将目标纹理中的四个 2D 纹素邻域与参考纹理中的单个 2D 邻域进行比较。每个比较的 R 分量被收集并返回到输出中。

纹素坐标系

图像通过纹素坐标寻址。有三种纹素坐标系

  • 归一化纹素坐标 [0.0, 1.0]

  • 未归一化纹素坐标 [0.0, 宽度 / 高度 / 深度)

  • 整数纹素坐标 [0, 宽度 / 高度 / 深度)

SPIR-V OpImageFetchOpImageSparseFetchOpImageReadOpImageSparseReadopImageBlockMatchSADQCOMopImageBlockMatchSSDQCOMopImageBlockMatchWindowSADQCOMopImageBlockMatchWindowSSDQCOMOpImageWrite 指令使用整数纹素坐标。

其他图像指令可以使用归一化或非归一化纹素坐标(由指令中使用的采样器的 unnormalizedCoordinates 状态选择),但在支持的操作、图像状态和采样器状态方面存在限制。归一化坐标在逻辑上转换为非归一化坐标作为图像操作的一部分,并且某些步骤仅在归一化坐标上执行。即使其他坐标被归一化,数组层坐标也始终被视为非归一化坐标。

归一化纹素坐标被称为 (s,t,r,q,a),其中坐标具有以下含义

  • s: 图像的第一维坐标。

  • t: 图像的第二维坐标。

  • r: 图像的第三维坐标。

    • (s,t,r) 被解释为立方体图像的方向向量。

  • q: 第四个坐标,用于齐次(投影)坐标。

  • a: 数组层的坐标。

坐标根据图像变量的维度和指令类型从 SPIR-V 操作数中提取。对于 Proj 指令,组件按顺序为 (s, [t,] [r,] q),其中 tr 根据图像的 Dim 有条件地存在。对于非 Proj 指令,坐标为 (s [,t] [,r] [,a]),其中 tr 根据图像的 Dim 有条件地存在,而 a 根据图像的 Arrayed 属性有条件地存在。投影图像指令在 Arrayed 图像上不受支持。

非归一化纹素坐标被称为 (u,v,w,a),其中坐标具有以下含义

  • u: 图像的第一维坐标。

  • v: 图像的第二维坐标。

  • w: 图像的第三维坐标。

  • a: 数组层的坐标。

只有 uv 坐标直接从 SPIR-V 操作数中提取,因为只有 1D 和 2D(非 Arrayed)维度支持非归一化坐标。组件按顺序为 (u [,v]),当维度为 2D 时,v 有条件地存在。当归一化坐标转换为非归一化坐标时,会使用所有四个坐标。

整数纹素坐标被称为 (i,j,k,l,n),其中坐标具有以下含义

  • i: 图像的第一维坐标。

  • j: 图像的第二维坐标。

  • k: 图像的第三维坐标。

  • l: 数组层的坐标。

  • n: 纹素内样本的索引。

它们按顺序从 SPIR-V 操作数中提取,顺序为 (i [,j] [,k] [,l] [,n]),其中 jk 根据图像的 Dim 有条件地存在,而 l 根据图像的 Arrayed 属性有条件地存在。n 有条件地存在,并从 Sample 图像操作数中获取。

如果访问的图像是通过使用 VkImageViewSlicedCreateInfoEXT 从视图创建,并通过 VK_DESCRIPTOR_TYPE_STORAGE_IMAGE 描述符访问,则 k 的值会增加 VkImageViewSlicedCreateInfoEXT::sliceOffset,得到 k ← sliceOffset + k。图像在第三维中的可访问范围为 k < sliceOffset + sliceCount。如果 VkImageViewSlicedCreateInfoEXT::sliceCountVK_REMAINING_3D_SLICES_EXT,则范围从图像的深度范围继承,如 图像 Mip 级别大小调整 中指定的那样。

对于所有坐标类型,未使用的坐标都分配为零值。

vulkantexture0 ll
图 1. 纹素坐标系,线性滤波

纹素坐标系 - 对于显示的 8×4 纹素二维图像的示例。

  • 归一化纹素坐标

    • s 坐标从 0.0 到 1.0。

    • t 坐标从 0.0 到 1.0。

  • 非归一化纹素坐标

    • u 坐标在 0.0 到 8.0 范围内时位于图像内,否则在图像外。

    • v 坐标在 0.0 到 4.0 范围内时位于图像内,否则在图像外。

  • 整数纹素坐标

    • i 坐标在 0 到 7 范围内寻址图像内的纹素,否则在图像外。

    • j 坐标在 0 到 3 范围内寻址图像内的纹素,否则在图像外。

  • 还显示了线性滤波

    • 给定非归一化坐标 (u,v),选择的四个纹素是 i0j0i1j0i0j1i1j1

    • 分数 αβ

    • 给定偏移量 ΔiΔj,偏移量选择的四个纹素是 i0j'0i1j'0i0j'1i1j'1

对于具有降分辨率组件的格式,ΔiΔj 相对于最高分辨率组件的分辨率,因此相对于较低分辨率组件的非归一化坐标空间,可以除以 2。

vulkantexture1 ll
图 2. 纹素坐标系,最近邻滤波

纹素坐标系 - 对于显示的 8×4 纹素二维图像的示例。

  • 纹素坐标如上所述。还显示了最近邻滤波

    • 给定非归一化坐标 (u,v),选择的纹素是 ij

    • 给定偏移量 ΔiΔj,偏移量选择的纹素是 ij'

对于角采样图像,纹素样本位于网格交点处,而不是纹素中心。

vulkantexture0 corner alternative a ll
图 3. 纹素坐标系,角采样

转换公式

RGB 到共享指数转换

RGB 颜色 (red, green, blue) 转换为共享指数颜色 (redshared, greenshared, blueshared, expshared),如下所示

首先,将分量 (red, green, blue) 钳制为 (redclamped, greenclamped, blueclamped),如下所示

redclamped = max(0, min(sharedexpmax, red))

greenclamped = max(0, min(sharedexpmax, green))

blueclamped = max(0, min(sharedexpmax, blue))

其中

如果支持 NaN,则按以下方式处理
IEEE 754-2008 minNum()maxNum()。这会导致任何 NaN 被映射为零。

确定最大的钳制分量 maxclamped

maxclamped = max(redclamped, greenclamped, blueclamped)

计算初步的共享指数 exp'

计算共享指数 expshared

最后,计算范围为 02N 的三个整数值

共享指数到 RGB

共享指数颜色 (redshared, greenshared, blueshared, expshared) 转换为 RGB 颜色 (red, green, blue),如下所示

\(green = green_{shared} \times {2^{(exp_{shared}-B-N)}}\)

其中

N = 9 (每个分量的尾数位数)

B = 15 (指数偏差)

纹素输入操作

纹素输入指令是指从图像读取数据的 SPIR-V 图像指令。纹素输入操作是指在处理纹素输入指令时对状态、坐标和纹素值执行的一系列步骤,这些步骤对于某些或所有纹素输入指令是通用的。它们包括以下步骤,并按列出的顺序执行:

对于涉及多个纹素(用于采样或收集)的纹素输入指令,这些步骤将应用于指令中使用的每个纹素。根据图像指令的类型,其他步骤可能会在这些步骤之间有条件地执行,或涉及多个坐标或纹素值。

如果色度重建是隐式的,则纹素过滤会在色度重建期间进行,然后在发生采样器 Y′CBCR 转换之前进行。

块匹配权重图像采样中描述的操作将在转换为 RGBA组件混洗之前执行。

纹素输入验证操作

纹素输入验证操作检查指令/图像/采样器状态或坐标,并在某些情况下导致纹素值被替换或变为未定义。纹素会经历一系列验证。

指令/采样器/图像视图验证

在许多情况下,SPIR-V 指令可能与采样器、图像视图或两者都存在不匹配,并且在许多其他情况下,采样器可能与图像视图不匹配。在这些情况下,返回的纹素值是未定义的。

这些情况包括:

  • 采样器的 borderColor 是整数类型,并且图像视图的 format 不是VkFormat 整数类型之一,也不是深度/模板格式的模板组件。

  • 采样器的 borderColor 是浮点类型,并且图像视图的 format 不是VkFormat 浮点类型之一,也不是深度/模板格式的深度组件。

  • 采样器的 borderColor 是不透明黑色颜色之一(VK_BORDER_COLOR_FLOAT_OPAQUE_BLACKVK_BORDER_COLOR_INT_OPAQUE_BLACK),并且图像视图的VkComponentSwizzle 对于任何VkComponentMapping 组件都不是恒等混洗,并且未启用 VkPhysicalDeviceBorderColorSwizzleFeaturesEXT::borderColorSwizzleFromImage 功能,并且未指定 VkSamplerBorderColorComponentMappingCreateInfoEXT

  • VkSamplerBorderColorComponentMappingCreateInfoEXT::components(如果指定)具有与图像视图的组件混洗不匹配的组件混洗,并且任何一个组件混洗都不是恒等混洗的形式。

  • VkSamplerBorderColorComponentMappingCreateInfoEXT::srgb(如果指定)与图像视图的 sRGB 编码不匹配。

  • 采样器的 borderColor 是自定义颜色(VK_BORDER_COLOR_FLOAT_CUSTOM_EXTVK_BORDER_COLOR_INT_CUSTOM_EXT),并且提供的 VkSamplerCustomBorderColorCreateInfoEXT::customBorderColor 超出了图像视图的 format 中可表示的值的范围。

  • 采样器的 borderColor 是自定义颜色(VK_BORDER_COLOR_FLOAT_CUSTOM_EXTVK_BORDER_COLOR_INT_CUSTOM_EXT),并且图像视图的VkComponentSwizzle 对于任何VkComponentMapping 组件都不是恒等混洗,并且未启用 VkPhysicalDeviceBorderColorSwizzleFeaturesEXT::borderColorSwizzleFromImage 功能,并且未指定 VkSamplerBorderColorComponentMappingCreateInfoEXT

  • 图像视图中任何子资源的 VkImageLayout 与用于写入图像描述符的 VkDescriptorImageInfo::imageLayout 不匹配。

  • SPIR-V 图像格式与图像视图的 format兼容

  • 采样器的 unnormalizedCoordinatesVK_TRUE,并且违反了未归一化坐标的限制中的任何一项。

  • 采样器创建时,flags 包含 VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT,而图像创建时,flags 未包含 VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT

  • 采样器创建时,flags 未包含 VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT,而图像创建时,flags 包含 VK_IMAGE_CREATE_SUBSAMPLED_BIT_EXT

  • 采样器创建时,flags 包含 VK_SAMPLER_CREATE_SUBSAMPLED_BIT_EXT,并与不是 OpImageSampleImplicitLodOpImageSampleExplicitLod 的函数一起使用,或者与操作数 OffsetConstOffsets 一起使用。

  • SPIR-V 指令是 OpImage*Dref* 指令之一,并且采样器的 compareEnableVK_FALSE

  • SPIR-V 指令不是 OpImage*Dref* 指令之一,并且采样器的 compareEnableVK_TRUE

  • SPIR-V 指令是 OpImage*Dref* 指令之一,图像视图的 format 是深度/模板格式之一,并且图像视图的方面不是 VK_IMAGE_ASPECT_DEPTH_BIT

  • SPIR-V 指令的图像变量的属性与图像视图不兼容。

    • 如果图像视图的 viewTypeVK_IMAGE_VIEW_TYPE_1D_ARRAYVK_IMAGE_VIEW_TYPE_2D_ARRAYVK_IMAGE_VIEW_TYPE_CUBE_ARRAY 之一,则指令必须具有 Arrayed = 1。否则,指令必须具有 Arrayed = 0。

    • 如果图像创建时,VkImageCreateInfo::samples 等于 VK_SAMPLE_COUNT_1_BIT,则指令必须具有 MS = 0。

    • 如果图像创建时,VkImageCreateInfo::samples 不等于 VK_SAMPLE_COUNT_1_BIT,则指令必须具有 MS = 1。

    • 如果 OpTypeImageSampled TypeSPIR-V 类型不匹配。

    • 如果任何读取或采样操作的符号性与图像格式的符号性不匹配。

  • 如果图像创建时使用 VkImageCreateInfo::flags 包含 VK_IMAGE_CREATE_CORNER_SAMPLED_BIT_NV,则采样器寻址模式必须仅使用 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGEVkSamplerAddressMode

  • SPIR-V 指令是 OpImageSampleFootprintNV,其中 Dim = 2D,并且采样器中的 addressModeUaddressModeV 不是 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE

  • SPIR-V 指令是 OpImageSampleFootprintNV,其中 Dim = 3D,并且采样器中的 addressModeUaddressModeVaddressModeW 不是 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE

  • 采样器创建时指定了 VkSamplerCustomBorderColorCreateInfoEXT::format,它与它正在采样的图像视图的 VkFormat 不匹配。

  • 采样器正在采样 VK_FORMAT_B4G4R4A4_UNORM_PACK16VK_FORMAT_B5G6R5_UNORM_PACK16VK_FORMAT_B5G5R5A1_UNORM_PACK16 格式的图像视图,但没有指定 VkSamplerCustomBorderColorCreateInfoEXT::format

只有 OpImageSample*OpImageSparseSample* 可以与启用 采样器 Y′CBCR 转换的采样器或图像视图一起使用。

OpImageFetchOpImageSparseFetchOpImage*GatherOpImageSparse*Gather 必须不与启用 采样器 Y′CBCR 转换的采样器或图像视图一起使用。

ConstOffsetOffset 操作数必须不与启用 采样器 Y′CBCR 转换的采样器或图像视图一起使用。

如果底层 VkImage 格式在其格式描述中具有 X 分量,则从这些位读取的值是未定义的

如果 VkImage 格式和 VkImageView 格式相同,则这些位将不会被格式转换使用,并且不会产生任何影响。但是,如果 VkImageView 格式不同,则结果的某些位可能是未定义的。例如,当通过 VK_FORMAT_R16_UNORM VkImageView 采样 VK_FORMAT_R10X6_UNORM_PACK16 VkImage 时,格式转换之前的低 6 位的值是未定义的,并且格式转换可能会返回一系列不同的值。

在以下情况下,某些实现将返回未定义的值:采样器使用 VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEATVkSamplerAddressMode,采样器与操作数 OffsetConstOffsetConstOffsets 一起使用,并且偏移量的值大于或等于任何访问的图像级别的相应宽度、高度或深度。

此行为在 Vulkan 一致性测试套件版本 1.3.8.0 之前未经过测试。受影响的实现将对此问题进行一致性测试豁免。

整数纹素坐标验证

整数纹素坐标会根据图像级别的大小以及图像中的层数和样本数进行验证。对于使用整数纹素坐标的 SPIR-V 指令,此操作直接在整数坐标上执行。对于使用归一化或非归一化纹素坐标的指令,此操作在转换为整数纹素坐标后产生的坐标上执行。

如果整数纹素坐标不满足所有条件

0 ≤ i < ws

0 ≤ j < hs

0 ≤ k < ds

0 ≤ l < layers

0 ≤ n < samples

其中

ws = 图像级别的宽度

hs = 图像级别的高度

ds = 图像级别的深度

layers = 图像中的层数

samples = 图像中每个纹素的样本数

则纹素未通过整数纹素坐标验证。

有四种情况需要考虑

  1. 有效纹素坐标

    • 如果纹素坐标通过验证(即,坐标位于图像内),

      则纹素值来自图像内存中的值。

  2. 边界纹素

    • 如果纹素坐标未通过验证,并且

    • 如果读取是图像采样指令或图像收集指令的结果,并且

    • 如果图像不是立方体图像,或者如果使用使用 VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT 创建的采样器,

    则纹素是边界纹素,并且执行 纹素替换

  3. 无效纹素

    • 如果纹素坐标未通过验证,并且

    • 如果读取是图像获取指令、图像读取指令或原子指令的结果,

      则纹素是无效纹素,并且执行 纹素替换

  4. 立方体贴图边缘或角

    否则,纹素坐标位于所选立方体贴图面的边缘或角之外,并且执行 立方体贴图边缘处理

立方体贴图边缘处理

如果纹素坐标位于所选立方体贴图面的边缘或角之外(如上一节所述),则执行以下步骤。请注意,当在 mip 级别中使用 VK_FILTER_NEAREST 滤波时,不会发生这种情况,因为 VK_FILTER_NEAREST 被视为使用 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE

  • 立方体贴图边缘纹素

    • 如果纹素仅在 i 或仅在 j 中超出所选立方体贴图面,则坐标 (i,j) 和数组层 l 会被转换,以从适当的相邻面中选择相邻纹素。

  • 立方体贴图角纹素

    • 如果纹素在 ij 中都超出所选立方体贴图面,则没有唯一的相邻面可以从中读取该纹素。纹素应该被每个入射面中相邻纹素的三个值的平均值替换。但是,实现可以使用其他方法替换立方体贴图角纹素。这些方法受限于以下约束:对于线性滤波,如果三个可用的纹素具有相同的值,则生成的滤波纹素必须具有该值;对于三次滤波,如果十二个可用的样本具有相同的值,则生成的滤波纹素必须具有该值。

稀疏验证

如果纹素从稀疏图像的未绑定区域读取,则该纹素是稀疏未绑定纹素,并且继续进行 纹素替换

布局验证

如果不相交多平面图像的所有平面不在同一图像布局中,则必须不使用启用 采样器 Y′CBCR 转换来采样该图像。

格式转换

纹素会从图像视图的 VkFormat 转换为浮点或有符号或无符号整数分量的向量,其中分量的数量基于格式中存在的分量数量。

  • 根据格式,颜色格式具有一个、两个、三个或四个分量。

  • 深度/模板格式是一个组件。深度或模板组件由图像视图的 aspectMask 选择。

每个组件都根据其类型和大小进行转换(如 格式定义 部分针对每个 VkFormat 所定义的那样),使用 16 位浮点数无符号 11 位浮点数无符号 10 位浮点数定点数据转换共享指数到 RGB 中的相应公式。小于 32 位的有符号整数组件将进行符号扩展。

如果图像视图格式为 sRGB,则颜色分量首先会被视为 UNORM 进行转换,然后按照 Khronos 数据格式规范 的“sRGB EOTF”部分所述,对 R、G 和 B 分量应用 sRGB 到线性的转换。A 分量(如果存在)保持不变。

如果 VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM::enableYDegamma 等于 VK_TRUE,则按照 Khronos 数据格式规范 的“sRGB EOTF”部分所述,对 G 分量应用 sRGB 到线性的转换。如果 VkSamplerYcbcrConversionYcbcrDegammaCreateInfoQCOM::enableCbCrDegamma 等于 VK_TRUE,则按照 Khronos 数据格式规范 的“sRGB EOTF”部分所述,对 R 和 B 分量应用 sRGB 到线性的转换。A 分量(如果存在)保持不变。

如果图像视图格式为块压缩格式,则首先解码纹素值,然后根据压缩格式定义的类型和分量数量进行转换。

纹素替换

如果纹素是以下情况之一(并且仅是其中之一),则该纹素将被替换:

  • 边界纹素,

  • 无效纹素,或

  • 稀疏未绑定纹素。

边界纹素会被替换为基于图像格式和采样器的 borderColor 的值。边界颜色为:

表 1. 边界颜色 B,自定义边界颜色 VkSamplerCustomBorderColorCreateInfoEXT::customBorderColor U
采样器 borderColor 对应的边界颜色

VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK

[Br, Bg, Bb, Ba] = [0.0, 0.0, 0.0, 0.0]

VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK

[Br, Bg, Bb, Ba] = [0.0, 0.0, 0.0, 1.0]

VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE

[Br, Bg, Bb, Ba] = [1.0, 1.0, 1.0, 1.0]

VK_BORDER_COLOR_INT_TRANSPARENT_BLACK

[Br, Bg, Bb, Ba] = [0, 0, 0, 0]

VK_BORDER_COLOR_INT_OPAQUE_BLACK

[Br, Bg, Bb, Ba] = [0, 0, 0, 1]

VK_BORDER_COLOR_INT_OPAQUE_WHITE

[Br, Bg, Bb, Ba] = [1, 1, 1, 1]

VK_BORDER_COLOR_FLOAT_CUSTOM_EXT

[Br, Bg, Bb, Ba] = [Ur, Ug, Ub, Ua]

VK_BORDER_COLOR_INT_CUSTOM_EXT

[Br, Bg, Bb, Ba] = [Ur, Ug, Ub, Ua]

自定义边界颜色 (U) 可能在纹素替换之前被实现四舍五入,但这种四舍五入引入的误差 必须 不超过图像 format 的一个 ULP。

名称 VK_BORDER_COLOR_*_TRANSPARENT_BLACKVK_BORDER_COLOR_*_OPAQUE_BLACKVK_BORDER_COLOR_*_OPAQUE_WHITE 旨在描述合成词汇中哪些分量为零和一,而不是暗示 VK_BORDER_COLOR_INT_OPAQUE_WHITE 的数值是整数的饱和值。

这通过替换图像格式中的分量数量来代替纹素值

表 2. 替换后的边界纹素分量
纹素方面或格式 分量赋值

深度方面

D = Br

模板方面

S = Br

一个分量颜色格式

Colorr = Br

两个分量颜色格式

[Colorr,Colorg] = [Br,Bg]

三个分量颜色格式

[Colorr,Colorg,Colorb] = [Br,Bg,Bb]

四个分量颜色格式

[Colorr,Colorg,Colorb,Colora] = [Br,Bg,Bb,Ba]

单分量 Alpha 格式

[Colorr,Colorg,Colorb, Colora] = [0,0,0,Ba]

† 当 VkSamplerCreateInfo::borderColorVK_BORDER_COLOR_INT_CUSTOM_EXT 并且 VkSamplerCustomBorderColorCreateInfoEXT::formatVK_FORMAT_UNDEFINED 时,S = Bg 可能会被实现作为替换方法。实现 应该 使用 S = Br 作为替换方法。

除非读取操作来自缓冲区资源并且启用了 robustBufferAccess 功能,否则读取无效纹素返回的值是 未定义的。在这种情况下,无效纹素将按照 robustBufferAccess 功能的描述进行替换。如果访问的是图像资源,并且 x、y、z 或图层坐标验证失败,并且启用了 robustImageAccess 功能,则如果存在,R、G 和 B 分量 必须 返回零。如果存在 A 分量,则 必须 返回零或一。如果启用了 robustImageAccess2 功能,则 必须 返回零值。如果仅样本索引无效,则返回的值是 未定义的

此外,如果启用了 robustImageAccess 功能,但未启用 robustImageAccess2 功能,则任何无效纹素 可能 在纹素替换之前扩展到四个分量。这意味着图像格式中不存在的分量可以用 0 替换,或者可以像往常一样进行 转换为 RGBA

从空描述符加载返回一个所有分量均为零的四分量颜色值。但是,对于使用显式 SPIR-V 图像格式的存储图像和存储纹素缓冲区,如果格式不包含 alpha,则从空描述符加载 可能 返回 alpha 值为 1(浮点或整数,取决于格式)。

如果 VkPhysicalDeviceSparseProperties::residencyNonResidentStrict 属性为 VK_TRUE,则稀疏未绑定纹素将分别用图像格式的整数和浮点分量的 0 或 0.0 值替换。

如果 residencyNonResidentStrictVK_FALSE,则稀疏未绑定纹素的值是未定义的

深度比较操作

如果图像视图具有深度/模板格式,则深度分量由 aspectMask 选择,并且操作是 OpImage*Dref* 指令,则会执行深度比较。如果比较结果为 true,则结果为 1.0,否则为 0.0。此值将替换深度分量 D

比较操作由 VkCompareOp 值选择,该值由 VkSamplerCreateInfo::compareOp 设置。SPIR-V 操作数 Dref 中的参考值和纹素深度值 Dtex 在该操作中分别用作参考值和测试值。

如果采样的图像具有无符号归一化定点格式,则在比较操作之前,Dref 会被钳制到 [0,1]

转换为 RGBA

根据图像基本颜色,纹素从一个、两个或三个分量扩展到四个分量。

表 3. 转换为 RGBA 后的纹素颜色
纹素方面或格式 RGBA 颜色

深度方面

[Colorr,Colorg,Colorb, Colora] = [D,0,0,one]

模板方面

[Colorr,Colorg,Colorb, Colora] = [S,0,0,one]

一个分量颜色格式

[Colorr,Colorg,Colorb, Colora] = [Colorr,0,0,one]

两个分量颜色格式

[Colorr,Colorg,Colorb, Colora] = [Colorr,Colorg,0,one]

三个分量颜色格式

[Colorr,Colorg,Colorb, Colora] = [Colorr,Colorg,Colorb,one]

四个分量颜色格式

[Colorr,Colorg,Colorb, Colora] = [Colorr,Colorg,Colorb,Colora]

一个 alpha 分量颜色格式

[Colorr,Colorg,Colorb, Colora] = [0,0,0,Colora]

其中 one = 1.0f 用于浮点格式和深度方面,one = 1 用于整数格式和模板方面。

分量混洗

所有纹素输入指令都基于以下内容应用混洗

混洗可以重新排列纹素的分量,或者为任何分量替换零或一。它对于每个颜色 component 定义如下:

其中

如果边框颜色是 VK_BORDER_COLOR_*_OPAQUE_BLACK 枚举之一,并且对于所有分量,VkComponentSwizzle 不是 恒等混洗,则混洗后的纹素的值是未定义的

如果图像视图具有深度/模板格式,并且 VkComponentSwizzleVK_COMPONENT_SWIZZLE_ONE,并且 VkPhysicalDeviceMaintenance5Properties::depthStencilSwizzleOneSupport 不是 VK_TRUE,则混洗后的纹素的值是未定义的

稀疏驻留

OpImageSparse* 指令返回一个结构,其中包括一个驻留代码,指示该指令访问的任何纹素是否是稀疏未绑定纹素。此代码可以OpImageSparseTexelsResident 指令解释,该指令将驻留代码转换为布尔值。

色度重建

在某些颜色模型中,颜色表示是根据单色光强度(通常称为“亮度”)和相对于此强度的颜色差异(通常称为“色度”)来定义的。对于除 RGB 之外的颜色模型,通常以比亮度分量更低的空间分辨率表示色度分量。此方法用于利用人眼对颜色的空间敏感度低于其对亮度的敏感度的特点。较不常见的是,相同的方法也用于加色,因为绿色分量在人眼对光强度的敏感度中占主导地位,并且红色和蓝色引入的颜色空间敏感度较低。

较低分辨率的分量通过将它们调整为比表示亮度的分量更低的空间分辨率进行“下采样”。此过程通常也称为“色度二次采样”。每个纹理纹素中都有一个亮度样本,但每个色度样本可能会在纹理的一个或两个维度中被多个纹素共享。

  • _444”格式与亮度相比,不会对色度值进行空间下采样:每个纹素都有唯一的色度样本。

  • _422”格式在 x 维度(对应于 us 坐标)中具有下采样:在该维度中,它们的采样分辨率是亮度的一半。

  • _420”格式在 x 维度(对应于 us 坐标)和 y 维度(对应于 vt 坐标)中具有下采样:它们在两个维度中的采样分辨率都是亮度的一半。

为纹理访问重建完整颜色值的过程涉及在同一位置访问色度和亮度值。为了准确生成颜色,必须从较低分辨率的样本位置重建亮度样本位置的较低分辨率分量的值,无论实际颜色模型如何,该操作在此处称为“色度重建”。

色度样本相对于亮度坐标的位置由用于创建采样器 Y′CBCR 转换的 VkSamplerYcbcrConversionCreateInfo 结构的 xChromaOffsetyChromaOffset 成员确定。

下图显示了非归一化 (u,v) 坐标和亮度分量中 (i,j) 整数纹素位置之间的关系(以黑色显示,圆圈显示整数样本位置)以及以红色交叉显示的降低分辨率色度分量的纹素坐标。

如果通过插值在亮度样本的位置重建色度值,则需要来自图像边界之外的色度样本;这些样本根据环绕操作确定。这些图通过显示“色度纹素”的边界延伸到图像边界之外,并包括插值所需的额外色度样本位置来表示这一点。NEAREST 采样的样本限制显示为网格。

chromasamples 422 cosited
图 4. 422 下采样,xChromaOffset=COSITED_EVEN
chromasamples 422 midpoint
图 5. 422 下采样,xChromaOffset=MIDPOINT
chromasamples 420 xcosited ycosited
图 6. 420 下采样,xChromaOffset=COSITED_EVEN,yChromaOffset=COSITED_EVEN
chromasamples 420 xmidpoint ycosited
图 7. 420 下采样,xChromaOffset=MIDPOINT,yChromaOffset=COSITED_EVEN
chromasamples 420 xcosited ymidpoint
图 8. 420 下采样,xChromaOffset=COSITED_EVEN,yChromaOffset=MIDPOINT
chromasamples 420 xmidpoint ymidpoint
图 9. 420 下采样,xChromaOffset=MIDPOINT,yChromaOffset=MIDPOINT

重建以两种方式之一实现

如果要采样的图像的格式设置了 VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT,或者 VkSamplerYcbcrConversionCreateInfoforceExplicitReconstructionVK_TRUE,则重建将作为独立于过滤的显式步骤执行,如显式重建部分所述。

如果要采样的图像的格式未设置 VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT,并且如果 VkSamplerYcbcrConversionCreateInfoforceExplicitReconstructionVK_FALSE,则重建将作为颜色模型转换之前过滤的隐式部分执行,没有单独的转换后纹素过滤步骤,如隐式重建部分所述。

显式重建

  • 如果 VkSamplerYcbcrConversionCreateInfo 结构的 chromaFilter 成员为 VK_FILTER_NEAREST

    • 如果格式的 R 和 B 分量相对于 G 分量在宽度上以 2 的因子降低分辨率(即,这是一个“_422”格式),则通过纹素过滤访问的 值按如下方式重建:

    • 如果格式的 R 和 B 分量在宽度和高度上的分辨率相对于 G 分量降低了二分之一(即,这是一个 “_420” 格式),则通过 纹素过滤 访问的 值按照以下方式重建

      如果 chromaFilter 对于显式重建是 VK_FILTER_NEAREST,则 xChromaOffsetyChromaOffset 无效。

  • 如果 VkSamplerYcbcrConversionCreateInfo 结构的 chromaFilter 成员是 VK_FILTER_LINEAR

    • 如果格式的 R 和 B 分量在宽度上的分辨率相对于 G 分量降低了二分之一(即,这是一个 “_422” 格式)

      • 如果 xChromaOffsetVK_CHROMA_LOCATION_COSITED_EVEN

      • 如果 xChromaOffsetVK_CHROMA_LOCATION_MIDPOINT

    • 如果格式的 R 和 B 分量在宽度和高度上的分辨率相对于 G 分量降低了二分之一(即,这是一个 “_420” 格式),则适用类似的关系。由于选项数量众多,这些公式以更简洁的方式表达如下

如果纹理本身按照 纹素过滤 中所述进行双线性插值,因此过滤操作需要四个全彩色样本,并且由于 chromaFilter=VK_FILTER_LINEAR,这些样本的重建在色度分量中使用双线性插值,则可能需要多达九个色度样本,具体取决于样本位置。

隐式重建

隐式重建通过对样本进行插值来实现,插值过程根据采样器的滤波器设置进行,但chromaFilter 对色度样本具有优先权。

如果 chromaFilterVK_FILTER_NEAREST,则实现 可以 表现得好像 xChromaOffsetyChromaOffset 都为 VK_CHROMA_LOCATION_MIDPOINT,而忽略实际设置的值。

如果亮度样本的位置与用于光栅化的样本位置重合,则这不会产生任何可见的影响。

样本坐标会根据组件的降采样因子进行调整(例如,如果组件相对于亮度组件的降采样因子为 2,则样本坐标将除以 2)

采样器 Y′CBCR 转换

采样器 Y′CBCR 转换执行以下操作,实现 可以 将其组合为单个数学运算

采样器 Y′CBCR 范围扩展

采样器 Y′CBCR 范围扩展应用于所有非特定于采样器 Y′CBCR 转换的纹素输入操作之后的颜色分量值。例如,此阶段的输入值已使用普通的格式转换规则进行转换。

如果启用了ycbcrDegamma 特性,则此阶段的输入值可能已使用 sRGB 到线性的转换进行转换。

如果 ycbcrModelVK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,则不应用采样器 Y′CBCR 范围扩展。也就是说,着色器接收组件置换阶段输出的向量 C'rgba,而无需进一步修改。

对于 ycbcrModel 的其他值,范围扩展应用于 组件置换输出的纹素分量值,该置换由 VkSamplerYcbcrConversionCreateInfocomponents 成员定义。范围扩展独立应用于图像的每个分量。为了进行范围扩展和 Y′CBCR 模型转换,R 和 B 分量包含色差(色度)值,而 G 分量包含亮度。A 分量不会被采样器 Y′CBCR 范围扩展修改。

要应用的范围扩展由 VkSamplerYcbcrConversionCreateInfo 结构的 ycbcrRange 成员定义。

  • 如果 ycbcrRangeVK_SAMPLER_YCBCR_RANGE_ITU_FULL,则应用以下转换

    这些公式对应于Khronos 数据格式规范的“量化方案”章节中的“全范围”编码。

    如果未来对这些公式所依据的 ITU 规范进行任何修改,Vulkan 使用的公式 可以 也进行更新以保持一致。

  • 如果 ycbcrRangeVK_SAMPLER_YCBCR_RANGE_ITU_NARROW,则应用以下转换

    这些公式对应于Khronos 数据格式规范的“量化方案”章节中的“窄范围”编码。

  • n 是格式中分量的位深度。

范围扩展期间执行的操作的精度 必须 至少与源格式的精度相同。

实现 可以 钳制这些范围扩展操作的结果,使得 Y′ 落在 [0,1] 范围内,和/或使得 CB 和 CR 落在 [-0.5,0.5] 范围内。

采样器 Y′CBCR 模型转换

范围扩展后的值根据 ycbcrModel 成员中指定的颜色模型转换在颜色模型之间进行转换。

VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY

颜色分量不会被颜色模型转换修改,因为它们被假设已经表示着色器正在运行的所需颜色模型;Y′CBCR 范围扩展也被忽略。

VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY

颜色分量不会被颜色模型转换修改,并被假定在内存和着色器中都被视为 Y′CBCR 形式;Y′CBCR 范围扩展应用于分量,如同其他 Y′CBCR 模型一样,向量 (CR,Y′,CB,A) 提供给着色器。

VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709

颜色分量从 Y′CBCR 表示形式转换为 R′G′B′ 表示形式,如Khronos 数据格式规范的“BT.709 Y′CBCR 转换”部分所述。

VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601

颜色分量从 Y′CBCR 表示形式转换为 R′G′B′ 表示形式,如Khronos 数据格式规范的“BT.601 Y′CBCR 转换”部分所述。

VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020

颜色分量从 Y′CBCR 表示形式转换为 R′G′B′ 表示形式,如Khronos 数据格式规范的“BT.2020 Y′CBCR 转换”部分所述。

在此操作中,每个输出分量都依赖于每个输入分量。

实现 可以 将这些转换的 R′G′B′ 结果钳制到 [0,1] 范围内。

模型转换期间执行的操作的精度 必须 至少与源格式的精度相同。

alpha 分量不会被这些模型转换修改。

在非线性颜色空间中的采样操作可能会在急剧的过渡边界处引入颜色和强度的偏移。为了避免这个问题,可以按照Khronos 数据格式规范的“颜色转换简介”章节中描述的技术上精确的颜色校正顺序进行操作:

与直接使用输出相比,在 VK_FILTER_LINEAR 情况下,额外的计算,特别是额外的采样操作次数,预计会对性能产生影响。由于对于大多数内容,“正确”结果的差异很小,应用程序作者应确定是否严格需要更昂贵的实现。

如果 chromaFilterminFiltermagFilter 都是 VK_FILTER_NEAREST,则这些操作是多余的,并且在所需的采样坐标处使用采样器 Y′CBCR 转换进行采样将产生“正确”的结果,无需进一步处理。

纹素输出操作

纹素输出指令是写入图像的 SPIR-V 图像指令。纹素输出操作是在处理纹素输出指令时,对状态、坐标和纹素值执行的一系列步骤,这些步骤对于某些或所有纹素输出指令都是通用的。它们包括以下步骤,并按所列顺序执行

纹素输出验证操作

纹素输出验证操作检查指令/图像状态或坐标,并且在某些情况下会导致写入无效。纹素会经历一系列验证。

纹素格式验证

如果 OpTypeImage 的图像格式与 VkImageViewformat兼容,则写入会导致图像内存的内容变为未定义

纹素类型验证

如果 OpTypeImageSampled TypeSPIR-V 类型不匹配,则写入会导致纹素的值变为未定义。对于整数类型,如果访问的符号与所访问资源的符号不匹配,则写入会导致纹素的值变为未定义

整数纹素坐标验证

整数纹素坐标的验证规则与纹素输入坐标验证的规则相同。

如果纹素未通过整数纹素坐标验证,则写入无效。

稀疏纹素操作

如果纹素尝试写入稀疏图像的未绑定区域,则该纹素是稀疏的未绑定纹素。在这种情况下,如果VkPhysicalDeviceSparseProperties::residencyNonResidentStrict 属性为 VK_TRUE,则稀疏的未绑定纹素写入无效。如果 residencyNonResidentStrictVK_FALSE,则写入可能会产生副作用,该副作用对于任何资源中对未绑定纹素的其他访问是可见的,但对于应用程序分配的任何设备内存将不可见。

纹素输出格式转换

如果图像格式为 sRGB,则按照Khronos 数据格式规范的“sRGB EOTF”章节中的描述,对 R、G 和 B 分量应用线性到 sRGB 的转换。A 分量(如果存在)保持不变。

然后,纹素将从纹素数据的浮点、有符号或无符号整数类型转换为图像视图的VkFormat。如果纹素数据中的分量数量大于格式中的分量数量,则会丢弃其他分量。

每个分量都根据其类型和大小进行转换(如每个VkFormat格式定义部分中所定义)。浮点输出的转换如浮点格式转换定点数据转换中所述。整数输出的转换会保留其值。任何无法以目标格式表示的整数的转换后的值都是未定义的。

如果 VkImageView 格式在其格式描述中具有 X 分量,则会向这些位写入未定义的值。

如果底层 VkImage 格式在其格式描述中具有 X 分量,则也会向这些位写入未定义的值,即使结果格式转换会为这些位产生有效值,因为 VkImageView 格式是不同的。

标准化纹素坐标操作

如果图像采样器指令提供标准化纹素坐标,则会执行以下一些操作。

投影操作

对于 Proj 图像操作,标准化纹素坐标 (s,t,r,q,a) 和(如果存在)Dref 坐标按如下方式转换

导数图像操作

导数用于 LOD 选择。这些导数可以是隐式的(在网格、任务、计算或片段着色器中的 ImplicitLod 图像指令中),也可以是显式的(由着色器在任何着色器中显式提供给图像指令)。

对于隐式导数图像指令,纹素坐标的导数以与导数操作相同的方式计算。即

某些图像维度未定义的上述偏导数设置为零。

对于显式 LOD 图像指令,如果提供了可选的 SPIR-V 操作数 Grad,则操作数值将用于导数。给定图像维度的每个导数中存在的组件数量与上面计算的偏导数数量相匹配。

如果提供了可选的 SPIR-V 操作数 Lod,则导数设置为零,跳过立方体贴图导数变换,并跳过缩放因子运算。相反,浮点标量坐标将直接赋值给 λbase,如 LOD 操作中所述。

如果隐式导数图像指令使用的图像或采样器对象在四边形中不均匀,并且不支持 quadDivergentImplicitLod,则导数和 LOD 值是未定义的。当图像和采样器以及控制流在四边形中均匀时,即使它们在不同的四边形之间发散,隐式导数也是定义良好的。

如果支持 quadDivergentImplicitLod,即使图像或采样器对象在四边形内不均匀,导数和隐式 LOD 值也是定义良好的。导数按照上述指定计算,并且每个着色器调用的隐式 LOD 计算都使用其各自的图像和采样器对象进行。

立方体贴图面选择和变换

对于立方体贴图图像指令,(s,t,r) 坐标被视为方向向量 (rx,ry,rz)。该方向向量用于选择立方体贴图面。方向向量被转换为每个面的纹素坐标系 (sface,tface)。方向向量还用于将导数转换为每个面的导数。

立方体贴图面选择

方向向量根据最大幅度坐标方向(主轴方向)选择立方体贴图的一个面。由于两个或多个坐标可能具有相同的幅度,因此实现必须具有规则来消除这种情况的歧义。

这些规则的第一个规则应该rz 胜过 ryrx,第二个规则是 ry 胜过 rx。实现可以选择其他规则,但这些规则必须是确定性的,并且仅取决于 (rx,ry,rz)

层号(对应于立方体贴图面)、sctcrc 的坐标选择以及导数的选择由主轴方向确定,如下两个表所示。

表 4. 立方体贴图面和坐标选择
主轴方向 层号 立方体贴图面 sc tc rc

+rx

0

正 X

-rz

-ry

rx

-rx

1

负 X

+rz

-ry

rx

+ry

2

正 Y

+rx

+rz

ry

-ry

3

负 Y

+rx

-rz

ry

+rz

4

正 Z

+rx

-ry

rz

-rz

5

负 Z

-rx

-ry

rz

表 5. 立方体贴图导数选择
主轴方向 ∂sc / ∂x ∂sc / ∂y ∂tc / ∂x ∂tc / ∂y ∂rc / ∂x ∂rc / ∂y

+rx

-∂rz / ∂x

-∂rz / ∂y

-∂ry / ∂x

-∂ry / ∂y

+∂rx / ∂x

+∂rx / ∂y

-rx

+∂rz / ∂x

+∂rz / ∂y

-∂ry / ∂x

-∂ry / ∂y

-∂rx / ∂x

-∂rx / ∂y

+ry

+∂rx / ∂x

+∂rx / ∂y

+∂rz / ∂x

+∂rz / ∂y

+∂ry / ∂x

+∂ry / ∂y

-ry

+∂rx / ∂x

+∂rx / ∂y

-∂rz / ∂x

-∂rz / ∂y

-∂ry / ∂x

-∂ry / ∂y

+rz

+∂rx / ∂x

+∂rx / ∂y

-∂ry / ∂x

-∂ry / ∂y

+∂rz / ∂x

+∂rz / ∂y

-rz

-∂rx / ∂x

-∂rx / ∂y

-∂ry / ∂x

-∂ry / ∂y

-∂rz / ∂x

-∂rz / ∂y

立方体贴图坐标变换

立方体贴图导数变换

立方体贴图坐标变换的偏导数可以计算为

其他导数也类似地简化,结果为

缩放因子运算、LOD 运算和图像层级选择

LOD 选择可以是显式的(由图像指令显式提供)或隐式的(从根据导数计算的缩放因子确定)。LOD 必须mipmapPrecisionBits 的精度计算。

缩放因子运算

导数的大小按以下方式计算:

mux = |∂s/∂x| × wbase

mvx = |∂t/∂x| × hbase

mwx = |∂r/∂x| × dbase

muy = |∂s/∂y| × wbase

mvy = |∂t/∂y| × hbase

mwy = |∂r/∂y| × dbase

其中

∂t/∂x = ∂t/∂y = 0(对于 1D 图像)

∂r/∂x = ∂r/∂y = 0(对于 1D、2D 或立方体图像)

并且

wbase = image.w

hbase = image.h

dbase = image.d

(对于来自图像描述符的 baseMipLevel)。

对于角采样图像,wbasehbasedbase 则为

wbase = image.w - 1

hbase = image.h - 1

dbase = image.d - 1

屏幕空间中的点采样在纹理空间中具有椭圆形的足迹。最小和最大缩放因子 min, ρmax) 应该是此椭圆的短轴和长轴。

根据 x 和 y 方向的导数大小计算的缩放因子 ρxρy 用于计算最小和最大缩放因子。

ρxρy 可以使用函数 fxfy 近似,但须满足以下约束:

最小和最大缩放因子 minmax) 由下式确定:

ρmax = max(ρx, ρy)

ρmin = min(ρx, ρy)

各向异性比率由下式确定:

η = min(ρmaxmin, maxAniso)

其中

sampler.maxAniso = maxAnisotropy(来自采样器描述符)

limits.maxAniso = maxSamplerAnisotropy(来自物理设备限制)

maxAniso = min(sampler.maxAniso, limits.maxAniso)

如果 ρmax = ρmin = 0,则所有偏导数均为零,片段在纹素空间中的足迹是一个点,并且 η 应该被视为 1。如果 ρmax ≠ 0ρmin = 0,则沿一个轴的所有偏导数均为零,片段在纹素空间中的足迹是一条线段,并且 η 应该被视为 maxAniso。但是,只要足迹在纹素空间中很小,即使 ρmin 为零或接近零,实现可以使用较小的 η 值。如果 VkPhysicalDeviceFeatures::samplerAnisotropyVkSamplerCreateInfo::anisotropyEnableVK_FALSE,则 maxAniso 设置为 1。

如果 η = 1,则采样是各向同性的。如果 η > 1,则采样是各向异性的。

采样率 (N) 的推导公式如下

N = ⌈η⌉

实现可以N 向上取整到最近的受支持采样率。实现可以使用 N 的值作为 η 的近似值。

LOD 操作

LOD 参数 λ 的计算方式如下

其中

其中 maxSamplerLodBiasVkPhysicalDeviceLimits 特性的 maxSamplerLodBias 的值。

图像层级选择

从中读取纹素的图像层级 ddhidlo 由图像层级参数 dl 确定,该参数基于 LOD 参数计算,如下所示

其中

并且

baseMipLevellevelCount 取自图像视图的 subresourceRange

minLodimageView 必须小于或等于 levelbase + q

如果采样器的 mipmapModeVK_SAMPLER_MIPMAP_MODE_NEAREST,则选择的层级是 d = dl

如果采样器的 mipmapModeVK_SAMPLER_MIPMAP_MODE_LINEAR,则选择两个相邻的层级

δ 是用于层级之间线性滤波的小数值,量化为mipmap 精度位数

(s,t,r,q,a) 到 (u,v,w,a) 的变换

归一化的纹素坐标按图像层级的维度进行缩放,并选择数组层。

此变换对滤波中使用的每个层级执行一次(d,或 dhidlo)。

其中

widthscale = widthlevel

heightscale = heightlevel

depthscale = depthlevel

对于传统图像,以及

widthscale = widthlevel - 1

heightscale = heightlevel - 1

depthscale = depthlevel - 1

对于角采样图像。

其中 i, Δj, Δk) 取自图像指令(如果包含 ConstOffsetOffset 操作数),否则它们被视为零。

然后操作继续到非归一化纹素坐标操作。

非归一化纹素坐标操作

(u,v,w,a) 到 (i,j,k,l,n) 的变换和数组层选择

非归一化纹素坐标被转换为相对于选定 mipmap 层级的整数纹素坐标。

层索引 l 的计算公式为

l = clamp(RNE(a), 0, layerCount - 1) + baseArrayLayer

其中 layerCount 是图像视图的图像子资源范围中的层数,baseArrayLayer 是子资源范围中的第一层,其中

采样索引 n 被赋值为 0。

最近邻滤波 (VK_FILTER_NEAREST) 计算非归一化坐标所在的整数纹素坐标

其中

shift = 0.0

对于传统图像,以及

shift = 0.5

对于角采样图像。

线性滤波 (VK_FILTER_LINEAR) 计算一组包围非归一化坐标的相邻坐标。整数纹素坐标是 i0i1j0j1k0k1 的组合,以及权重 α、βγ

其中

shift = 0.5

对于传统图像,以及

shift = 0.0

对于角采样图像,其中

其中保留的小数位数由 VkPhysicalDeviceLimits::subTexelPrecisionBits 指定。

三次滤波 (VK_FILTER_CUBIC_EXT) 计算一组包围非归一化坐标的相邻坐标。整数纹素坐标是 i0i1i2i3j0j1j2j3k0k1k2k3 的组合,以及权重 αβγ

其中

其中保留的小数位数由 VkPhysicalDeviceLimits::subTexelPrecisionBits 指定。

整数纹素坐标操作

整数纹素坐标操作可以使用可选的 SPIR-V 操作数 Lod 提供要从中读取或写入纹素的 LOD。如果提供了 Lod,则它必须是整数。

选择的图像层级为

如果 d 不在范围 [baseMipLevel, baseMipLevel + levelCount) 内,或者 d 小于 minLodIntegerimageView,则如果启用 robustImageAccess2 功能,则获取的任何值都为零,否则为未定义,并且任何写入(如果支持)都会被丢弃。

图像采样操作

环绕操作

如果使用的采样器在创建时没有使用 VK_SAMPLER_CREATE_NON_SEAMLESS_CUBE_MAP_BIT_EXT,则 Cube 图像会忽略采样器中指定的环绕模式。相反,如果在 mip 层级内使用 VK_FILTER_NEAREST,则使用 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;如果在 mip 层级内使用 VK_FILTER_LINEAR,则在边缘的采样按照立方体贴图边缘处理部分前面的描述执行。

第一个整数纹素坐标 i 根据采样器的 addressModeU 参数进行转换。

其中

j(对于 2D 和 Cube 图像)和 k(对于 3D 图像)分别根据采样器的 addressModeVaddressModeW 参数进行类似转换。

纹素收集

名称中带有 Gather 的 SPIR-V 指令会返回一个从图像视图的基层中的 4 个纹素派生的向量。VK_FILTER_LINEAR 缩小过滤器的规则用于识别选择的四个纹素。然后根据转换为 RGBA将每个纹素转换为 RGBA 值,然后进行通道重组。然后,通过从四个纹素的通道重组颜色值中获取指令中 Component 值指示的组件,来组装一个四组件向量。如果操作不使用 ConstOffsets 图像操作数,则四个纹素形成用于纹理滤波的 2 × 2 矩形

如果操作确实使用 ConstOffsets 图像操作数,则偏移允许定义自定义滤波器

其中

OpImage*Gather 不得用于启用了采样器 Y′CBCR 转换的采样图像。

如果 levelbase < minLodIntegerimageView,则如果启用 robustImageAccess2 功能,则获取的任何值都为零。否则,这些值是未定义的

纹素滤波

首先对每个层级(ddhidlo)执行纹素过滤。

如果 λ 小于或等于零,则称纹理被放大,并且通过采样器中的 magFilter 选择 mip 层级内的过滤模式。如果 λ 大于零,则称纹理被缩小,并且通过采样器中的 minFilter 选择 mip 层级内的过滤模式。

纹素最近邻过滤

在 mip 层级内,VK_FILTER_NEAREST 过滤使用 (i, j, k) 纹素坐标选择单个值,所有纹素都取自图层 l。

纹素线性过滤

在 mip 层级内,VK_FILTER_LINEAR 过滤将 8 个(对于 3D)、4 个(对于 2D 或立方体)或 2 个(对于 1D)纹素值与其线性权重组合在一起。线性权重从先前计算的分数得出。

多个纹素的值与其权重组合在一起,以产生过滤后的值。

VkSamplerReductionModeCreateInfo::reductionMode 可以控制多个纹素及其权重组合以生成过滤后的纹理值的过程。

reductionMode 被设置为(显式或隐式)VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE 时,将计算加权平均值。

但是,如果减少模式是 VK_SAMPLER_REDUCTION_MODE_MINVK_SAMPLER_REDUCTION_MODE_MAX,则该过程将对上述多个纹素及其权重进行操作,分别计算具有非零权重的纹素集合的分量最小值或最大值。

纹素三次过滤

在 mip 层级内,VK_FILTER_CUBIC_EXT 过滤计算 64 个(对于 3D)、16 个(对于 2D)或 4 个(对于 1D)纹素值的加权平均值,以及由 VkSamplerCubicWeightsCreateInfoQCOM 指定的 Catmull-Rom、零切线基数、B 样条或 Mitchell-Netravali 权重。

VK_CUBIC_FILTER_WEIGHTS_CATMULL_ROM_QCOM 指定的 Catmull-Rom 权重从先前计算的分数得出。

VK_CUBIC_FILTER_WEIGHTS_ZERO_TANGENT_CARDINAL_QCOM 指定的零切线基数权重从先前计算的分数得出。

VK_CUBIC_FILTER_WEIGHTS_B_SPLINE_QCOM 指定的 B 样条权重从先前计算的分数得出。

VK_CUBIC_FILTER_WEIGHTS_MITCHELL_NETRAVALI_QCOM 指定的 Mitchell-Netravali 权重从先前计算的分数得出。

多个纹素的值与其权重组合在一起,以产生过滤后的值。

VkSamplerReductionModeCreateInfo::reductionMode 可以控制多个纹素及其权重组合以生成过滤后的纹理值的过程。

reductionMode 被设置为(显式或隐式)VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGEVK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM 时,将计算加权平均值。

但是,如果减少模式是 VK_SAMPLER_REDUCTION_MODE_MINVK_SAMPLER_REDUCTION_MODE_MAX,则该过程将对上述多个纹素及其权重进行操作,分别计算具有非零权重的纹素集合的分量最小值或最大值。

纹素范围钳制

reductionModeVK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_RANGECLAMP_QCOM 时,加权平均值被钳制在具有非零权重的纹素集合的分量最小值和最大值之间。

纹素 Mipmap 过滤

VK_SAMPLER_MIPMAP_MODE_NEAREST 过滤返回单个 mipmap 层级的值,

τ = τ[d].

VK_SAMPLER_MIPMAP_MODE_LINEAR 过滤将多个 mipmap 层级(τ[hi] 和 τ[lo])的值与其线性权重组合在一起。

线性权重从先前计算的分数得出。

多个 mipmap 层级的值与其权重组合在一起,以生成最终过滤后的值。

VkSamplerReductionModeCreateInfo::reductionMode 可以控制多个纹素及其权重组合以生成过滤后的纹理值的过程。

reductionMode 被设置为(显式或隐式)VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE 时,将计算加权平均值。

但是,如果减少模式是 VK_SAMPLER_REDUCTION_MODE_MINVK_SAMPLER_REDUCTION_MODE_MAX,则该过程将对上述值及其权重进行操作,分别计算具有非零权重的分量最小值或最大值。

纹素各向异性过滤

采样器中的 anisotropyEnable 启用各向异性过滤。启用后,图像过滤方案会考虑一定程度的各向异性。

各向异性纹理过滤的特定方案取决于具体实现。实现考虑采样器的 magFilterminFiltermipmapMode 来控制所使用的各向异性过滤方案的细节。此外,实现考虑采样器的 minLodmaxLod

由于历史原因,各向异性过滤的供应商实现以不同的方式解释这些采样器参数,尤其是在 magFilterminFilterNEARESTmaxAnisotropy 等于 1.0 等极端情况下。应用程序不应期望在这些情况下保持一致的行为,而应仅将各向异性过滤与预期可提供相对于 LINEAR 过滤的质量改进的参数一起使用。

以下描述了一种为 2D 图像实现各向异性过滤的特定方法;实现可以选择其他方法。

给定 magFilterminFilterVK_FILTER_LINEARmipmapModeVK_SAMPLER_MIPMAP_MODE_NEAREST

不是单个各向同性样本,而是在图像级别 d 的图像覆盖区内采样 N 个各向同性样本,以近似各向异性过滤器。总和 τ2Daniso 是使用级别 d 的单个各向同性 τ2D(u,v) 定义的。

VkSamplerReductionModeCreateInfo::reductionModeVK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE 时,使用上述求和。但是,如果减少模式是 VK_SAMPLER_REDUCTION_MODE_MINVK_SAMPLER_REDUCTION_MODE_MAX,则该过程将对上述值及其权重进行操作,分别计算具有非零权重的分量最小值或最大值。

纹素覆盖区评估

SPIR-V 指令 OpImageSampleFootprintNV 评估在 纹素过滤 操作期间将从单个 mip 层级访问的纹素集合。除了等效的 OpImageSample* 指令会接受的输入外,OpImageSampleFootprintNV 还接受两个附加输入。Granularity 输入是一个整数,用于标识用于评估覆盖区的纹素组的大小。返回的覆盖区掩码中的每个位都对应于一个对齐的纹素块,其大小由下表给出。

表 6. 纹素覆盖区粒度值
粒度 Dim = 2D Dim = 3D

0

不支持

不支持

1

2x2

2x2x2

2

4x2

不支持

3

4x4

4x4x2

4

8x4

不支持

5

8x8

不支持

6

16x8

不支持

7

16x16

不支持

8

不支持

不支持

9

不支持

不支持

10

不支持

16x16x16

11

64x64

32x16x16

12

128x64

32x32x16

13

128x128

32x32x32

14

256x128

64x32x32

15

256x256

不支持

Coarse 输入用于在使用 mipmapModeVK_SAMPLER_MIPMAP_MODE_LINEAR 时,在纹素过滤期间可能访问的两个 mip 级别之间进行选择。当在两个 mip 级别之间进行过滤时,Coarse 值为 true 表示请求较低分辨率 mip 级别(较高级别编号)中的足迹,而 false 表示请求较高分辨率 mip 级别中的足迹。如果纹素过滤仅访问单个 mip 级别,则当 Coarsefalse 时,将返回该级别中的足迹;当 Coarsetrue 时,将返回空足迹。

OpImageSampleFootprintNV 的足迹在一个包含六个成员的结构中返回。

  • 第一个成员是一个布尔值,如果纹素过滤操作仅访问单个 mip 级别,则该值为 true。

  • 第二个成员是一个两分量或三分量整数向量,其中包含足迹锚点位置。对于二维图像,返回的分量以 8 个纹素组为单位。对于三维图像,返回的分量以 4 个纹素组为单位。

  • 第三个成员是一个两分量或三分量整数向量,其中包含相对于锚点的足迹偏移量。所有返回的分量均以纹素组为单位。

  • 第四个成员是一个两分量整数向量掩码,其中包含一个位域,用于标识相对于锚点和偏移量的 8x8 或 4x4x4 邻域中的纹素组集。

  • 第五个成员是一个整数,用于标识包含由锚点、偏移量和掩码标识的足迹的 mip 级别。

  • 第六个成员是一个整数,用于标识返回的足迹的粒度。

对于二维图像 (Dim2D) 中的足迹,OpImageSampleFootprintNV 返回的掩码指示在纹素过滤期间,8x8 局部纹素组邻域中的每个纹素组是否会访问一个或多个纹素。在掩码中,如果且仅当以下条件成立时,具有局部组坐标 被认为是覆盖的。

其中

  • ;以及

  • 是返回的双组分掩码。

如果纹理过滤操作会访问一个或多个 遮罩中坐标的局部组,当且仅当纹理过滤操作会访问返回的 mip 层级中的一个或多个纹理元素

并且

  • ;

  • 是一个双分量向量,保存了由粒度标识的纹素组的宽度和高度;

  • 是返回的双分量锚点向量;以及

  • 是返回的双分量偏移向量。

对于三维图像(Dim3D)中的足迹,OpImageSampleFootprintNV 返回的掩码指示在纹理过滤期间,是否会访问 4x4x4 局部纹理组邻域中的每个纹理组的一个或多个纹素。在掩码中,局部组坐标为 的纹理组,当且仅当

其中

  • , , 以及 \(0 \leq lgz < 4\); 并且

  • 是返回的双组分掩码。

The local group with coordinates in the mask is considered covered if and only if the texel filtering operation would access one or more texels in the returned mip level where

并且

  • , , ;

  • 是一个三组件向量,它保存了由粒度标识的纹素组的宽度、高度和深度;

  • 是返回的三组件锚点向量;并且

  • 是返回的三分量偏移向量。

如果 OpImageSampleFootprintNV 使用的采样器通过 anisotropyEnable 启用了各向异性纹素过滤,则在 mip 级别中访问的纹素组集合可能太大,无法使用指令中请求的粒度以 8x8 或 4x4x4 掩码表示。在这种情况下,实现会使用大于请求粒度的纹素组。当使用较大的纹素组大小时,OpImageSampleFootprintNV 会返回一个整数粒度值,该值可以以与提供给指令的粒度值相同的方式解释,以确定所使用的纹素组大小。如果在采样器中禁用各向异性纹素过滤,或者如果各向异性足迹可以表示为具有请求粒度的 8x8 或 4x4x4 掩码,则 OpImageSampleFootprintNV 将按原样使用请求的粒度,并返回零的粒度值。

OpImageSampleFootprintNV 仅支持二维和三维图像访问(Dim2DDim3D),并且如果采样器使用除 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE 之外的寻址模式,则返回的足迹是未定义的。

权重图像采样

SPIR-V 指令 OpImageWeightedSampleQCOM 指定一个涉及两个图像的纹理采样操作:采样图像权重图像。它类似于双线性过滤,但可能参与过滤的纹素多于 2x2 个,并且过滤权重是应用程序指定的,而不是由固定功能硬件计算的。权重图像视图定义了采样期间使用的 2D 内核权重。

OpImageWeightedSampleQCOM 支持归一化或非归一化的纹素坐标。除了等效 OpImageSample* 指令将接受的输入之外,OpImageWeightedSampleQCOM 还接受一个 weight 输入,该输入指定采样权重图像的视图。

输入 weight必须是具有 miplevels 等于 1samples 等于 VK_SAMPLE_COUNT_1_BIT、使用恒等换算创建且使用包括 VK_IMAGE_USAGE_SAMPLE_WEIGHT_BIT_QCOMusage 创建的 2D 或 1D 图像的视图。VkImageViewSampleWeightCreateInfoQCOM 指定了视图的其他参数:filterCenterfilterSizenumPhases,详见下文。

weight 输入必须使用采样权重图像描述符类型绑定。weight 视图定义一个过滤内核,该内核是视图子资源范围的区域。内核跨越从整数纹素坐标 (0,0)(filterSize.x-1, filterSize.y-1) 的区域。视图的子资源具有大于内核的尺寸是有效的,但是具有大于 (filterSize.width-1, filterSize.height-1) 的整数坐标的纹素将被权重采样忽略。查询 OpImageQuerySizeOpImageQuerySizeLodOpImageQueryLevelsOpImageQuerySamples 为权重图像返回的值是未定义的。

filterCenter 将过滤内核中的整数纹素坐标指定为内核的“中心”。该中心必须(0,0)(filterSize.x-1, filterSize.y-1) 的范围内。numPhases 描述用于提供亚像素过滤的过滤阶段数。两者将在下面更详细地描述。

权重图像布局

权重图像指定过滤内核权重值。2D 图像视图可用于指定 2D 过滤权重矩阵。对于可分离的过滤器,可以使用 1D 图像视图来指定水平和垂直权重。

2D 不可分离的权重过滤器

使用 VkImageViewSampleWeightCreateInfoQCOM 定义的 2D 图像视图描述了一个权重元素的 2D 矩阵 (filterSize.width × filterSize.height),其滤波器中心点位于 filterCenter。请注意,filterSize 可以小于视图的子资源,但滤波器将始终位于整数纹素坐标 (0,0) 开始的位置。

下图展示了一个 2D 卷积滤波器,其 filterSize(4,3)filterCenter 位于 (1, 1)

weight filter 2d
图 10. 2D 卷积滤波器

对于 2D 权重滤波器,相位存储为 2D 数组图像的层。视图的子资源范围的宽度和高度必须小于或等于 VkPhysicalDeviceImageProcessingPropertiesQCOM::maxWeightFilterDimension。这些层以水平相位主序存储。用公式表示,每个滤波器相位的层索引计算如下:

layerIndex(horizPhase,vertPhase,horizPhaseCount) = (vertPhase * horizPhaseCount) + horizPhase

1D 可分离权重滤波器

可分离权重滤波器是一种 2D 滤波器,它可以通过 xy 方向上的两个 1D 滤波器指定,它们的乘积得到 2D 滤波器。以下示例展示了一个 2D 滤波器及其相关的可分离 1D 水平和垂直滤波器。

weight filter 1d separable
图 11. 可分离 2D 卷积滤波器

使用 VkImageViewSampleWeightCreateInfoQCOM 定义且 layerCount 等于 “2” 的 1D 数组图像视图描述了一个可分离的权重滤波器。水平权重在切片 “0” 中指定,垂直权重在切片 “1” 中指定。filterSizefilterCenter 指定水平和垂直滤波器的大小和原点。对于许多用例,1D 可分离滤波器可以提供比 2D 滤波器更好的性能。

对于 1D 可分离权重滤波器,相位被排列成具有两层的 1D 数组图像。水平权重存储在第 0 层,垂直权重存储在第 1 层。在 1D 数组图像的每一层中,权重被排列成 4 个一组,然后按相位排列。用公式表示,每一层中每个权重的 1D 纹素偏移量计算如下:

// Let horizontal weights have a weightIndex of [0, filterSize.width - 1]
// Let vertical weights have a weightIndex of [0, filterSize.height - 1]
// Let phaseCount be the number of phases in either the vertical or horizontal direction.

texelOffset(phaseIndex,weightIndex,phaseCount) = (phaseCount * 4 * (weightIndex / 4)) + (phaseIndex * 4) + (weightIndex % 4)

权重采样相位

当使用权重图像采样时,纹理坐标可能与采样图像中的纹素中心不对齐。在这种情况下,可以根据子像素位置调整滤波器权重。这被称为“子像素滤波”,表示滤波器的原点位于纹素中心以外的子像素位置。从概念上讲,这意味着权重滤波器的位置使得滤波器抽头与采样的纹素不能完全对齐。在这种情况下,可能需要修改后的滤波器权重来调整偏离中心的滤波器抽头。与双线性滤波不同,在双线性滤波中,子像素权重由实现计算,子像素权重图像采样要求每个相位的滤波器权重由应用程序预先计算并存储在一个数组中,其中数组的每个切片都是一个“滤波器相位”。该数组由实现根据子像素定位进行索引。应用程序提供的是一个内核数组,而不是单个 2D 滤波器权重内核,每个相位对应一组滤波器权重。

相位的数量受到以下要求的限制,这些要求适用于可分离和不可分离的滤波器

  • 垂直方向的相位数,phaseCountvert必须是 2 的幂(即 1、2、4 等)。

  • 水平方向的相位数 phaseCounthoriz必须等于 phaseCountvert

  • 相位的总数 phaseCountvert × phaseCounthoriz必须小于或等于 VkPhysicalDeviceImageProcessingPropertiesQCOM::maxWeightFilterPhases

权重采样器参数

权重采样要求 VkSamplerCreateInfoaddressModeUaddressModeV 必须VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGEVK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER。如果使用 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,则边框颜色必须VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK

权重采样操作

The 2D unnormalized texel coordinates are transformed by to specify coordinates .

其中 VkImageViewSampleWeightCreateInfoQCOM::filterCenter 指定。

Two sets of neighboring integer 2D texel coordinates are generated. The first set is used for selecting texels from the sampled image and the second set used for selecting texels from the weight image . The first set of neighboring coordinates are combinations of to and to . The second set of neighboring coordinates are combinations of to and to . The first and second sets each contain \((filterWidth \times filterHeight)\) of pairs of and coordinates respectively.

where and are specified by VkImageViewSampleWeightCreateInfoQCOM::filterSize.

每个生成的整数坐标 经过纹理环绕操作转换,然后进行整数纹素坐标验证。如果任何坐标未通过坐标验证,则为边界纹素,并执行纹素替换

相位索引 是从非标准化 2D 纹素坐标的小数位计算得出的。

where the number of fraction bits retained is specified by VkImageViewSampleWeightCreateInfoQCOM::numPhases

Each pair of texel coordinates in the first set selects a single texel value from the sampled image. Each pair of texel coordinates in the second set, combined with phaseIndex , selects a single weight from the weight image .

If is a 2D array view, then non-separable filtering is specified, and integer coordinates are used to select texels from layer of . If is a 1D array view, then separable filtering is specified and integer coordinates are transformed to , and used to select horizontal weight and vertical weight texels from layer 0 and layer 1 of respectively.

其中 指的是整数模运算符。

多个纹素的值与其权重组合在一起,以产生过滤后的值。

VkSamplerReductionModeCreateInfo::reductionModeVK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE 时,使用上述求和公式。但是,如果缩减模式为 VK_SAMPLER_REDUCTION_MODE_MINVK_SAMPLER_REDUCTION_MODE_MAX,则对上述值进行操作,计算具有非零权重的纹素的逐分量最小值或最大值。如果缩减模式为 VK_SAMPLER_REDUCTION_MODE_MINVK_SAMPLER_REDUCTION_MODE_MAX,则每个 权重必须等于 0.0 或 1.0,否则返回未定义的值。

最后,执行 转换为 RGBA组件交换 中描述的操作,并将最终结果返回给着色器。

块匹配

SPIR-V 指令 opImageBlockMatchSADopImageBlockMatchSSD 指定纹理块匹配操作,其中目标图像内的纹素块或区域与参考图像中大小相同的区域进行比较。这些指令使用两个图像视图:目标视图参考视图。目标视图和参考视图可以是同一个视图,允许在单个图像内进行两个块的块匹配。

类似于等效的 OpImageFetch 指令,opImageBlockMatchSADopImageBlockMatchSAD 指定一个 image 和一个整数纹素 coordinate,用于描述目标块的左下纹素。还有三个额外的输入。referencerefCoodinate 指定参考块的左下纹素。blockSize 指定要比较的目标块和参考块的整数宽度和高度,并且必须不大于 VkPhysicalDeviceImageProcessingPropertiesQCOM.maxBlockMatchRegion

opImageBlockMatchWindowSADopImageBlockMatchWindowSAD 采用与相应的非窗口指令相同的输入参数。对于采样器中指定尺寸的二维窗口内的所有像素值执行块匹配比较。

块匹配采样器参数

对于 opImageBlockMatchSADopImageBlockMatchSSD,输入 sampler 必须使用 addressModeUaddressModeV 创建,这两个值等于 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,或等于带有 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACKVK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER。输入 sampler 必须使用等于 VK_TRUEunnormalizedCoordinates 创建。输入 sampler 必须使用等于 VK_COMPONENT_SWIZZLE_IDENTITYcomponents 创建。

对于 opImageBlockMatchWindowSADopImageBlockMatchWindowSSD 指令,target 采样器必须已在 pNext 链中使用 VkSamplerBlockMatchWindowCreateInfoQCOM 创建。

对于 opImageBlockMatchWindowSADopImageBlockMatchWindowSSDopImageBlockMatchGatherSADopImageBlockMatchGatherSSDinstructions,输入 sampler 必须使用 addressModeUaddressModeV 创建,这两个值等于带有 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACKVK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER

忽略其他采样器状态。

块匹配操作

块匹配 SPIR-V 指令 opImageBlockMatchSADopImageBlockMatchSSD 指定了两组 2D 整数纹素坐标:目标坐标 和参考坐标

这些坐标定义了目标块 的左下角纹素以及参考块 \((k_{0}, l_{0})\)。

For the target block, a set of neighboring integer texel coordinates are generated. The neighboring coordinates are combinations of to and to . The set is of size .

where and is specified by the blockSize operand.

如果目标整数纹素坐标集 中任何一个未能通过整数纹素坐标验证,则该纹素为无效纹素,并执行纹素替换

类似地,对于参考块,也会生成一组相邻的整数纹素坐标。

参考纹素坐标集 中的每一个都必须通过整数纹素坐标验证。为了避免未定义的行为,应用程序着色器应保证参考块完全在参考图像的边界内。

Each pair of texel coordinates in the set selects a single texel value from the target image . Each pair of texel coordinates in the set selects a single texel value from the reference image .

目标纹素值和参考纹素值之间的差异被求和以计算差异度量。opTextureBlockMatchSAD 计算绝对差异之和。

opImageBlockMatchSSD 计算平方差之和。

When VkSamplerReductionModeCreateInfo::reductionMode is VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, the above summation is used. However, if the reduction mode is VK_SAMPLER_REDUCTION_MODE_MIN or VK_SAMPLER_REDUCTION_MODE_MAX, the process operates on the above values, computing a component-wise minimum or maximum of , respectively. For , the minimum or maximum difference is computed and for , the square of the minimum or maximum is computed.

最后,执行转换为RGBA组件置换中描述的操作,并将最终结果返回给着色器。组件置换由目标图像描述符指定;由参考图像描述符指定的任何置换都将被忽略。

块匹配窗口操作

窗口块匹配 SPIR-V 指令 opImageBlockMatchWindowSADopImageBlockMatchWindowSSD 指定了两组 2D 整数纹素坐标:目标坐标 和参考坐标 块匹配操作 会针对指定窗口内的多组目标整数坐标重复执行。这些指令有效地在目标纹理内的区域或“窗口”中搜索,并标识出找到最小或最大误差度量的窗口坐标。这些指令仅支持单分量图像格式。

The target coordinates are combinations of coordinates from to where and are specified by VkSamplerBlockMatchWindowCreateInfoQCOM::windowExtent. At each target coordinate, a block matching operation is performed, resulting in a difference metric. The reference coordinate is fixed. The block matching operation is repeated \(windowWidth \times windowHeight\) times.

结果的最小或最大误差在输出的 R 分量中返回。整数窗口坐标 在输出的 G 和 B 分量中返回。 A 分量为 0。最小或最大行为由 VkSamplerBlockMatchWindowCreateInfoQCOM::windowCompareMode 选择。

以下伪代码描述了 opImageBlockMatchWindowSAD 的操作。 opImageBlockMatchWindowSSD 的伪代码遵循相同的模式。

vec4 opImageBlockMatchGatherSAD( sampler2D target,
                                 uvec2 targetCoord,
                                 samler2D reference,
                                 uvec2 refCoord,
                                 uvec2 blocksize) {
    // Two parameters are sourced from the VkSampler associated with
    // `target`:
    //    compareMode  (which can be either `MIN` or `MAX`)
    //    uvec2 window (which defines the search window)

    minSAD = INF;
    maxSAD = -INF;
    uvec2 minCoord;
    uvec2 maxCoord;

    for (uint x=0, x<window.width; x++) {
        for (uint y=0; y<window.height; y++) {
            float SAD = textureBlockMatchSAD(target,
                                             targetCoord + uvec2(x, y),
                                             reference,
                                             refCoord,
                                             blocksize).x;
            if (SAD < minSAD) {
                minSAD = SAD;
                minCoord = uvec2(x,y);
            }
            if (SAD > maxSAD) {
                maxSAD = SAD;
                maxCoord = uvec2(x,y);
            }
        }
    }
    if (compareMode==MIN) {
        return vec4(minSAD, minCoord.x, minCoord.y, 0.0);
    } else {
        return vec4(maxSAD, maxCoord.x, maxCoord.y, 0.0);
    }
}

块匹配收集操作

块匹配 Gather SPIR-V 指令 opImageBlockMatchGatherSADopImageBlockMatchGatherSSD 指定两组二维整数纹素坐标:目标坐标 和参考坐标

These instructions perform the block matching operation 4 times, using integer target coordinates , , , and . The R component from each of those 4 operations is gathered and returned in the R, G, B, and A components of the output respectively. For each block match operation, the reference coordinate is . For each block match operation, only the R component of the target and reference images are compared. The following pseudocode describes the operation opImageBlockMatchGatherSAD. The pseudocode for opImageBlockMatchGatherSSD follows an identical pattern.

vec4 opImageBlockMatchGatherSAD(sampler2D target,
                                uvec2 targetCoord,
                                samler2D reference,
                                uvec2 refCoord,
                                uvec2 blocksize) {
    vec4 out;
    for (uint x=0, x<4; x++) {
            float SAD = textureBlockMatchSAD(target,
                                             targetCoord + uvec2(x, 0),
                                             reference,
                                             refCoord,
                                             blocksize).x;
            if (x == 0) {
                out.x = SAD;
            }
            if (x == 1) {
                out.y = SAD;
            }
            if (x == 2) {
                out.z = SAD;
            }
            if (x == 3) {
                out.w = SAD;
            }
    }
    return out;
}

盒式滤波器采样

SPIR-V 指令 OpImageBoxFilterQCOM 指定纹理盒式滤波操作,其中计算纹素区域的加权平均值,权重与每个纹素的覆盖率成正比。

除了等效的 OpImageSample* 指令会接受的输入外,OpImageBoxFilterQCOM 还接受一个额外的输入 boxSize,它指定要平均的区域的宽度和高度(以纹素为单位)。

下图显示了使用 OpImageBoxFilterQCOM8 × 4 纹素二维图像进行采样的示例,其中未标准化的纹理坐标为 (4.125, 2.625)boxSize(2.75, 2.25)。该滤波器将读取 12 个纹素值,并计算基于盒子覆盖的每个纹素部分的权重。

vulkantexture boxFilter
图 12. 盒式滤波器采样示例

如果 boxSize 的高度和宽度都等于 1.0,则此指令将表现为传统的双线性滤波。 boxSize 参数必须大于或等于 1.0,并且必须不大于 VkPhysicalDeviceImageProcessingPropertiesQCOM.maxBoxFilterBlockSize

盒式滤波器采样器参数

输入 sampler 必须使用 addressModeUaddressModeV 创建,它们等于 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,或者 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER 并使用 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK

盒式滤波器操作

2D未归一化的纹素坐标 通过 变换,以指定过滤器左下角纹素的整数纹素坐标 \((i_{0}, j_{0})\)。

where and are specified by the code:(x,y) components of the boxSize operand.

The filter dimensions are computed from the fractional portion of the coordinates and the .

其中 保留的小数位由 VkPhysicalDeviceLimits::subTexelPrecisionBits 指定。

A set of neighboring integer texel coordinates are generated. The neighboring coordinates are combinations of to and to , with being the top-left coordinate of this set. The set is of size .

每个生成的整数坐标 经过纹理环绕操作转换,然后进行整数纹素坐标验证。如果任何坐标未通过坐标验证,则为边界纹素,并执行纹素替换

Horizontal weights to and vertical weights to are computed. Texels that are fully covered by the box will have a horizontal and vertical weight of 1. Texels partially covered by the box will have will have a reduced weights proportional to the coverage.

多个纹素的值,连同它们的水平和垂直权重,组合起来产生一个盒式滤波值。

VkSamplerReductionModeCreateInfo::reductionModeVK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE 时,使用上述求和。但是,如果缩减模式是 VK_SAMPLER_REDUCTION_MODE_MINVK_SAMPLER_REDUCTION_MODE_MAX,则该过程对上述值进行操作,计算纹素的逐分量最小值或最大值。

图像操作步骤

本章中描述的每个步骤都由图像指令的子集执行

  • 纹素输入验证操作、格式转换、纹素替换、转换为 RGBA 和分量混合:由除 OpImageWrite 之外的所有指令执行。

  • 深度比较:由 OpImage*Dref 指令执行。

  • 所有纹素输出操作:由 OpImageWrite 执行。

  • 投影:由所有 OpImage*Proj 指令执行。

  • 导数图像操作、立方体贴图操作、缩放因子操作、LOD 操作和图像级别选择以及纹素各向异性滤波:由所有 OpImageSample*OpImageSparseSample* 指令执行。

  • (s,t,r,q,a) 到 (u,v,w,a) 转换、环绕和 (u,v,w,a) 到 (i,j,k,l,n) 转换和数组层选择:由所有 OpImageSampleOpImageSparseSampleOpImage*Gather 指令执行。

  • 纹素收集:由 OpImage*Gather 指令执行。

  • 纹素足迹评估:由 OpImageSampleFootprint 指令执行。

  • 纹素滤波:由所有 OpImageSample*OpImageSparseSample* 指令执行。

  • 稀疏驻留:由所有 OpImageSparse* 指令执行。

  • (s,t,r,q,a) 到 (u,v,w,a) 转换、环绕和权重图像采样:由 OpImageWeightedSample* 指令执行。

  • (s,t,r,q,a) 到 (u,v,w,a) 转换、环绕和块匹配:由 opImageBlockMatch* 指令执行。

  • (s,t,r,q,a) 到 (u,v,w,a) 转换、环绕和盒式滤波器采样:由 OpImageBoxFilter* 指令执行。

图像查询指令

图像属性查询

OpImageQuerySizeOpImageQuerySizeLodOpImageQueryLevelsOpImageQuerySamples 查询着色器图像操作将访问的图像描述符的属性。如果绑定的描述符为空描述符,则它们返回 0。

OpImageQuerySizeLod 返回由 Level of Detail 操作数标识的图像级别的大小。如果该级别在图像中不存在,并且描述符不为空,则返回的值是未定义的

LOD 查询

OpImageQueryLod 返回在给定图像和坐标的图像操作中将使用的 LOD 参数。如果要访问的描述符是空描述符,则返回 (0,0)。否则,将执行本章中描述的步骤,就像针对 OpImageSampleImplicitLod 一样,直到 缩放因子操作、LOD 操作和图像级别选择。返回值是向量 (λ', dl - levelbase)。这些值可能受限于非常大的、超出范围值的特定于实现的上限和下限。