不变性

Vulkan 规范不是像素精确的。因此,它不保证不同 Vulkan 实现生成的图像完全匹配。但是,该规范在某些情况下指定了同一实现生成的图像的精确匹配。本附录的目的是确定并提供需要精确匹配的情况的理由。

可重复性

最明显和最基本的情况是重复执行一系列 Vulkan 命令。对于任何给定的 Vulkan 和帧缓冲状态向量,以及对于任何 Vulkan 命令,当该命令在该初始 Vulkan 和帧缓冲状态上执行时,所得的 Vulkan 和帧缓冲状态必须相同。当使用包含副作用(图像和缓冲区变量存储以及原子操作)的着色器时,此可重复性要求不适用,因为不能保证这些内存操作以定义的顺序进行处理。

可重复性要求不适用于使用 VK_RASTERIZATION_ORDER_RELAXED_AMD 的图形管线完成的渲染。

可重复性的一个目的是避免在重绘双缓冲场景时出现视觉伪影。如果渲染不可重复,则使用相同命令序列渲染的两个缓冲区之间的交换可能会导致图像中出现可见的变化。这种虚假运动会分散观看者的注意力。可重复性的另一个原因是可测试性。

可重复性虽然重要,但只是一个较弱的要求。仅以可重复性为要求,使用一个(小)多边形更改位置渲染的两个场景可能在每个像素上都不同。这种差异虽然在可重复性的法律范围内,但肯定不在其精神范围内。为了确保有用的操作,需要额外的不可变规则。

多通道算法

不变性对于一整套有用的多通道算法是必要的。此类算法多次渲染,每次使用不同的 Vulkan 模式向量,最终在帧缓冲中产生结果。这些算法的示例包括

  • 通过重新绘制图元,以不同的颜色或使用 XOR 逻辑运算来从帧缓冲中“擦除”图元。

  • 使用模板操作来计算封盖平面。

不变性规则

对于给定的 Vulkan 设备

规则 1 对于任何给定的 Vulkan 和帧缓冲状态向量,以及对于任何给定的 Vulkan 命令,每次在该初始 Vulkan 和帧缓冲状态上执行该命令时,所得的 Vulkan 和帧缓冲状态必须相同。

规则 2 以下状态值的更改没有副作用(任何其他状态值的使用不受更改的影响):

必需

  • 颜色和深度/模板附件内容

  • 剪刀参数(启用除外)

  • 写入掩码(颜色、深度、模板)

  • 清除值(颜色、深度、模板)

强烈建议

  • 模板参数(启用除外)

  • 深度测试参数(启用除外)

  • 混合参数(启用除外)

  • 逻辑运算参数(启用除外)

推论 1 片段生成相对于规则 2 中列出的状态值是不变的。

规则 3 每个片段操作的算术运算是不变的,除非使用直接控制它的参数。

推论 2 使用同一命令序列,同时或单独渲染到同一帧缓冲的不同颜色附件中的图像是像素相同的。

规则 4 相同的管线在多次使用相同输入运行时会产生相同的结果。措辞“相同的管线”是指已使用相同的 SPIR-V 二进制文件和相同的状态创建的 VkPipeline 对象,然后由使用相同 Vulkan 状态向量执行的命令使用。对于具有副作用(例如执行存储或原子操作)的着色器,不变性会放宽。

规则 5 所有有条件或无条件地将 FragCoord.z 赋值给 FragDepth 的片元着色器,对于实际执行了 FragDepth 赋值的片元来说,彼此之间是深度不变的。

如果一系列 Vulkan 命令指定使用包含副作用(图像和缓冲区变量存储以及原子操作)的着色器渲染图元,则不变性规则会放宽。特别是,规则 1、推论 2 和规则 4 在存在着色器副作用的情况下不适用。

以下规则 1 和 4 的较弱版本适用于涉及着色器副作用的 Vulkan 命令

规则 6 对于任何给定的 Vulkan 和帧缓冲状态向量,以及对于任何给定的 Vulkan 命令,任何不受着色器图像或缓冲区变量存储或原子操作结果直接或间接影响的帧缓冲状态的内容,必须在每次在该初始 Vulkan 和帧缓冲状态上执行该命令时都保持相同。

规则 7 只要满足以下条件,相同的管线多次使用相同输入运行时将产生相同的结果:

  • 着色器调用不使用图像原子操作;

  • 除非所有此类存储写入相同的值,否则帧缓冲内存不会被图像存储写入多次;并且

  • 没有着色器调用或执行的其他操作来处理命令序列,读取图像存储写入的内存。

