Direct3D 12 保守光栅化
保守光栅化为像素呈现添加了一些确定性,这特别有助于冲突检测算法。
概述
保守光栅化表示呈现基元至少部分覆盖的所有像素都经过光栅化,这意味着调用像素着色器。 正常行为是采样,如果未启用保守光栅化,则不会使用它。
在很多情况下,保守光栅化非常有用,包括在碰撞检测、遮挡剔除和平铺呈现方面的确定性。
例如,下图显示了使用保守光栅化呈现的绿色三角形,如光栅器中所示(即使用 16.8 固定点顶点坐标)。 棕色区域被称为“不确定性区域”-一个概念区域,表示三角形的扩展边界,需要确保光栅器中的基元相对于原始浮点顶点坐标是保守的。 每个顶点上的红色方块显示如何计算不确定性区域:作为一个横扫方块。
大灰色正方形显示将呈现的像素。 粉红色正方形显示使用“Top-Left 规则”呈现的像素,当三角形的边缘越过像素的边缘时,该规则将发挥作用。 可以有误报(不应设置的像素集),系统通常会,但不总是剔除。
与管道的交互
光栅化规则交互
在保守光栅化模式下,光栅化规则与未启用保守光栅化模式的方式相同,但上述 Top-Left 规则和像素覆盖率除外。 必须使用 16.8 Fixed-Point 光栅器精度。
如果硬件正在使用完整的浮点顶点坐标,则不会覆盖的像素,仅当它们位于固定点域中的不确定区域中没有较大的一半像素时,才可包含这些像素。 未来硬件预计将达到第 2 层中指定的紧缩不确定性区域。 请注意,此要求可防止细化三角形超出必要范围。
类似的有效不确定性区域也适用于 InnerCoverage
,但它更加严格,因为对于这种情况,任何实现都不需要更大的不确定性区域。 有关更多详细信息,请参阅 InnerCoverage 交互。
在固定点域中,内部和外部不确定性区域必须大于或等于子像素网格的一半或 1/512 的大小。 这是最小有效不确定性区域。 1/512 来自 16.8 固定点光栅器坐标表示形式,以及将浮点顶点坐标转换为 16.8 固定点坐标时应用的最接近的规则。 如果光栅器精度发生更改,则 1/512 可能会更改。 如果实现实现实现此最小不确定性区域,则当不确定性区域的边缘或角沿像素边缘或角下降时,它们必须遵循 Top-Left 规则。 不确定区域的剪裁边缘应视为最近的顶点,这意味着它算作两个边缘:在关联的顶点上联接的两个边缘。 使用最小不确定性区域时,Top-Left 规则是必需的,因为如果没有,则保守光栅化实现将无法将禁用保守光栅化模式时覆盖的像素光栅化。
下图演示了通过扫描固定点域中基元边缘(即顶点表示法已按 16.8 固定点表示形式量化)生成的有效外部不确定性区域。 此平方的尺寸基于有效的外部不确定性区域大小:对于像素的 1/2,方块的宽度和高度为 1 像素,对于像素的 1/512,正方形为 1/256,宽度和高度的像素为 1/256。 绿色三角形表示给定基元,红色点线表示过度估计的保守光栅化边界,实心黑色正方形表示沿基元边缘横扫的正方形,蓝色复选区域是外部不确定性区域:
多重采样交互
无论 RenderTarget/DepthStencil 图面中的样本数(或者是否正在使用 ForcedSampleCount),所有样本都涵盖由保守光栅化光栅化的像素。 不测试各个示例位置是否位于基元中。
SampleMask 交互
SampleMask 光栅器状态应用的方式与未为 InputCoverage
启用保守光栅化时一样,但不会影响 InnerCoverage
(即它不是使用 InnerCoverage
声明的输入)。 这是因为 InnerCoverage
与 MSAA 样本是否屏蔽无关:0 InnerCoverage
仅表示不保证完全覆盖像素,不保证不会更新任何样本。
深度/模具测试交互
深度/模具测试继续保守光栅化像素的方式与未启用保守光栅化时覆盖所有样本的方式相同。
继续处理涵盖的所有样本可能会导致深度推断有效,并且必须在未启用保守光栅化时将视区固定到视区。 这类似于在 RenderTarget 上使用像素频率内插模式时,样本计数大于 1,尽管在保守光栅化的情况下,它是可推断的固定函数深度测试的深度值。
未定义深度推断的早期深度剔除行为。 这是因为某些早期深度剔除硬件无法正确支持推断的深度值。 但是,即使硬件可以支持推断深度值,早期深度剔除行为也存在问题。 此问题可以通过将像素着色器输入深度固定到要光栅化基元的最小和最大深度值,并将该值写入 oDepth
(像素着色器输出深度寄存器)。 在这种情况下,由于 oDepth
写入,需要实现才能禁用早期深度剔除。
帮助程序像素交互
帮助程序像素规则与未启用保守光栅化时应用的方式相同。 作为其中的一部分,包括帮助程序像素在内的所有像素都必须准确报告 InputCoverage
如 InputCoverage
交互部分中指定的那样。 因此,完全未覆盖的像素报告 0 覆盖率。
输出覆盖率交互
输出覆盖率(oMask
)的行为对于保守光栅化像素的行为,因为它在未启用保守光栅化时,覆盖的所有样本。
InputCoverage 交互
在保守光栅化模式下,此输入寄存器填充,就像未为给定的保守光栅化像素启用保守光栅化时覆盖所有样本一样。 也就是说,所有现有交互都适用(例如 应用 SampleMask),并且 LSB InputCoverage
中的第一个 n 位设置为 1,对于保守光栅化像素,给定 RenderTarget 和/或 DepthStencil 缓冲区绑定在 输出合并处的 n 个样本,或 n 个示例 ForcedSampleCount。 其余位为 0。
无论使用保守光栅化,此输入都可用于着色器,但保守光栅化会更改其行为,仅显示涵盖的所有样本(或帮助程序像素均未显示)。
InnerCoverage 交互
此功能是必需的,并且仅在第 3 层中可用。 当实现支持低于第 3 层的层时,运行时将为使用此模式的着色器创建着色器失败。
像素着色器具有可用的 32 位标量整数系统生成值:InnerCoverage
。 这是一个位字段,仅当保证该像素完全位于当前基元内部时,才会将 LSB 设置为 1 的位字段。 如果未设置位 0,则必须将所有其他输入寄存器位设置为 0,但在位 0 设置为 1 时未定义(实质上,此位字段表示布尔值,其中 false 必须正好为 0,但 true 可以是任何奇数(即位 0 set)非零值)。 此输入用于低估的保守光栅化信息。 它通知像素着色器当前像素是否完全位于几何图形内部。
这必须考虑到在分辨率大于或等于当前 Draw作的分辨率时捕捉错误。 不得有误报(如果像素在分辨率大于或等于当前 Draw 运行的分辨率时未完全覆盖像素,则设置 InnerCoverage
位),但允许误报。 总之,实现不能错误地将像素标识为完全覆盖的像素,该像素不会在光栅器中使用完整的浮点顶点坐标。
如果硬件使用完全浮点顶点坐标,则仅当硬件与固定点域中的内部不确定性区域相交(不能大于子像素网格的大小或像素的 1/256)相交时,才能省略完全覆盖的像素。 另一种方法是,完全在内部不确定性区域的内部边界内的像素必须标记为完全覆盖。 不确定性区域的内部边界在下图中通过粗体黑色虚线来说明。 1/256 来自 16.8 固定点光栅器坐标表示形式,如果光栅器精度发生更改,则这可能会更改。 此不确定性区域足以解释由于将浮点顶点坐标转换为光栅器中固定点顶点坐标而导致的对齐错误。
光栅化规则交互中定义的相同 1/512 最小不确定性区域要求同样适用。
下图演示了通过扫描固定点域中基元边缘(即顶点表示法已按 16.8 固定点表示形式量化)生成的有效内部不确定性区域。 此正方形的尺寸基于有效的内部不确定性区域大小:对于像素的 1/256,正方形的宽度和高度为像素的 1/128。 绿色三角形表示给定基元,粗黑色虚线表示内部不确定性区域的边界,实心黑色正方形表示沿基元边缘横扫的正方形,橙色复选区域是内部不确定性区域:
使用 InnerCoverage
不会影响像素是否保守光栅化,即使用其中一种 InputCoverage
模式不会影响启用保守光栅化模式时将光栅化哪些像素。 因此,使用 InnerCoverage
并且像素着色器正在处理几何图形未完全覆盖的像素,其值将为 0,但像素着色器调用将更新样本。 这与 InputCoverage
为 0 时不同,这意味着不会更新任何示例。
此输入与 InputCoverage
互斥:不能同时使用这两个输入。
若要访问 InnerCoverage
,必须将它声明为像素着色器输入寄存器之一中的单个组件。 声明上的内插模式必须是常量(内插不适用)。
InnerCoverage
位字段不受深度/模具测试的影响,也没有使用 SampleMask 光栅器状态进行 AND。
此输入仅在保守光栅化模式下有效。 如果未启用保守光栅化,InnerCoverage
将生成未定义的值。
由于需要帮助程序像素而引起的像素着色器调用,否则基元未涵盖,必须将 InnerCoverage
寄存器设置为 0。
属性内插交互
属性内插模式保持不变,并且继续的方式与未启用保守光栅化时相同,其中使用了视区缩放和固定点转换顶点。 由于保守光栅化像素中的所有样本都被视为已覆盖,因此对值进行推断是有效的,类似于在 RenderTarget 上使用像素频率内插模式时,其样本计数大于 1 的。 质心内插模式产生的结果与相应的非质心内插模式相同;在此方案中,质心的概念毫无意义 – 其中样本覆盖率仅为完整或 0。
保守光栅化允许退化的三角形生成像素着色器调用,因此,退化三角形必须使用分配给顶点 0 的值用于所有内插值。
剪辑交互
启用保守光栅化模式并禁用深度剪辑(当 DepthClipEnable 光栅器状态设置为 FALSE 时),基元段的属性内插可能存在差异,这些段位于 0 <= z <= w 范围之外,具体取决于实现:基元与相关平面(近或远)相交的点使用任一常量值。 或属性内插的行为与禁用保守光栅化模式时的行为一样。 但是,无论保守光栅化模式如何,深度值行为都是相同的,即超出深度范围的基元仍必须给定视区深度范围最接近限制的值。 0 <= z <= w 范围中的属性内插行为必须保持不变。
剪辑距离交互
启用保守光栅化模式时,剪辑距离有效,并且对于保守光栅化像素的行为,就像未启用保守光栅化时一样,涵盖所有样本。
请注意,保守光栅化可能导致 W 顶点坐标的推断,这可能会导致 W <= 0。 这可能导致每像素剪辑距离实现对已由无效 W 值除以透视的剪辑距离进行作。 剪辑距离实现必须防止对顶点坐标 W <= 0 的像素调用光栅化(例如,在保守光栅化模式下由于外推)。
目标独立光栅化交互
保守光栅化模式与目标独立光栅化(TIR)兼容。 TIR 规则和限制适用,对保守光栅化像素的行为就像覆盖了所有样本一样。
IA 基元拓扑交互
未为线条或点基元定义保守光栅化。 因此,如果基元拓扑在启用保守光栅化时将点或线条馈送到光栅器单元,则它们会产生未定义的行为。
调试层验证验证应用程序不使用这些基元拓扑。
查询交互
对于保守光栅化像素,当覆盖所有样本时,查询的行为就像未启用保守光栅化一样。 例如,对于保守光栅化像素,D3D12_QUERY_TYPE_OCCLUSION和D3D12_QUERY_TYPE_PIPELINE_STATISTICS(从 D3D12_QUERY_TYPE)必须像在覆盖所有样本时未启用保守光栅化时一样。
对于保守光栅化模式下的每个保守光栅化像素,像素着色器调用应递增。
Cull 状态交互
所有 Cull 状态在保守光栅化模式下有效,并遵循与未启用保守光栅化时相同的规则。
将保守光栅化与自身或未启用保守光栅化相比较时,一些基元可能具有不匹配的面容(即一个面向后方,另一个正面)。 应用程序可以通过使用D3D12_CULL_MODE_NONE(从 D3D12_CULL_MODE)而不是使用 IsFrontFace
系统生成的值来避免这种不确定性。
IsFrontFace 交互
IsFrontFace
系统生成的值在保守光栅化模式下有效,并遵循未启用保守光栅化时定义的行为。
填充模式交互
保守光栅化的唯一有效 D3D12_FILL_MODE 是D3D12_FILL_SOLID,任何其他填充模式都是光栅器状态的无效参数。
这是因为 D3D12 功能规范指定线框填充模式应将三角形边缘转换为线条,并遵循线条光栅化规则和保守线光栅化行为尚未定义。
实现详细信息
Direct3D 12 中支持的光栅化类型有时称为“过度引入的保守光栅化”。 还有“低估的保守光栅化”的概念,这意味着仅对呈现基元完全覆盖的像素进行光栅化。 低估的保守光栅化信息可通过像素着色器通过输入覆盖率数据获得,并且只有过度估计的保守光栅化可用作光栅化模式。
如果基元的任何部分与像素重叠,则认为该像素已覆盖,然后进行光栅化。 当基元的边缘或角沿像素的边缘或角下降时,“左上角规则”的应用特定于实现。 但是,对于支持退化三角形的实现,边缘或角上的退化三角形必须至少覆盖一个像素。
保守光栅化实现在不同硬件上可能有所不同,并生成误报,这意味着它们可以错误地决定覆盖像素。 这可能是由于特定于实现的详细信息,例如基元增长或贴靠在光栅化中使用的固定点顶点坐标固有的错误。 误报(相对于固定点顶点坐标)有效的原因是,需要一些误报,以便实现对贴靠顶点(即已从浮点转换为光栅器中使用的 16.8 固定点的顶点的顶点坐标)进行覆盖评估,但遵循原始浮点顶点坐标生成的覆盖。
保守光栅化实现不会针对非退化后贴靠基元的浮点顶点坐标生成误报:如果基元的任何部分与像素的任何部分重叠,则该像素将光栅化。
退化的三角形(索引缓冲区中的重复索引或 3D 中的合音线),或在固定点转换后退化(光栅器中的合音顶点),可以或可能不会被剔除:这两者都是有效的行为。 必须将退化的三角形视为背对,因此,如果应用程序需要特定行为,则可以对正面使用后脸剔除或测试。 退化三角形使用分配给顶点 0 的值来表示所有内插值。
除了硬件不支持此功能的可能性外,还有三层硬件支持。
- 第 1 层强制实施最大 1/2 像素不确定性区域,并且不支持后快照退化。 这适用于平铺呈现、纹理图集、光线贴图生成和子像素阴影地图。
- 第 2 层将最大不确定性区域减少到 1/256,并且要求不剔除快照后退化。 此层适用于基于 CPU 的算法加速(如体素化)。
- 第 3 层保持最大 1/256 不确定性区域,并增加了对内部输入覆盖率的支持。 内部输入覆盖率将新值
SV_InnerCoverage
添加到高级底纹语言(HLSL)。 这是一个 32 位标量整数,可在像素着色器的输入上指定,并表示低估的保守光栅化信息(即是否保证像素-to-be完全覆盖)。 此层有助于遮挡剔除。
API 摘要
以下方法、结构、枚举和帮助程序类引用保守光栅化:
- D3D12_RASTERIZER_DESC:包含光栅器说明的结构。
- D3D12_CONSERVATIVE_RASTERIZATION_MODE:模式的枚举值(打开或关闭)。
- D3D12_FEATURE_DATA_D3D12_OPTIONS:包含支持层的结构。
- D3D12_CONSERVATIVE_RASTERIZATION_TIER:硬件支持的每个层的枚举值。
- CheckFeatureSupport:访问支持的功能的方法。
- CD3DX12_RASTERIZER_DESC:用于创建光栅器说明的帮助程序类。
相关主题