OpenGL 规范具有以下不变性规则:考虑一个通过窗口坐标中的偏移量 (x, y) 平移图元 p 得到的图元 p',其中 x 和 y 是整数。只要 p' 和 p 都没有被裁剪,那么从 p' 产生的每个片元 f' 必须与来自 p 的相应片元 f 相同,只是 f' 的中心与 f 的中心偏移了 (x, y)。

此规则不适用于 Vulkan,并且是与 OpenGL 的有意区别。

当任何 Vulkan 命令序列触发执行图像存储或原子操作的着色器调用,并且后续 Vulkan 命令读取这些着色器调用写入的内存时,这些操作必须显式同步。

细分不变性

当使用包含细分评估着色器的管线时,固定功能细分图元生成器会消耗应用程序指定的输入片,并发出新的图元集。以下不变性规则旨在提供可重复性保证。此外,它们旨在允许使用精心设计的细分评估着色器的应用程序确保为两个相邻片生成的三角形集合在共享片边缘具有相同的顶点,从而避免因共享边缘顶点位置的细微差异而导致的“裂缝”。

规则 1 当处理具有相同外部和内部细分级别的两个片时,只要用于处理片图元的管线具有指定相同细分模式、间距、顶点顺序和点模式修饰的细分评估着色器,细分图元生成器将发出相同的点、线或三角形图元集。如果两组图元包含相同数量和类型的图元,并且对于所有 m 和 n 的值,编号为 n 的图元的编号为 m 的顶点生成的细分坐标相同,则认为这两组图元是相同的。

规则 2 在三角形和四边形细分中,沿细分图元外边缘生成的顶点集合以及每个顶点的细分坐标仅取决于相应的外部细分级别和管线细分着色器中的间距修饰。

规则 3 细分任何外部图元边缘时生成的顶点集合始终是对称的。对于三角形细分,如果细分生成一个细分坐标形式为 (0, x, 1-x)、(x, 0, 1-x) 或 (x, 1-x, 0) 的顶点,它也将生成一个坐标恰好为 (0, 1-x, x)、(1-x, 0, x) 或 (1-x, x, 0) 的顶点。对于四边形细分,如果细分生成一个坐标为 (x, 0) 或 (0, x) 的顶点,它也将生成一个坐标恰好为 (1-x, 0) 或 (0, 1-x) 的顶点。对于等值线细分,如果它在 (0, x) 和 (1, x) 处生成顶点,其中 x 不为零,它也将分别在 (0, 1-x) 和 (1, 1-x) 处生成顶点。

规则 4 在给定相同的外部细分级别和间距的情况下,三角形和四边形细分中细分外部边缘时生成的顶点集合必须独立于细分的特定边缘。例如,如果在三角形细分中细分 w = 0 边缘时生成了 (x, 1 - x, 0) 和 (1-x, x, 0) 处的顶点,则在细分其他相同的 v = 0 边缘时,必须生成 (x, 0, 1-x) 和 (1-x, 0, x) 处的顶点。对于四边形细分,如果在细分 v = 0 边缘时生成了 (x, 0) 和 (1-x, 0) 处的顶点,则在细分其他相同的 u = 0 边缘时,必须生成 (0, x) 和 (0, 1-x) 处的顶点。

规则 5 当处理除了顶点顺序之外在规则 1 中枚举的所有方面都相同的两个片时,为三角形和四边形细分生成的三角形集合必须相同,除了顶点和三角形顺序之外。对于处理第一个片生成的每个三角形 n1,在处理第二个片时必须生成一个三角形 n2,其每个顶点的细分坐标与 n1 中的一个顶点的细分坐标相同。

规则 6 当处理除了匹配的外部细分级别和/或顶点顺序之外在规则 1 中枚举的所有方面都相同的两个片时,为三角形和四边形细分生成的内部三角形集合必须在除顶点和三角形顺序之外的所有方面都相同。对于处理第一个片生成的每个内部三角形 n1,在处理第二个片时必须生成一个三角形 n2,其每个顶点的细分坐标与 n1 中的一个顶点的细分坐标相同。如果细分器生成的三角形的任何顶点都不位于细分图元的外边缘上,则该三角形被视为内部三角形。

规则 7 对于四边形和三角形细分,连接内部和外部边缘的三角形集合仅取决于与该边缘对应的内部和外部细分级别以及间距修饰。

规则 8 TessCoord 的所有已定义组件的值都将在 [0, 1] 范围内。此外,对于 TessCoord 的任何已定义组件 x,在细分评估着色器中计算 1.0-x 的结果将是精确的。如果范围 [0, 1] 中的任何浮点值未能满足此属性,则必须不将此类值用作细分坐标分量。