光栅化
光栅化是将图元转换为二维图像的过程。此图像的每个离散位置都包含诸如深度、颜色或其他属性之类的相关数据。
光栅化图元首先确定帧缓冲坐标中整数网格的哪些正方形被该图元占据,并为每个此类正方形分配一个或多个深度值。下面描述了点、线和多边形的此过程。
网格正方形,包括其 (x,y) 帧缓冲坐标、z(深度)以及片段着色器添加的相关数据,称为片段。片段由其左上角定位,该左上角位于整数网格坐标上。
光栅化操作还指片段的采样位置,这些采样位置与片段左上角偏移了分数的值。点、线和三角形的光栅化规则包括测试每个采样位置是否在图元内部。片段实际上不必是正方形,并且光栅化规则不受片段纵横比的影响。但是,显示非正方形网格会导致光栅化的点和线段在一个方向上看起来比另一个方向更粗。
我们假设片段是正方形的,因为它简化了抗锯齿和纹理处理。光栅化后,片段由片段操作处理。
几个因素会影响光栅化,包括 VkPipelineRasterizationStateCreateInfo 和 VkPipelineMultisampleStateCreateInfo 的成员。
VkPipelineRasterizationStateCreateInfo
结构定义如下:
// Provided by VK_VERSION_1_0
typedef struct VkPipelineRasterizationStateCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineRasterizationStateCreateFlags flags;
VkBool32 depthClampEnable;
VkBool32 rasterizerDiscardEnable;
VkPolygonMode polygonMode;
VkCullModeFlags cullMode;
VkFrontFace frontFace;
VkBool32 depthBiasEnable;
float depthBiasConstantFactor;
float depthBiasClamp;
float depthBiasSlopeFactor;
float lineWidth;
} VkPipelineRasterizationStateCreateInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
保留供将来使用。 -
depthClampEnable
控制是否如 深度测试中所述来钳制片段的深度值。如果管线不是使用 VkPipelineRasterizationDepthClipStateCreateInfoEXT 创建的,则启用深度钳制也会禁用将图元裁剪到视锥体的 z 平面,如 图元裁剪中所述。否则,深度裁剪由 VkPipelineRasterizationDepthClipStateCreateInfoEXT 中设置的状态控制。 -
rasterizerDiscardEnable
控制是否在光栅化阶段之前立即丢弃图元。 -
polygonMode
是三角形渲染模式。请参阅 VkPolygonMode。 -
cullMode
是用于图元剔除的三角形朝向方向。请参阅 VkCullModeFlagBits。 -
frontFace
是一个 VkFrontFace 值,用于指定用于剔除的正面三角形方向。 -
depthBiasEnable
控制是否偏置片段深度值。 -
depthBiasConstantFactor
是一个标量因子,用于控制添加到每个片段的常量深度值。 -
depthBiasClamp
是片段的最大(或最小)深度偏置。 -
depthBiasSlopeFactor
是一个标量因子,应用于深度偏置计算中片段的斜率。 -
lineWidth
是光栅化线段的宽度。
应用程序可以还将 VkPipelineRasterizationStateRasterizationOrderAMD
结构添加到 VkPipelineRasterizationStateCreateInfo 结构的 pNext
链。此结构启用选择使用相应的图形管线渲染时要使用的光栅化顺序,如 光栅化顺序中所述。
// Provided by VK_VERSION_1_0
typedef VkFlags VkPipelineRasterizationStateCreateFlags;
VkPipelineRasterizationStateCreateFlags
是用于设置掩码的位掩码类型,但当前保留供将来使用。
如果 VkPipelineRasterizationStateCreateInfo 的 pNext
链包含 VkPipelineRasterizationDepthClipStateCreateInfoEXT
结构,则该结构控制是否启用或禁用深度裁剪。
VkPipelineRasterizationDepthClipStateCreateInfoEXT
结构定义为
// Provided by VK_EXT_depth_clip_enable
typedef struct VkPipelineRasterizationDepthClipStateCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkPipelineRasterizationDepthClipStateCreateFlagsEXT flags;
VkBool32 depthClipEnable;
} VkPipelineRasterizationDepthClipStateCreateInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
保留供将来使用。 -
depthClipEnable
控制是否启用 图元裁剪 中所述的深度裁剪。
// Provided by VK_EXT_depth_clip_enable
typedef VkFlags VkPipelineRasterizationDepthClipStateCreateFlagsEXT;
VkPipelineRasterizationDepthClipStateCreateFlagsEXT
是用于设置掩码的位掩码类型,但当前保留供将来使用。
VkPipelineMultisampleStateCreateInfo
结构定义为
// Provided by VK_VERSION_1_0
typedef struct VkPipelineMultisampleStateCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineMultisampleStateCreateFlags flags;
VkSampleCountFlagBits rasterizationSamples;
VkBool32 sampleShadingEnable;
float minSampleShading;
const VkSampleMask* pSampleMask;
VkBool32 alphaToCoverageEnable;
VkBool32 alphaToOneEnable;
} VkPipelineMultisampleStateCreateInfo;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
保留供将来使用。 -
rasterizationSamples
是一个 VkSampleCountFlagBits 值,指定光栅化中使用的样本数。如果管道是使用设置的VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT
动态状态创建的,则此值将被忽略,不用于设置光栅化中使用的样本数,但如果未设置VK_DYNAMIC_STATE_SAMPLE_MASK_EXT
动态状态,则它仍用于定义如下所述的pSampleMask
数组的大小。 -
sampleShadingEnable
可以用于启用 样本着色。 -
如果
sampleShadingEnable
为VK_TRUE
,则minSampleShading
指定样本着色的最小比例。 -
pSampleMask
是指向用于 样本掩码测试 的VkSampleMask
值数组的指针。 -
alphaToCoverageEnable
控制是否基于片段的第一个颜色输出的 alpha 分量生成临时覆盖值,如 多重采样覆盖 部分中所指定。 -
alphaToOneEnable
控制是否将片段的第一个颜色输出的 alpha 分量替换为 1,如 多重采样覆盖 中所述。
样本掩码中的每个位都与唯一的 样本索引 相关联,如 覆盖掩码 所定义。样本掩码中掩码字 w
的每个位 b
对应于样本索引 i
,其中 i = 32 × w + b
。pSampleMask
的长度等于 ⌈ rasterizationSamples
/ 32 ⌉ 个字。
如果 pSampleMask
为 NULL
,则将其视为掩码的所有位都设置为 1
。
// Provided by VK_VERSION_1_0
typedef VkFlags VkPipelineMultisampleStateCreateFlags;
VkPipelineMultisampleStateCreateFlags
是用于设置掩码的位掩码类型,但目前保留供将来使用。
样本掩码数组的元素类型为 VkSampleMask
,每个元素代表 32 位覆盖信息。
// Provided by VK_VERSION_1_0
typedef uint32_t VkSampleMask;
光栅化仅生成覆盖帧缓冲区内一个或多个像素的片段。 帧缓冲区外的像素永远不会被视为片段的覆盖范围。 由下面描述的任何图元光栅化规则的应用产生的,但位于帧缓冲区之外的片段不会被生成,也不会被管道的任何后续阶段处理,包括任何片段操作。
幸存的片段由片段着色器处理。 片段着色器确定片段的关联数据,并且可以修改或替换其指定的深度值。
光栅化前丢弃图元
如果启用 VkPipelineRasterizationStateCreateInfo 的 rasterizerDiscardEnable
成员,则在光栅化之前丢弃图元。启用后,图元在光栅化之前由管道中最后一个活动的着色器阶段处理后会被丢弃。
要动态启用是否在光栅化阶段之前丢弃图元,请调用
// Provided by VK_VERSION_1_3
void vkCmdSetRasterizerDiscardEnable(
VkCommandBuffer commandBuffer,
VkBool32 rasterizerDiscardEnable);
或等效命令
// Provided by VK_EXT_extended_dynamic_state2, VK_EXT_shader_object
void vkCmdSetRasterizerDiscardEnableEXT(
VkCommandBuffer commandBuffer,
VkBool32 rasterizerDiscardEnable);
-
commandBuffer
是将记录命令的命令缓冲区。 -
rasterizerDiscardEnable
控制是否在光栅化阶段之前立即丢弃图元。
当使用 着色器对象进行绘制时,或者当使用 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置的 VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE
创建图形管线时,此命令将为后续绘制命令设置丢弃启用。 否则,此状态由用于创建当前活动管线的 VkPipelineRasterizationStateCreateInfo::rasterizerDiscardEnable
值指定。
控制用于光栅化的顶点流
默认情况下,来自最后一个光栅化前着色器阶段输出的顶点数据被定向到顶点流零。几何着色器可以将图元发射到多个独立的顶点流。几何着色器发射的每个顶点都指向其中一个顶点流。当每个顶点流上接收到顶点时,它们将被排列成几何着色器输出图元类型指定的图元。着色语言指令 OpEndPrimitive
和 OpEndStreamPrimitive
可以用于结束在给定顶点流上组装的图元并启动相同类型的新空图元。一个实现支持多达 VkPhysicalDeviceTransformFeedbackPropertiesEXT
::maxTransformFeedbackStreams
个流,至少为 1。单个流的编号为 0 到 maxTransformFeedbackStreams
减 1。对于发射顶点的流的顺序没有要求,并且发射到每个顶点流的顶点数量可以完全独立,仅受 VkPhysicalDeviceTransformFeedbackPropertiesEXT
::maxTransformFeedbackStreamDataSize
和 VkPhysicalDeviceTransformFeedbackPropertiesEXT
::maxTransformFeedbackBufferDataSize
限制。来自所有顶点流的图元被传递到变换反馈阶段,以便按照最后一个 光栅化前着色器阶段着色器的图形管线中输出接口变量上的 XfbBuffer
、XfbStride
和 Offsets
装饰所指定的方式捕获到变换反馈缓冲区。要使用除零以外的顶点流,或者使用多个流,必须指定 GeometryStreams
功能。
默认情况下,来自顶点流零的图元被光栅化。如果该实现支持 VkPhysicalDeviceTransformFeedbackPropertiesEXT::transformFeedbackRasterizationStreamSelect
属性,则可以光栅化除零以外的顶点流。
默认情况下,将顶点发射到多个顶点流的几何着色器仅限于使用 OutputPoints
输出图元类型。如果实现支持 VkPhysicalDeviceTransformFeedbackPropertiesEXT::transformFeedbackStreamsLinesTriangles
属性,则除了 OutputPoints
之外,还可以发射 OutputLineStrip
或 OutputTriangleStrip
。
用于光栅化的顶点流通过将 VkPipelineRasterizationStateStreamCreateInfoEXT
结构添加到 VkPipelineRasterizationStateCreateInfo 结构的 pNext
链中来指定。
VkPipelineRasterizationStateStreamCreateInfoEXT
结构的定义如下:
// Provided by VK_EXT_transform_feedback
typedef struct VkPipelineRasterizationStateStreamCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkPipelineRasterizationStateStreamCreateFlagsEXT flags;
uint32_t rasterizationStream;
} VkPipelineRasterizationStateStreamCreateInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
保留供将来使用。 -
rasterizationStream
是为光栅化选择的顶点流。
如果此结构不存在,则假定 rasterizationStream
为零。
// Provided by VK_EXT_transform_feedback
typedef VkFlags VkPipelineRasterizationStateStreamCreateFlagsEXT;
VkPipelineRasterizationStateStreamCreateFlagsEXT
是用于设置掩码的位掩码类型,但目前保留供将来使用。
要动态设置 rasterizationStream
状态,请调用:
// Provided by VK_EXT_extended_dynamic_state3 with VK_EXT_transform_feedback, VK_EXT_shader_object with VK_EXT_transform_feedback
void vkCmdSetRasterizationStreamEXT(
VkCommandBuffer commandBuffer,
uint32_t rasterizationStream);
-
commandBuffer
是将记录命令的命令缓冲区。 -
rasterizationStream
指定rasterizationStream
状态。
当使用着色器对象进行绘制,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT
时创建时,此命令会设置后续绘制命令的 rasterizationStream
状态。否则,此状态由用于创建当前活动管线的 VkPipelineRasterizationStateStreamCreateInfoEXT::rasterizationStream
值指定。
光栅化顺序
在 渲染通道实例的子通道中,对于给定的 (x,y,layer,sample) 采样位置,对于包括该采样位置的每个单独的图元,以下操作保证按照光栅化顺序执行:
子通道中每个图元的这些操作的执行顺序由应用程序确定。
用于图形管线的光栅化顺序通过将 VkPipelineRasterizationStateRasterizationOrderAMD
结构添加到 VkPipelineRasterizationStateCreateInfo 结构的 pNext
链中来指定。
VkPipelineRasterizationStateRasterizationOrderAMD
结构的定义如下:
// Provided by VK_AMD_rasterization_order
typedef struct VkPipelineRasterizationStateRasterizationOrderAMD {
VkStructureType sType;
const void* pNext;
VkRasterizationOrderAMD rasterizationOrder;
} VkPipelineRasterizationStateRasterizationOrderAMD;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
rasterizationOrder
是一个 VkRasterizationOrderAMD 值,指定要使用的图元光栅化顺序。
如果未启用 VK_AMD_rasterization_order
设备扩展,或者应用程序未通过指定 VkPipelineRasterizationStateRasterizationOrderAMD
结构来请求特定的光栅化顺序,则图形管线使用的光栅化顺序默认为 VK_RASTERIZATION_ORDER_STRICT_AMD
。
指定图元光栅化顺序的 VkPipelineRasterizationStateRasterizationOrderAMD::rasterizationOrder
的可能值如下:
// Provided by VK_AMD_rasterization_order
typedef enum VkRasterizationOrderAMD {
VK_RASTERIZATION_ORDER_STRICT_AMD = 0,
VK_RASTERIZATION_ORDER_RELAXED_AMD = 1,
} VkRasterizationOrderAMD;
多重采样
多重采样是一种对所有 Vulkan 图元(点、线和多边形)进行抗锯齿的机制。该技术是在每个像素处对所有图元进行多次采样。每个帧缓冲附件中的每个采样都有存储颜色、深度和/或模板值的空间,因此每个片段操作独立应用于每个采样。颜色采样值稍后可以解析为单个颜色(有关如何将多重采样图像解析为非多重采样图像的更多详细信息,请参阅解析多重采样图像和 渲染通道章节)。
Vulkan 定义单采样模式的光栅化规则,其方式等效于在每个片段中心具有单个采样的多重采样模式。
每个片段都包含一个覆盖掩码,其中每个片段的每个采样点都有一个位,以及每个采样点的一些深度值和相关数据。
可以理解为每个像素都关联有 rasterizationSamples
个位置。这些位置是精确的位置,而不是区域或面积,每个位置都称为采样点。与像素关联的采样点必须位于被认为是像素边界的单位正方形内或边界上。此外,对于帧缓冲区中的每个像素,采样点的相对位置可能相同,也可能不同。
如果渲染通道具有片段密度图附件,则每个片段只有 rasterizationSamples
个关联位置,而无论片段区域覆盖了多少像素。片段采样位置的定义就像片段的面积为 (1,1) 一样,并且其采样点必须位于这些边界内。它们在帧缓冲区中的实际位置是通过将采样位置按片段面积缩放来计算的。每个像素存储多个采样的附件位于像素采样位置。否则,片段的采样位置通常用于评估相关数据和片段操作。
如果当前管线包含一个片段着色器,其接口中有一个或多个变量用 Sample
和 Input
修饰,则这些变量关联的数据将为每个采样点单独分配。每个采样点的值必须在采样点的位置进行评估。与任何其他未用 Sample
和 Input
修饰的变量关联的数据无需为每个采样点单独评估。
会为每个片段生成一个覆盖掩码,该掩码基于该片段中确定位于生成该片段的图元区域内的采样点。
由片段密度图定义的单像素片段和多像素片段有一组采样点。由着色率图像定义的多像素片段每个像素都有一组采样点。通过设置片段着色率定义的多像素片段每个像素都有一组采样点。每组采样点都具有由 VkPipelineMultisampleStateCreateInfo::rasterizationSamples
确定的采样点数量。集合中的每个采样点都被分配一个唯一的采样索引 i,范围为 [0, rasterizationSamples
)。
要动态设置 rasterizationSamples
,请调用
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetRasterizationSamplesEXT(
VkCommandBuffer commandBuffer,
VkSampleCountFlagBits rasterizationSamples);
-
commandBuffer
是将记录命令的命令缓冲区。 -
rasterizationSamples
指定rasterizationSamples
。
在使用着色器对象进行绘制时,或者在图形管线创建时,在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT
时,此命令将为后续的绘制命令设置 rasterizationSamples
。否则,此状态由用于创建当前活动管线的 VkPipelineMultisampleStateCreateInfo::rasterizationSamples
值指定。
片段中的每个采样点还被分配了一个唯一的覆盖索引 j,范围为 [0, n × rasterizationSamples
),其中 n 是片段中集合的数量。如果片段包含一组采样点,则覆盖索引始终等于采样索引。如果使用了着色率图像并且一个片段覆盖了多个像素,则覆盖索引的确定方式如 VkPipelineViewportCoarseSampleOrderStateCreateInfoNV 或 vkCmdSetCoarseSampleOrderNV 中定义的那样。
如果设置了片段着色率,则覆盖索引 j 被确定为像素索引 p、采样索引 i 和光栅化采样点数量 r 的函数,如下所示:
-
j = i + r × ((fw × fh) - 1 - p)
其中,像素索引 p 被确定为像素的帧缓冲区位置 (x,y) 和片段大小 (fw,fh) 的函数,如下所示:
-
px = x % fw
-
py = y % fh
-
p = px + (py × fw)
下表说明了多像素片段的像素索引
1x1 | 1x2 | 1x4 |
---|---|---|
2x1 | 2x2 | 2x4 |
---|---|---|
4x1 | 4x2 | 4x4 |
---|---|---|
覆盖掩码包括 B 位,打包到 W 个字中,定义为:
-
B = n ×
rasterizationSamples
-
W = ⌈B/32⌉
如果覆盖索引 j = 32×w + b 的采样点被覆盖,则覆盖掩码字 w 中的位 b 为 1
,否则为 0
。
如果 VkPhysicalDeviceLimits 的 standardSampleLocations
成员为 VK_TRUE
,则采样计数 VK_SAMPLE_COUNT_1_BIT
、VK_SAMPLE_COUNT_2_BIT
、VK_SAMPLE_COUNT_4_BIT
、VK_SAMPLE_COUNT_8_BIT
和 VK_SAMPLE_COUNT_16_BIT
具有下表中列出的采样位置,表中第 i 个条目对应于采样索引 i。VK_SAMPLE_COUNT_32_BIT
和 VK_SAMPLE_COUNT_64_BIT
没有标准的采样位置。位置是相对于片段左上角的原点定义的。
采样计数 | 采样位置 | |
---|---|---|
|
(0.5,0.5) |
|
|
(0.75,0.75) |
|
|
(0.375, 0.125) |
|
|
(0.5625, 0.3125) |
|
|
(0.5625, 0.5625) |
使用每个像素多个采样点创建的颜色图像使用一种压缩技术,其中每个像素都关联有两个数据数组。第一个数组包含每个采样点一个元素,其中每个元素存储一个索引,指向定义像素片段掩码的第二个数组。第二个数组包含每个颜色片段一个元素,并且每个元素以图像的格式存储一个唯一的颜色值。使用这种压缩技术,并不总是需要为每个颜色采样点实际使用唯一的存储位置:当多个采样点共享相同的颜色值时,片段掩码可能有两个采样点引用相同的颜色片段。颜色片段的数量由用于创建图像的 VkImageCreateInfo 结构的 samples
成员确定。 VK_AMD_shader_fragment_mask
设备扩展提供了着色器指令,使应用程序能够直接访问片段掩码和各个颜色片段值。
自定义采样位置
应用程序可以控制用于光栅化的采样位置。
如果在管线创建时指定的 VkPipelineMultisampleStateCreateInfo 结构的 pNext
链中包含 VkPipelineSampleLocationsStateCreateInfoEXT
结构,那么该结构将控制管线光栅化图元时使用的采样位置。
VkPipelineSampleLocationsStateCreateInfoEXT
结构的定义如下:
// Provided by VK_EXT_sample_locations
typedef struct VkPipelineSampleLocationsStateCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkBool32 sampleLocationsEnable;
VkSampleLocationsInfoEXT sampleLocationsInfo;
} VkPipelineSampleLocationsStateCreateInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
sampleLocationsEnable
控制是否使用自定义采样位置。如果sampleLocationsEnable
为VK_FALSE
,则使用默认的采样位置,并忽略sampleLocationsInfo
中指定的值。 -
如果
sampleLocationsEnable
为VK_TRUE
且图形管线不是使用VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT
创建的,则sampleLocationsInfo
是光栅化期间要使用的采样位置。
VkSampleLocationsInfoEXT
结构的定义如下:
// Provided by VK_EXT_sample_locations
typedef struct VkSampleLocationsInfoEXT {
VkStructureType sType;
const void* pNext;
VkSampleCountFlagBits sampleLocationsPerPixel;
VkExtent2D sampleLocationGridSize;
uint32_t sampleLocationsCount;
const VkSampleLocationEXT* pSampleLocations;
} VkSampleLocationsInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
sampleLocationsPerPixel
是一个 VkSampleCountFlagBits 值,指定每个像素的采样位置数。 -
sampleLocationGridSize
是用于选择自定义采样位置的采样位置网格的大小。 -
sampleLocationsCount
是pSampleLocations
中采样位置的数量。 -
pSampleLocations
是指向sampleLocationsCount
个 VkSampleLocationEXT 结构数组的指针。
此结构可以用于指定渲染时要使用的采样位置,或者用于指定深度/模板图像子资源上次渲染时使用的采样位置集,以便进行使用 VK_IMAGE_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_EXT
创建的深度/模板图像的布局转换。
pSampleLocations
中的采样位置为 sampleLocationGridSize
中指定大小的网格中的每个像素指定 sampleLocationsPerPixel
个采样位置。像素网格位置 (x,y) 处的第 i 个采样的采样位置取自 pSampleLocations
[(x + y × sampleLocationGridSize.width
) × sampleLocationsPerPixel
+ i]。
如果渲染通道具有片段密度图,则实现将为片段选择采样位置,并且可能会忽略 pSampleLocations
的内容。
VkSampleLocationEXT
结构的定义如下:
// Provided by VK_EXT_sample_locations
typedef struct VkSampleLocationEXT {
float x;
float y;
} VkSampleLocationEXT;
-
x
是采样位置的水平坐标。 -
y
是采样位置的垂直坐标。
采样位置坐标的域空间在帧缓冲区空间内的像素中具有左上角原点。
在 VkSampleLocationEXT
结构中指定的值始终被限制在与实现相关的采样位置坐标范围 [sampleLocationCoordinateRange
[0],sampleLocationCoordinateRange
[1]] 内,该范围可以使用 VkPhysicalDeviceSampleLocationsPropertiesEXT 查询。
要动态设置 sampleLocationsEnable
状态,请调用:
// Provided by VK_EXT_extended_dynamic_state3 with VK_EXT_sample_locations, VK_EXT_sample_locations with VK_EXT_shader_object
void vkCmdSetSampleLocationsEnableEXT(
VkCommandBuffer commandBuffer,
VkBool32 sampleLocationsEnable);
-
commandBuffer
是将记录命令的命令缓冲区。 -
sampleLocationsEnable
指定sampleLocationsEnable
状态。
当使用 着色器对象 绘图时,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT
时创建时,此命令将为后续绘图命令设置 sampleLocationsEnable
状态。否则,此状态由用于创建当前活动管线的 VkPipelineSampleLocationsStateCreateInfoEXT::sampleLocationsEnable
值指定。
要动态设置用于光栅化的采样位置,请调用:
// Provided by VK_EXT_sample_locations
void vkCmdSetSampleLocationsEXT(
VkCommandBuffer commandBuffer,
const VkSampleLocationsInfoEXT* pSampleLocationsInfo);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pSampleLocationsInfo
是要设置的采样位置状态。
当使用 着色器对象 绘图时,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT
且绑定图形管线的 VkPipelineSampleLocationsStateCreateInfoEXT::sampleLocationsEnable
属性为 VK_TRUE
时,此命令将为后续绘图命令设置自定义采样位置。否则,此状态由用于创建当前活动管线的 VkPipelineSampleLocationsStateCreateInfoEXT::sampleLocationsInfo
值指定。
片段着色率
VkPhysicalDeviceFragmentShadingRateFeaturesKHR 公告的功能允许应用程序控制给定片段着色器调用的着色率。
片段着色率与多重采样密切相关,并且实现的可用速率集合可能受到采样率的限制。
要查询可用的着色率,请调用
// Provided by VK_KHR_fragment_shading_rate
VkResult vkGetPhysicalDeviceFragmentShadingRatesKHR(
VkPhysicalDevice physicalDevice,
uint32_t* pFragmentShadingRateCount,
VkPhysicalDeviceFragmentShadingRateKHR* pFragmentShadingRates);
-
physicalDevice
是要查询其属性的物理设备的句柄。 -
pFragmentShadingRateCount
是指向与可用或查询的片段着色率数量相关的整数的指针,如下所述。 -
pFragmentShadingRates
要么为NULL
,要么是指向 VkPhysicalDeviceFragmentShadingRateKHR 结构体数组的指针。
如果 pFragmentShadingRates
为 NULL
,则可用片段着色率的数量将返回在 pFragmentShadingRateCount
中。否则,pFragmentShadingRateCount
必须指向应用程序设置为 pFragmentShadingRates
数组中元素数量的变量,并且在返回时,该变量将被实际写入到 pFragmentShadingRates
的结构体数量覆盖。如果 pFragmentShadingRateCount
小于可用片段着色率的数量,则最多将写入 pFragmentShadingRateCount
个结构体,并且将返回 VK_INCOMPLETE
而不是 VK_SUCCESS
,以表明并非所有可用的片段着色率都被返回。
返回的片段着色率数组必须按照从最大 fragmentSize.width
值到最小值的顺序排列,并且每个具有相同 fragmentSize.width
值的片段着色率集合必须按照从最大 fragmentSize.height
到最小值的顺序排列。数组中的任何两个条目必须不具有相同的 fragmentSize
值。
对于数组中的任何条目,还适用以下规则
-
fragmentSize.width
的值必须小于或等于maxFragmentSize.width
。 -
fragmentSize.width
的值必须大于或等于1
。 -
fragmentSize.width
的值必须是 2 的幂。 -
fragmentSize.height
的值必须小于或等于maxFragmentSize.height
。 -
fragmentSize.height
的值必须大于或等于1
。 -
fragmentSize.height
的值必须是 2 的幂。 -
sampleCounts
中的最高采样计数必须小于或等于maxFragmentShadingRateRasterizationSamples
。 -
fragmentSize.width
、fragmentSize.height
和sampleCounts
中的最高采样计数的乘积必须小于或等于maxFragmentShadingRateCoverageSamples
。
实现必须至少支持以下着色率
sampleCounts |
fragmentSize |
---|---|
|
{2,2} |
|
{2,1} |
~0 |
{1,1} |
如果 framebufferColorSampleCounts
包括 VK_SAMPLE_COUNT_2_BIT
,则所需的速率必须还包括 VK_SAMPLE_COUNT_2_BIT
。
包含 {1,1} 片段大小是为了完整性;它对不设置片段大小的渲染支持没有实际影响。所有采样计数和渲染通道变换都支持此速率。 |
返回的片段着色率集合必须以本机(旋转)坐标系返回。对于使用不等于 VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
的渲染通道 transform
进行的栅格化,应用程序必须将返回的片段着色率变换到当前(未旋转)坐标系,以获得该变换的支持速率。
例如,考虑一个实现返回支持 4x2 但不支持 2x4 的受支持片段着色率集。这意味着对于变换 |
VkPhysicalDeviceFragmentShadingRateKHR
结构定义如下:
// Provided by VK_KHR_fragment_shading_rate
typedef struct VkPhysicalDeviceFragmentShadingRateKHR {
VkStructureType sType;
void* pNext;
VkSampleCountFlags sampleCounts;
VkExtent2D fragmentSize;
} VkPhysicalDeviceFragmentShadingRateKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
sampleCounts
是一个位掩码,表示fragmentSize
描述的着色率支持的采样计数。 -
fragmentSize
是一个 VkExtent2D,描述了受支持着色率的宽度和高度。
片元着色率可以在三个点设置,三个速率组合起来以确定最终的着色率。
管线片元着色率
管线片元着色率 可以通过在图形管线中设置速率,或通过 vkCmdSetFragmentShadingRateKHR 动态设置,从而在每次绘制时设置。
VkPipelineFragmentShadingRateStateCreateInfoKHR
结构定义如下:
// Provided by VK_KHR_fragment_shading_rate
typedef struct VkPipelineFragmentShadingRateStateCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkExtent2D fragmentSize;
VkFragmentShadingRateCombinerOpKHR combinerOps[2];
} VkPipelineFragmentShadingRateStateCreateInfoKHR;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
fragmentSize
指定一个 VkExtent2D 结构,其中包含用于定义使用此管线的绘制命令的管线片元着色率的片元大小。 -
combinerOps
指定一个 VkFragmentShadingRateCombinerOpKHR 值,该值确定 管线、图元 和 附件着色率 如何为使用创建的管线的绘制命令生成的片元进行 组合。
如果 VkGraphicsPipelineCreateInfo 的 pNext
链中包含 VkPipelineFragmentShadingRateStateCreateInfoKHR
结构,则该结构包含控制管线片元着色率的参数。
如果此结构不存在,则认为 fragmentSize
等于 (1,1),并且认为 combinerOps
的两个元素都等于 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR
。
要动态设置管线片元着色率和组合器操作,请调用:
// Provided by VK_KHR_fragment_shading_rate
void vkCmdSetFragmentShadingRateKHR(
VkCommandBuffer commandBuffer,
const VkExtent2D* pFragmentSize,
const VkFragmentShadingRateCombinerOpKHR combinerOps[2]);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pFragmentSize
指定后续绘制命令的管线片元着色率。 -
combinerOps
指定一个 VkFragmentShadingRateCombinerOpKHR,它确定 管线、图元 和 附件着色率 如何为后续绘制命令生成的片元进行 组合。
当使用着色器对象进行绘制,或者当图形管线创建时,在VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR
时,此命令为后续绘制命令设置管线片元着色率和组合器操作。否则,此状态由用于创建当前活动管线的 VkPipelineFragmentShadingRateStateCreateInfoKHR 值指定。
图元片元着色率
图元片元着色率 可以通过最后一个活动的光栅化前着色器阶段中的 PrimitiveShadingRateKHR
内建变量设置。如果最后一个光栅化前着色器阶段正在使用 MeshEXT
Execution
Model
,则与给定图元相关的速率来源于写入每个图元的 PrimitiveShadingRateKHR
的值。否则,与给定图元相关的速率来源于该图元的起始顶点写入 PrimitiveShadingRateKHR
的值。
附件片元着色率
附件着色率 可以通过在子通道中包含 VkFragmentShadingRateAttachmentInfoKHR 来设置,以定义一个片元着色率附件。帧缓冲中的每个像素都根据以下公式,通过片元着色率附件中的相应纹素分配一个附件片元着色率:
-
x' = floor(x / regionx)
-
y' = floor(y / regiony)
其中 x' 和 y' 是片元着色率附件中纹素的坐标,x 和 y 是帧缓冲中像素的坐标,regionx 和 regiony 是每个纹素对应的区域大小,由 VkFragmentShadingRateAttachmentInfoKHR 的 shadingRateAttachmentTexelSize
成员定义。
如果 启用了多视口,并且着色率附件具有多个图层,则使用 layer = ViewIndex
选择着色率附件纹素。如果禁用了多视口,并且着色率附件和帧缓冲都具有多个图层,则使用 layer = Layer
选择着色率附件纹素。否则,layer = 0。
纹素是从片元着色率附件图像中读取的,作为纹理输入操作,不使用采样器,使用整数坐标 i = x'、j = y'、k = 0、l = layer 和 s = 0。片元大小被编码到该操作结果的第一个分量中,如下所示:
-
sizew = 2((texel/4)&3)
-
sizeh = 2(texel&3)
其中 texel 是返回值的第一个分量中的值,sizew 和 sizeh 是片元大小的宽度和高度,从纹素解码而来。
如果未指定片元着色率附件,则此大小计算为 sizew = sizeh = 1。应用程序必须不能通过此方法指定大于 4 的宽度或高度。
SPIR-V 中的片元着色率枚举遵循上述编码。
合并片元着色率
用于片元着色的最终速率 (Cxy') 必须是由 vkGetPhysicalDeviceFragmentShadingRatesKHR 返回的用于光栅化所使用的采样计数和渲染通道变换的速率之一。
如果满足以下任何条件,则实现会将 Cxy' 设置为 {1,1}
-
如果启用了采样着色。
-
不支持
fragmentShadingRateWithSampleMask
限制,并且 VkPipelineMultisampleStateCreateInfo::pSampleMask
在片元操作使用的任何位中都包含零值。 -
不支持
fragmentShadingRateWithShaderSampleMask
限制,并且片元着色器的输入或输出接口中具有SampleMask
。 -
不支持
fragmentShadingRateWithShaderDepthStencilWrites
限制,并且片元着色器声明了FragDepth
或FragStencilRefEXT
内建变量。 -
不支持
fragmentShadingRateWithConservativeRasterization
限制,并且 VkPipelineRasterizationConservativeStateCreateInfoEXT::conservativeRasterizationMode
不是VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT
。 -
不支持
fragmentShadingRateWithFragmentShaderInterlock
限制,并且片元着色器声明了任何片元着色器互锁执行模式。 -
不支持
fragmentShadingRateWithCustomSampleLocations
限制,并且 VkPipelineSampleLocationsStateCreateInfoEXT::sampleLocationsEnable
为VK_TRUE
。 -
片元着色器声明了
TileImageColorReadAccessEXT
、TileImageDepthReadAccessEXT
或TileImageStencilReadAccessEXT
功能中的任何一个。
每个合并操作所使用的公式由 VkFragmentShadingRateCombinerOpKHR
定义
// Provided by VK_KHR_fragment_shading_rate
typedef enum VkFragmentShadingRateCombinerOpKHR {
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR = 0,
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR = 1,
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR = 2,
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR = 3,
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR = 4,
} VkFragmentShadingRateCombinerOpKHR;
-
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR
指定的合并操作为 combine(Axy,Bxy) = Axy。 -
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR
指定的合并操作为 combine(Axy,Bxy) = Bxy。 -
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR
指定的合并操作为 combine(Axy,Bxy) = min(Axy,Bxy)。 -
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR
指定的合并操作为 combine(Axy,Bxy) = max(Axy,Bxy)。 -
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR
指定组合操作为 combine(Axy,Bxy) = Axy*Bxy。
其中 combine(Axy,Bxy) 是组合操作,而 Axy 和 Bxy 是该操作的输入。
如果 fragmentShadingRateStrictMultiplyCombiner
为 VK_FALSE
,则在同一维度上,使用 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR
并将 A 和 B 的值都设置为 1 将导致该维度产生值 2。 有关详细信息,请参阅 fragmentShadingRateStrictMultiplyCombiner
的定义。
这些操作以分量方式执行。
这用于使用以下等式生成组合的片元区域:
-
Cxy = combine(Axy,Bxy)
其中 Cxy 是组合的片元区域结果,而 Axy 和 Bxy 是被组合的片元着色率的片元区域。
执行两个组合操作,首先将 Axy 等于管线片元着色率,并将 Bxy 等于图元片元着色率,使用 combinerOps[0] 选择的 combine() 操作。然后执行第二个组合,将 Axy 等于第一个组合的结果,并将 Bxy 等于附件片元着色率,使用 combinerOps[1] 选择的 combine() 操作。第二个组合的结果用作最终片元着色率,并通过ShadingRateKHR
内置变量报告。
如果 VkPhysicalDeviceMaintenance6Properties
::fragmentShadingRateClampCombinerInputs
为 VK_TRUE
,则实现**应该**钳制组合器操作 Axy 和 Bxy 的输入,并且**必须**这样做。所有实现**必须**钳制第二个组合器操作的结果。
表示 Axy、Bxy 或 Cxy 的任何一个的片元着色率 Rxy 按如下方式钳制。如果 Rxy 是 vkGetPhysicalDeviceFragmentShadingRatesKHR 针对光栅化使用的样本计数和渲染通道转换返回的速率之一,则钳制的着色率 Rxy' 为 Rxy。否则,钳制的着色率将从 vkGetPhysicalDeviceFragmentShadingRatesKHR 针对光栅化使用的样本计数和渲染通道转换返回的速率中选择。从支持速率列表中,按顺序应用以下步骤以选择单个值:
-
仅保留满足 Rx' ≤ Rx 且 Ry' ≤ Ry 的速率。
-
实现**可能**还会保留满足 Rx' ≤ Ry 且 Ry' ≤ Rx 的速率。
-
-
仅保留具有最高区域(Rx' × Ry')的速率。
-
仅保留具有最低纵横比(Rx' + Ry')的速率。
-
在剩余宽速率(例如 4x1)和高速率(例如 1x4)的情况下,实现**可能**选择任一速率。但是,对于相同的着色率,渲染通道转换和组合器操作,在VkDevice的生命周期内,**必须**一致地选择此速率。
扩展片元着色率
VkPhysicalDeviceFragmentShadingRateEnumsFeaturesNV 公告的功能支持超出指定一个片元着色器调用覆盖片元中所有像素的额外的片元着色率,其大小由片元着色率指示。
如果启用了fragmentShadingRateEnums
功能,则可以使用定义为 VkFragmentShadingRateNV 枚举类型指定片元着色率:
// Provided by VK_NV_fragment_shading_rate_enums
typedef enum VkFragmentShadingRateNV {
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV = 0,
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV = 1,
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV = 4,
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV = 5,
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV = 6,
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV = 9,
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV = 10,
VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV = 11,
VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV = 12,
VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV = 13,
VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV = 14,
VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV = 15,
} VkFragmentShadingRateNV;
-
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV
指定的片元大小为 1x1 像素。 -
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV
指定的片元大小为 1x2 像素。 -
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV
指定的片元大小为 2x1 像素。 -
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV
指定的片元大小为 2x2 像素。 -
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV
指定的片元大小为 2x4 像素。 -
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV
指定的片元大小为 4x2 像素。 -
VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV
指定的片元大小为 4x4 像素。 -
VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV
指定的片元大小为 1x1 像素,每个片元有两个片元着色器调用。 -
VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV
指定的片元大小为 1x1 像素,每个片元有四个片元着色器调用。 -
VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV
指定的片元大小为 1x1 像素,每个片元有八个片元着色器调用。 -
VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV
指定的片元大小为 1x1 像素,每个片元有十六个片元着色器调用。 -
VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV
指定应丢弃使用该着色率的图元的任何部分,而不调用任何片元着色器。
要将着色率 VK_FRAGMENT_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV
、VK_FRAGMENT_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV
、VK_FRAGMENT_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV
和 VK_FRAGMENT_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV
用作管线、图元或附件着色率,**必须**启用supersampleFragmentShadingRates
功能。要将着色率 VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV
用作管线、图元或附件着色率,**必须**启用noInvocationFragmentShadingRates
功能。
使用片元着色率枚举时,可以通过在图形管线中设置速率,或通过 vkCmdSetFragmentShadingRateEnumNV 动态设置管线片元着色率(在每次绘制的基础上)。
VkPipelineFragmentShadingRateEnumStateCreateInfoNV
结构定义为
// Provided by VK_NV_fragment_shading_rate_enums
typedef struct VkPipelineFragmentShadingRateEnumStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkFragmentShadingRateTypeNV shadingRateType;
VkFragmentShadingRateNV shadingRate;
VkFragmentShadingRateCombinerOpKHR combinerOps[2];
} VkPipelineFragmentShadingRateEnumStateCreateInfoNV;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
shadingRateType
指定一个 VkFragmentShadingRateTypeNV 值,该值指示是否使用片元大小或 VkFragmentShadingRateNV 枚举指定片元着色率。 -
shadingRate
指定一个 VkFragmentShadingRateNV 值,该值指示管线片元着色率。 -
combinerOps
指定 VkFragmentShadingRateCombinerOpKHR 值,这些值确定如何将 管线、图元和附件着色率对于使用创建的管线绘制命令生成的片元进行组合。
如果 VkGraphicsPipelineCreateInfo 的 pNext
链包含 VkPipelineFragmentShadingRateEnumStateCreateInfoNV
结构,则该结构包含控制管线片元着色率的参数。
如果此结构不存在,则认为 shadingRateType
等于 VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV
,认为 shadingRate
等于 VK_FRAGMENT_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV
,并且认为 combinerOps
的两个元素都等于 VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR
。
VkFragmentShadingRateTypeNV 枚举类型指定图形管线是从 VkPipelineFragmentShadingRateEnumStateCreateInfoNV 结构体还是从 VkPipelineFragmentShadingRateStateCreateInfoKHR 结构体获取其管线片段着色率和组合器。
// Provided by VK_NV_fragment_shading_rate_enums
typedef enum VkFragmentShadingRateTypeNV {
VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV = 0,
VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV = 1,
} VkFragmentShadingRateTypeNV;
-
VK_FRAGMENT_SHADING_RATE_TYPE_FRAGMENT_SIZE_NV
指定图形管线应从 VkPipelineFragmentShadingRateStateCreateInfoKHR 结构体获取其管线片段着色率和着色率组合器状态,并且应忽略 VkPipelineFragmentShadingRateEnumStateCreateInfoNV 结构体指定的任何状态。 -
VK_FRAGMENT_SHADING_RATE_TYPE_ENUMS_NV
指定图形管线应从 VkPipelineFragmentShadingRateEnumStateCreateInfoNV 结构体获取其管线片段着色率和着色率组合器状态,并且应忽略 VkPipelineFragmentShadingRateStateCreateInfoKHR 结构体指定的任何状态。
要动态设置管线片元着色率和组合器操作,请调用:
// Provided by VK_NV_fragment_shading_rate_enums
void vkCmdSetFragmentShadingRateEnumNV(
VkCommandBuffer commandBuffer,
VkFragmentShadingRateNV shadingRate,
const VkFragmentShadingRateCombinerOpKHR combinerOps[2]);
-
commandBuffer
是将记录命令的命令缓冲区。 -
shadingRate
指定一个 VkFragmentShadingRateNV 枚举值,表示后续绘制命令的管线片段着色率。 -
combinerOps
指定一个 VkFragmentShadingRateCombinerOpKHR,它确定 管线、图元 和 附件着色率 如何为后续绘制命令生成的片元进行 组合。
当使用 着色器对象进行绘制,或者在创建图形管线时,在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR
时,此命令将为后续绘制命令设置管线片段着色率和组合器操作。否则,此状态由用于创建当前活动管线的 VkPipelineFragmentShadingRateEnumStateCreateInfoNV 值指定。
此命令允许指定超出 vkCmdSetFragmentShadingRateKHR 支持的其他着色率。有关更多信息,请参阅 |
当启用 supersampleFragmentShadingRates
或 noInvocationFragmentShadingRates
功能时,着色率组合器操作的行为会扩展为支持这些功能启用的着色率。图元和附件着色率值被解释为 VkFragmentShadingRateNV 值,并且组合器的行为修改如下:
-
对于
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR
、VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR
和VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR
,如果 Axy 或 Bxy 中任何一个是VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV
,则 combine(Axy,Bxy) 产生一个着色率VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV
,而不管另一个输入着色率如何。 -
对于
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR
,combine(Axy,Bxy) 产生的着色率,其片段大小是 Axy 和 Bxy 的片段大小中较小的一个,其调用计数是 Axy 和 Bxy 的调用计数中较大的一个。 -
对于
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR
,combine(Axy,Bxy) 产生的着色率,其片段大小是 Axy 和 Bxy 的片段大小中较大的一个,其调用计数是 Axy 和 Bxy 的调用计数中较小的一个。 -
对于
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR
,combine(Axy,Bxy) 产生的着色率,其片段大小和调用计数分别是 Axy 和 Bxy 的片段大小和调用计数的乘积。如果生成的着色率在每个片段中都有多个像素和多个调用,则实现可以通过减少像素和调用计数来调整着色率。
如果来自组合器的最终着色率为 VK_FRAGMENT_SHADING_RATE_NO_INVOCATIONS_NV
,则不会为使用该着色率的任何图元部分生成任何片段。
如果来自组合器的最终着色率指定每个片段有多个片段着色器调用,则该片段将按照 采样着色 中的方式用多个唯一采样进行处理,其中调用的总数从着色率中获取,然后钳制到 rasterizationSamples
和 maxFragmentShadingRateInvocationCount
。
着色率图像
shadingRateImage
功能允许管线使用着色率图像来控制片段区域以及每个片段启动的最少片段着色器调用次数。当启用着色率图像时,光栅化器通过从着色率图像中获取一个值,并使用每个视口的着色率调色板将其转换为着色率,从而确定由图元覆盖的帧缓冲区的每个区域的基本着色率。然后调整这个基本着色率以得出最终着色率。最终着色率指定了在该区域生成的片段要使用的片段区域和片段着色器调用计数。
如果 VkPipelineViewportStateCreateInfo 的 pNext
链包含 VkPipelineViewportShadingRateImageStateCreateInfoNV
结构体,则该结构体包含控制着色率的参数。
VkPipelineViewportShadingRateImageStateCreateInfoNV
结构体定义如下:
// Provided by VK_NV_shading_rate_image
typedef struct VkPipelineViewportShadingRateImageStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkBool32 shadingRateImageEnable;
uint32_t viewportCount;
const VkShadingRatePaletteNV* pShadingRatePalettes;
} VkPipelineViewportShadingRateImageStateCreateInfoNV;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
shadingRateImageEnable
指定在光栅化期间是否使用着色率图像和调色板。 -
viewportCount
指定用于转换存储在着色率图像中的值的每个视口的调色板的数量。 -
pShadingRatePalettes
是指向一个 VkShadingRatePaletteNV 结构体数组的指针,该数组为每个视口定义调色板。如果着色率调色板状态是动态的,则忽略此成员。
如果此结构体不存在,则认为 shadingRateImageEnable
为 VK_FALSE
,并且不使用着色率图像和调色板。
当在绑定的管线中启用着色率图像使用时,管线会使用以下命令指定的着色率图像:
// Provided by VK_NV_shading_rate_image
void vkCmdBindShadingRateImageNV(
VkCommandBuffer commandBuffer,
VkImageView imageView,
VkImageLayout imageLayout);
-
commandBuffer
是将记录命令的命令缓冲区。 -
imageView
是一个图像视图句柄,用于指定着色率图像。imageView
可以为 VK_NULL_HANDLE,这相当于指定一个填充了零值的图像视图。 -
imageLayout
是当访问着色率图像时,可以从imageView
访问的图像子资源所处的布局。
When the shading rate image is enabled in the current pipeline, rasterizing a primitive covering the pixel with coordinates (x,y) will fetch a shading rate index value from the shading rate image bound by vkCmdBindShadingRateImageNV
. If the shading rate image view has a type of VK_IMAGE_VIEW_TYPE_2D
, the lookup will use texel coordinates (u,v) where \(u = \left\lfloor \frac{x}{twidth} \right\rfloor\), \(v = \left\lfloor \frac{y}{theight} \right\rfloor\), and and are the width and height of the implementation-dependent shading rate texel size. If the shading rate image view has a type of VK_IMAGE_VIEW_TYPE_2D_ARRAY
, the lookup will use texel coordinates (u,v) to extract a texel from the layer l, where l is the layer of the framebuffer being rendered to. If l is greater than or equal to the number of layers in the image view, layer zero will be used.
如果绑定的着色率图像视图不是 VK_NULL_HANDLE,并且包含层 *l*(如果适用)中坐标为 (*u*, *v*) 的纹素,则该纹素的单个无符号整数分量将用作着色率索引。如果 (*u*, *v*) 坐标在着色率图像视图使用的子资源的范围之外,或者如果图像视图是 VK_NULL_HANDLE,则着色率索引为零。如果着色率图像视图有多个 mipmap 级别,则将使用 VkImageSubresourceRange
::baseMipLevel
标识的基本级别。
着色率索引使用一个名为着色率图像调色板的查找表映射到基本着色率。每个视口都有一个单独的调色板。每个调色板中的条目数由实现相关的着色率图像调色板大小给出。
要动态设置 shadingRateImageEnable
状态,请调用
// Provided by VK_EXT_extended_dynamic_state3 with VK_NV_shading_rate_image, VK_EXT_shader_object with VK_NV_shading_rate_image
void vkCmdSetShadingRateImageEnableNV(
VkCommandBuffer commandBuffer,
VkBool32 shadingRateImageEnable);
-
commandBuffer
是将记录命令的命令缓冲区。 -
shadingRateImageEnable
指定shadingRateImageEnable
状态。
当使用着色器对象进行绘制时,或者当使用在VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV
的图形管线创建时,此命令为后续的绘图命令设置 shadingRateImageEnable
状态。 否则,此状态由用于创建当前活动管线的VkPipelineViewportShadingRateImageStateCreateInfoNV::shadingRateImageEnable
值指定。
要动态设置每个视口的着色率图像调色板,请调用
// Provided by VK_NV_shading_rate_image
void vkCmdSetViewportShadingRatePaletteNV(
VkCommandBuffer commandBuffer,
uint32_t firstViewport,
uint32_t viewportCount,
const VkShadingRatePaletteNV* pShadingRatePalettes);
-
commandBuffer
是将记录命令的命令缓冲区。 -
firstViewport
是此命令更新其着色率调色板的第一个视口的索引。 -
viewportCount
是此命令更新其着色率调色板的视口数。 -
pShadingRatePalettes
是一个指向 VkShadingRatePaletteNV 结构的数组的指针,这些结构定义了每个视口的调色板。
当使用着色器对象进行绘制时,或者当使用在VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV
的图形管线创建时,此命令为后续的绘图命令设置每个视口的着色率图像调色板。 否则,此状态由用于创建当前活动管线的VkPipelineViewportShadingRateImageStateCreateInfoNV::pShadingRatePalettes
值指定。
VkShadingRatePaletteNV
结构指定单个着色率图像调色板的内容,定义如下:
// Provided by VK_NV_shading_rate_image
typedef struct VkShadingRatePaletteNV {
uint32_t shadingRatePaletteEntryCount;
const VkShadingRatePaletteEntryNV* pShadingRatePaletteEntries;
} VkShadingRatePaletteNV;
-
shadingRatePaletteEntryCount
指定着色率图像调色板中的条目数。 -
pShadingRatePaletteEntries
是一个指向 VkShadingRatePaletteEntryNV 枚举数组的指针,这些枚举定义了每个调色板条目的着色率。
为了确定基本着色率图像,着色率索引 *i* 被映射到与该片段所使用的视口对应的调色板的数组 pShadingRatePaletteEntries
中的数组元素 *i*。 如果 *i* 大于或等于调色板大小 shadingRatePaletteEntryCount
,则基本着色率**未定义**。
支持的着色率图像调色板条目由 VkShadingRatePaletteEntryNV 定义
// Provided by VK_NV_shading_rate_image
typedef enum VkShadingRatePaletteEntryNV {
VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV = 0,
VK_SHADING_RATE_PALETTE_ENTRY_16_INVOCATIONS_PER_PIXEL_NV = 1,
VK_SHADING_RATE_PALETTE_ENTRY_8_INVOCATIONS_PER_PIXEL_NV = 2,
VK_SHADING_RATE_PALETTE_ENTRY_4_INVOCATIONS_PER_PIXEL_NV = 3,
VK_SHADING_RATE_PALETTE_ENTRY_2_INVOCATIONS_PER_PIXEL_NV = 4,
VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV = 5,
VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X1_PIXELS_NV = 6,
VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_1X2_PIXELS_NV = 7,
VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X2_PIXELS_NV = 8,
VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X2_PIXELS_NV = 9,
VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_2X4_PIXELS_NV = 10,
VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_4X4_PIXELS_NV = 11,
} VkShadingRatePaletteEntryNV;
下表显示了使用指示的着色率生成的每个片段的宽度和高度(以像素为单位),以及为每个片段启动的最大片段着色器调用次数。当处理着色率为 VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV
的图元区域时,将不会在该区域中生成任何片段。
着色率 | 宽度 | 高度 | 调用 |
---|---|---|---|
|
0 |
0 |
0 |
|
1 |
1 |
16 |
|
1 |
1 |
8 |
|
1 |
1 |
4 |
|
1 |
1 |
2 |
|
1 |
1 |
1 |
|
2 |
1 |
1 |
|
1 |
2 |
1 |
|
2 |
2 |
1 |
|
4 |
2 |
1 |
|
2 |
4 |
1 |
|
4 |
4 |
1 |
当禁用着色率图像时,将使用 VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV
的着色率作为基本着色率。
一旦确定了基础着色率,就会对其进行调整以产生最终的着色率。首先,如果基础着色率对每个片元使用多个像素,则实现可能会减少片元区域,以确保一个片元中所有像素的覆盖样本总数不超过与实现相关的最大值。
如果当前管线中启用了采样着色,并且在禁用着色率图像时,每个片元将导致处理n (n > 1) 个唯一样本,则会以依赖于实现的方式调整着色率,以增加由图元产生的片元着色器调用次数。如果着色率指示每个片元fs 个像素,且fs 大于 n,则会调整片元区域,使每个片元大约有 个像素。否则,如果着色率指示每个片元ipf 次调用,则片元区域将调整为单个像素,每个片元大约有 次调用。
如果由于使用以 SampleId
或 SamplePosition
修饰的片元着色器输入变量而发生采样着色,则会忽略着色率。每个片元将只有一个像素,并会生成多达 rasterizationSamples
个片元着色器调用,就像在使用 采样着色 而不使用着色率图像时一样。
最后,如果着色率指定每个片元有多个片元着色器调用,则着色率中的调用总数将被限制为不大于 rasterizationSamples
。
当覆盖像素 (x,y) 的图元的最终着色率的片元区域为 , 则该像素的片元将覆盖满足以下方程的所有坐标为 (x',y') 的像素
此组合片元被认为具有多个覆盖采样;此片元中的采样总数由 \(samples = fw \times fh \times rs\) 给出,其中 rs 表示管道创建时指定的 VkPipelineMultisampleStateCreateInfo
::rasterizationSamples
的值。片元中的覆盖采样集是片元中每个像素的每个像素覆盖采样的并集。组合片元中每个像素内的覆盖采样位置和顺序按照 多重采样 和 自定义采样位置 中所述进行分配。属于组合片元的像素集中的每个覆盖采样都被分配一个唯一的 覆盖索引,范围为 [0,samples-1]。如果支持 shadingRateCoarseSampleOrder
特性,则可以为片元区域和覆盖采样计数的每种组合指定覆盖采样的顺序。如果不支持此特性,则采样顺序是实现相关的。
如果 VkPipelineViewportStateCreateInfo 的 pNext
链包含 VkPipelineViewportCoarseSampleOrderStateCreateInfoNV
结构,则该结构包含控制大于一个像素的片元中覆盖采样顺序的参数。
VkPipelineViewportCoarseSampleOrderStateCreateInfoNV
结构的定义如下:
// Provided by VK_NV_shading_rate_image
typedef struct VkPipelineViewportCoarseSampleOrderStateCreateInfoNV {
VkStructureType sType;
const void* pNext;
VkCoarseSampleOrderTypeNV sampleOrderType;
uint32_t customSampleOrderCount;
const VkCoarseSampleOrderCustomNV* pCustomSampleOrders;
} VkPipelineViewportCoarseSampleOrderStateCreateInfoNV;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
sampleOrderType
指定用于对大于一个像素的片元中的覆盖采样进行排序的机制。 -
customSampleOrderCount
指定在排序覆盖采样时要使用的自定义采样顺序的数量。 -
pCustomSampleOrders
是指向customSampleOrderCount
个 VkCoarseSampleOrderCustomNV 结构的数组的指针,每个结构指定片元区域和覆盖采样计数的单个组合的覆盖采样顺序。
如果不存在此结构,则认为 sampleOrderType
为 VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV
。
如果 sampleOrderType
是 VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV
,则在 pCustomSampleOrders
中未枚举的片元区域和覆盖采样计数的任何组合使用的覆盖采样顺序将与 VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV
使用的覆盖采样顺序相同。
如果管道创建时使用了 VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV
,则忽略此结构(如果存在)的内容,并且覆盖采样顺序改为由 vkCmdSetCoarseSampleOrderNV 指定。
类型 VkCoarseSampleOrderTypeNV 指定用于对大于一个像素的片元中的覆盖采样进行排序的技术,并定义为
// Provided by VK_NV_shading_rate_image
typedef enum VkCoarseSampleOrderTypeNV {
VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV = 0,
VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV = 1,
VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV = 2,
VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV = 3,
} VkCoarseSampleOrderTypeNV;
-
VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV
指定覆盖采样将以实现定义的方式排序。 -
VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV
指定覆盖采样将根据VkPipelineViewportCoarseSampleOrderStateCreateInfoNV
的pCustomSampleOrders
成员或 vkCmdSetCoarseSampleOrderNV 的pCustomSampleOrders
成员中提供的自定义排序数组进行排序。 -
VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV
指定覆盖采样将按顺序排序,首先按像素坐标(按行主序),然后按采样索引排序。 -
VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV
指定覆盖采样将按顺序排序,首先按采样索引排序,然后按像素坐标(按行主序)排序。
When using a coarse sample order of VK_COARSE_SAMPLE_ORDER_TYPE_PIXEL_MAJOR_NV
for a fragment with an upper-left corner of with a width of \(fw \times fh\) and samples per pixel, coverage index of the fragment will be assigned to sample index of pixel as follows
当使用粗采样顺序 VK_COARSE_SAMPLE_ORDER_TYPE_SAMPLE_MAJOR_NV
时,覆盖索引 将按如下方式分配
VkCoarseSampleOrderCustomNV
结构的定义如下:
// Provided by VK_NV_shading_rate_image
typedef struct VkCoarseSampleOrderCustomNV {
VkShadingRatePaletteEntryNV shadingRate;
uint32_t sampleCount;
uint32_t sampleLocationCount;
const VkCoarseSampleLocationNV* pSampleLocations;
} VkCoarseSampleOrderCustomNV;
-
shadingRate
是一个着色率调色板条目,用于标识片段区域和每个像素覆盖采样计数组合的片段宽度和高度,以进行控制。 -
sampleCount
标识片段区域和覆盖采样计数组合的每个像素覆盖采样计数,以进行控制。 -
sampleLocationCount
指定自定义排序中采样位置的数量。 -
pSampleLocations
是指向 VkCoarseSampleLocationNV 结构数组的指针,该数组指定自定义排序中每个采样位置的位置。
VkCoarseSampleOrderCustomNV
结构与 VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV
的覆盖采样排序类型一起使用,以指定片段宽度、片段高度和覆盖采样计数的一个组合的覆盖采样顺序。
VkCoarseSampleLocationNV
结构标识一个特定像素和采样索引,该索引用于大于一个像素的片段中的覆盖采样之一。此结构的定义如下:
// Provided by VK_NV_shading_rate_image
typedef struct VkCoarseSampleLocationNV {
uint32_t pixelX;
uint32_t pixelY;
uint32_t sample;
} VkCoarseSampleLocationNV;
-
pixelX
被添加到每个片段最左上角像素的 x 坐标,以标识包含覆盖采样的像素。 -
pixelY
被添加到每个片段最左上角像素的 y 坐标,以标识包含覆盖采样的像素。 -
sample
是由pixelX
和pixelY
标识的像素中的覆盖采样的编号。
要动态设置大于一个像素的片段中的覆盖采样顺序,请调用
// Provided by VK_NV_shading_rate_image
void vkCmdSetCoarseSampleOrderNV(
VkCommandBuffer commandBuffer,
VkCoarseSampleOrderTypeNV sampleOrderType,
uint32_t customSampleOrderCount,
const VkCoarseSampleOrderCustomNV* pCustomSampleOrders);
-
commandBuffer
是将记录命令的命令缓冲区。 -
sampleOrderType
指定用于对大于一个像素的片元中的覆盖采样进行排序的机制。 -
customSampleOrderCount
指定在排序覆盖采样时要使用的自定义采样顺序的数量。 -
pCustomSampleOrders
是指向 VkCoarseSampleOrderCustomNV 结构体数组的指针,每个结构体指定了单个片段区域和覆盖样本计数的组合的覆盖样本顺序。
如果 sampleOrderType
是 VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV
,则在 pCustomSampleOrders
中未枚举的片元区域和覆盖采样计数的任何组合使用的覆盖采样顺序将与 VK_COARSE_SAMPLE_ORDER_TYPE_DEFAULT_NV
使用的覆盖采样顺序相同。
当使用着色器对象进行绘制时,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV
时,此命令会为后续绘制命令设置覆盖样本的顺序。 否则,此状态由用于创建当前活动管线的 VkPipelineViewportCoarseSampleOrderStateCreateInfoNV 值指定。
如果覆盖像素(x,y)的图元的最终着色率导致每个像素 n 个调用(n > 1),则会为该片段生成 n 个单独的片段着色器调用。片段中的每个覆盖样本将以依赖于实现的方式分配给 n 个片段着色器调用之一。每个着色器调用的片段输出接口的输出将被广播到与该调用关联的所有帧缓冲区样本。如果与片段着色器调用关联的覆盖样本均未被图元覆盖,则实现可以丢弃这些样本的片段着色器调用。
如果覆盖像素(x,y)的图元的最终着色率导致一个片段包含多个像素,则将为组合片段中的所有像素生成一组片段着色器调用。来自片段输出接口的输出将广播到属于该片段的所有被覆盖的帧缓冲区样本。如果片段着色器执行代码丢弃了该片段,则不会更新该片段的任何样本。
样本着色
样本着色可以用于指定每个片段要处理的最小唯一样本数。如果启用了样本着色,则实现必须为每个片段至少调用片段着色器 max(⌈ VkPipelineMultisampleStateCreateInfo::minSampleShading
× VkPipelineMultisampleStateCreateInfo::rasterizationSamples
⌉, 1) 次。如果 VkPipelineMultisampleStateCreateInfo::sampleShadingEnable
为 VK_TRUE
,则启用样本着色。
如果片段着色器入口点静态使用用 SampleId
或 SamplePosition
的 BuiltIn
修饰的输入变量,则启用样本着色,并且使用值 1.0
代替 minSampleShading
。如果片段着色器入口点静态使用用 Sample
修饰的输入变量,则可以启用样本着色,并且如果启用,则使用值 1.0
代替 minSampleShading
。 如果启用了 VK_AMD_mixed_attachment_samples
扩展,并且子通道使用颜色附件,则使用用于创建每个颜色附件的 samples
值代替 rasterizationSamples
。
如果着色器使用 |
重心插值
启用 fragmentShaderBarycentric
功能后,PerVertexKHR
插值修饰可以与片段着色器输入一起使用,以指示修饰的输入在片段中没有关联的数据。此类输入只能在片段着色器中使用数组索引进行访问,该数组索引的值(0、1 或 2)标识生成片段的图元的顶点之一。读取丢失顶点的每个顶点值(例如,直线图元的第三个顶点)将从具有最高索引的有效顶点返回值。这意味着点图元的索引 1 和 2 的每个顶点值将等于索引 0 的值,而直线图元的索引 2 的每个顶点值将等于索引 1 的值。
当细分曲面、几何着色和网格着色未激活时,使用 PerVertexKHR
修饰的片段着色器输入将从生成片段的图元的其中一个顶点获取值,该顶点由 SPIR-V 代码访问输入时提供的额外索引标识。如果传递给绘制调用的 n 个顶点编号为 0 到 n-1,并且绘制调用生成的点、线和三角形图元使用从零开始的连续整数编号,则下表指示当provoking vertex mode为 VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT
时,索引值 0、1 和 2 所使用的原始顶点编号。如果使用任何其他顶点索引值访问使用 PerVertexKHR
修饰的输入,或者在光栅化多边形时访问,并且当前活动管线的VkPipelineRasterizationStateCreateInfo::polygonMode
属性不是 VK_POLYGON_MODE_FILL
,则返回一个未定义的值。
图元拓扑 | 顶点 0 | 顶点 1 | 顶点 2 |
---|---|---|---|
|
i |
i |
i |
|
2i |
2i+1 |
2i+1 |
|
i |
i+1 |
i+1 |
|
3i |
3i+1 |
3i+2 |
|
i |
i+1 |
i+2 |
|
i |
i+2 |
i+1 |
|
i+1 |
i+2 |
0 |
|
4i+1 |
4i+2 |
4i+2 |
|
i+1 |
i+2 |
i+2 |
|
6i |
6i+2 |
6i+4 |
|
2i |
2i+2 |
2i+4 |
|
2i |
2i+4 |
2i+2 |
当 provoking vertex mode 为 VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
时,使用的原始顶点编号与上面的相同,但下表中指出的情况除外。
图元拓扑 | 顶点 0 | 顶点 1 | 顶点 2 |
---|---|---|---|
|
i+1 |
i |
i+2 |
|
0 |
i+1 |
i+2 |
|
2i+2 |
2i |
2i+4 |
当几何或网格着色激活时,片段着色器处理的图元是从几何或网格着色器发出的顶点组装而成的。在这种情况下,用于使用 PerVertexKHR
修饰的片段着色器输入的顶点是通过将着色器生成的图元视为好像它们是由绘制调用指定的,并参考上表来得出的。
当使用细分曲面而不使用几何着色时,细分器以实现相关的方式生成图元。虽然对于使用 PerVertexKHR
修饰的输入没有定义的顶点排序,但在这种情况下使用的顶点排序将与用于得出使用 BaryCoordKHR
或 BaryCoordNoPerspKHR
修饰的输入的值的排序保持一致。
使用 BaryCoordKHR
或 BaryCoordNoPerspKHR
修饰的片段着色器输入保存三组件向量,其中包含重心权重,指示片段相对于其图元的顶点的屏幕空间位置的位置。对于点图元,此类变量始终被赋值为 (1,0,0)。对于线图元,内置是通过内插属性获得的,该属性的顶点编号为 0 和 1 的值分别为 (1,0,0) 和 (0,1,0)。对于多边形图元,内置是通过内插属性获得的,该属性的顶点编号为 0、1 和 2 的值分别为 (1,0,0)、(0,1,0) 和 (0,0,1)。对于 BaryCoordKHR
,这些值是使用透视内插获得的。对于 BaryCoordNoPerspKHR
,这些值是使用线性内插获得的。当光栅化多边形时,并且当前活动管线的VkPipelineRasterizationStateCreateInfo::polygonMode
属性不是 VK_POLYGON_MODE_FILL
时,BaryCoordKHR
和 BaryCoordNoPerspKHR
的值是未定义的。
点
通过生成一组以点顶点为中心的方形形状的片段来绘制点。每个顶点都有一个关联的点大小,用于控制该正方形的宽度/高度。点大小取自(可能被裁剪的)着色器内置变量 PointSize
,该变量由以下着色器写入:
-
几何着色器(如果激活);
-
细分曲面计算着色器(如果激活且没有几何着色器激活);
-
否则为顶点着色器
并钳制到实现相关的点大小范围 [pointSizeRange
[0],pointSizeRange
[1]]。写入 PointSize
的值必须大于零。如果启用了maintenance5
功能,并且没有写入 PointSize
的值,则点大小将采用默认值 1.0。
并非所有点大小都需要支持,但必须支持大小 1.0。支持的大小范围和该范围内均匀间隔的梯度大小取决于实现。范围和梯度是从VkPhysicalDeviceLimits的 pointSizeRange
和 pointSizeGranularity
成员中获得的。例如,如果大小范围是从 0.1 到 2.0,并且梯度大小为 0.1,则支持大小 0.1、0.2、…、1.9、2.0。可能还支持其他点大小。没有要求这些大小均匀间隔。如果请求了不支持的大小,则会使用最近的支持大小。
此外,如果渲染通道具有片段密度图附件,则实现可能会将点大小舍入为片段宽度或高度的倍数。
基本点光栅化
点光栅化为每个帧缓冲像素的片段区域组生成一个片段,该组具有与以点的 (xf,yf) 为中心的区域相交的一个或多个采样点。该区域是一个边长等于当前点大小的正方形。与该区域相交的采样点对应的覆盖位为 1,其他覆盖位为 0。光栅化点产生的所有片段都被分配相同的关联数据,这些数据是与该点对应的顶点的数据。但是,片段着色器内置变量 PointCoord
包含点精灵纹理坐标。 s 和 t 点精灵纹理坐标在点上水平从左到右和垂直从上到下从零到一变化。以下公式用于评估 s 和 t
其中 size 是点的大小; (xp,yp) 是评估点精灵坐标的位置 - 这可能是片段中心的帧缓冲区坐标,或者是采样点的位置;而 (xf,yf) 是点的顶点的精确、未舍入的帧缓冲区坐标。
线段
线段光栅化选项由 VkPipelineRasterizationLineStateCreateInfo 结构体控制。
VkPipelineRasterizationLineStateCreateInfo
结构体定义如下:
// Provided by VK_VERSION_1_4
typedef struct VkPipelineRasterizationLineStateCreateInfo {
VkStructureType sType;
const void* pNext;
VkLineRasterizationMode lineRasterizationMode;
VkBool32 stippledLineEnable;
uint32_t lineStippleFactor;
uint16_t lineStipplePattern;
} VkPipelineRasterizationLineStateCreateInfo;
或等效于:
// Provided by VK_KHR_line_rasterization
typedef VkPipelineRasterizationLineStateCreateInfo VkPipelineRasterizationLineStateCreateInfoKHR;
或等效于:
// Provided by VK_EXT_line_rasterization
typedef VkPipelineRasterizationLineStateCreateInfo VkPipelineRasterizationLineStateCreateInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
lineRasterizationMode
是一个 VkLineRasterizationMode 值,用于选择线光栅化的样式。 -
stippledLineEnable
启用虚线光栅化。 -
lineStippleFactor
是虚线光栅化中使用的重复因子。 -
lineStipplePattern
是虚线光栅化中使用的位模式。
如果 stippledLineEnable
为 VK_FALSE
,则 lineStippleFactor
和 lineStipplePattern
的值将被忽略。
VkPipelineRasterizationLineStateCreateInfo::lineRasterizationMode
的可能值(用于指定线光栅化模式)如下:
// Provided by VK_VERSION_1_4
typedef enum VkLineRasterizationMode {
VK_LINE_RASTERIZATION_MODE_DEFAULT = 0,
VK_LINE_RASTERIZATION_MODE_RECTANGULAR = 1,
VK_LINE_RASTERIZATION_MODE_BRESENHAM = 2,
VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH = 3,
// Provided by VK_EXT_line_rasterization
VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT = VK_LINE_RASTERIZATION_MODE_DEFAULT,
// Provided by VK_EXT_line_rasterization
VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT = VK_LINE_RASTERIZATION_MODE_RECTANGULAR,
// Provided by VK_EXT_line_rasterization
VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT = VK_LINE_RASTERIZATION_MODE_BRESENHAM,
// Provided by VK_EXT_line_rasterization
VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_EXT = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH,
// Provided by VK_KHR_line_rasterization
VK_LINE_RASTERIZATION_MODE_DEFAULT_KHR = VK_LINE_RASTERIZATION_MODE_DEFAULT,
// Provided by VK_KHR_line_rasterization
VK_LINE_RASTERIZATION_MODE_RECTANGULAR_KHR = VK_LINE_RASTERIZATION_MODE_RECTANGULAR,
// Provided by VK_KHR_line_rasterization
VK_LINE_RASTERIZATION_MODE_BRESENHAM_KHR = VK_LINE_RASTERIZATION_MODE_BRESENHAM,
// Provided by VK_KHR_line_rasterization
VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH_KHR = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH,
} VkLineRasterizationMode;
或等效于:
// Provided by VK_KHR_line_rasterization
typedef VkLineRasterizationMode VkLineRasterizationModeKHR;
或等效于:
// Provided by VK_EXT_line_rasterization
typedef VkLineRasterizationMode VkLineRasterizationModeEXT;
-
如果 VkPhysicalDeviceLimits::
strictLines
为VK_TRUE
,则VK_LINE_RASTERIZATION_MODE_DEFAULT
等效于VK_LINE_RASTERIZATION_MODE_RECTANGULAR
,否则,线将绘制为非strictLines
的平行四边形。这两种模式都在基本线段光栅化中定义。 -
VK_LINE_RASTERIZATION_MODE_RECTANGULAR
指定线绘制为从线挤出的矩形。 -
VK_LINE_RASTERIZATION_MODE_BRESENHAM
指定线通过确定该线相交并退出的像素菱形来绘制,如Bresenham 线段光栅化中定义的那样。 -
VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH
指定线绘制为从线挤出的矩形,并带有 alpha 衰减,如平滑线中定义的那样。
要动态设置 lineRasterizationMode
状态,请调用:
// Provided by VK_EXT_extended_dynamic_state3 with VK_EXT_line_rasterization, VK_EXT_line_rasterization with VK_EXT_shader_object
void vkCmdSetLineRasterizationModeEXT(
VkCommandBuffer commandBuffer,
VkLineRasterizationModeEXT lineRasterizationMode);
-
commandBuffer
是将记录命令的命令缓冲区。 -
lineRasterizationMode
指定lineRasterizationMode
状态。
当使用 着色器对象进行绘制时,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_EXT
时,此命令将为后续的绘制命令设置 lineRasterizationMode
状态。否则,此状态由用于创建当前活动管线的 VkPipelineRasterizationLineStateCreateInfo::lineRasterizationMode
值指定。
要动态设置 stippledLineEnable
状态,请调用:
// Provided by VK_EXT_extended_dynamic_state3 with VK_EXT_line_rasterization, VK_EXT_line_rasterization with VK_EXT_shader_object
void vkCmdSetLineStippleEnableEXT(
VkCommandBuffer commandBuffer,
VkBool32 stippledLineEnable);
-
commandBuffer
是将记录命令的命令缓冲区。 -
stippledLineEnable
指定stippledLineEnable
状态。
当使用 着色器对象进行绘制时,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT
时,此命令将为后续的绘制命令设置 stippledLineEnable
状态。否则,此状态由用于创建当前活动管线的 VkPipelineRasterizationLineStateCreateInfo::stippledLineEnable
值指定。
要动态设置线宽,请调用
// Provided by VK_VERSION_1_0
void vkCmdSetLineWidth(
VkCommandBuffer commandBuffer,
float lineWidth);
-
commandBuffer
是将记录命令的命令缓冲区。 -
lineWidth
是光栅化线段的宽度。
此命令设置后续绘制命令的线宽,当使用着色器对象绘制时,或者当图形管线在VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了VK_DYNAMIC_STATE_LINE_WIDTH
时创建。否则,此状态由用于创建当前激活管线的VkPipelineRasterizationStateCreateInfo::lineWidth
值指定。
并非所有线宽都需要支持线段栅格化,但必须提供宽度为 1.0 的抗锯齿线段。范围和梯度从VkPhysicalDeviceLimits的lineWidthRange
和lineWidthGranularity
成员获得。例如,如果大小范围从 0.1 到 2.0,梯度大小为 0.1,则支持大小 0.1、0.2、…、1.9、2.0。可能还支持其他线宽。这些宽度不必均匀间隔。如果请求不支持的宽度,则会使用最接近的支持宽度。
此外,如果渲染通道具有片段密度图附件,则线宽可能会被实现舍入为片段宽度或高度的倍数。
基本线段栅格化
如果VkPipelineRasterizationLineStateCreateInfo的lineRasterizationMode
成员是VK_LINE_RASTERIZATION_MODE_RECTANGULAR
,则栅格化的线段会产生与以线段为中心的矩形相交的片段。两条边与指定的线段平行;每条边都以垂直于线方向的距离,距离该线段当前宽度的一半。另两条边穿过线端点,并且垂直于指定线段的方向。与矩形相交的样本点对应的覆盖位为 1,其他覆盖位为 0。
接下来,我们指定如何获取与每个栅格化片段关联的数据。令pr = (xd, yd)为评估关联数据的帧缓冲区坐标。这可能是片段的中心或片段内样本的位置。当rasterizationSamples
为VK_SAMPLE_COUNT_1_BIT
时,必须使用片段中心。令pa = (xa, ya)和pb = (xb,yb)分别为线段的初始和最终端点。设置
(请注意,t = 0在pa处,t = 1在pb处。另请注意,此计算将从pa到pr的向量投影到直线上,从而计算出片段沿直线的归一化距离。)
如果strictLines
为VK_TRUE
,则使用透视或线性插值栅格化线段。
线段的透视插值以考虑视口的透视的方式正确地插值两个值,通过线段的裁剪坐标实现。插值后的值f可以通过以下方式确定
其中fa和fb分别是与线段的起始和结束端点关联的数据;wa和wb分别是线段的起始和结束端点的裁剪w坐标。
线段的线性插值直接插值两个值,并且插值后的值f可以通过以下方式确定
-
f = (1 - t) fa + t fb
其中fa和fb分别是与线段的起始和结束端点关联的数据。
使用透视插值确定样本的裁剪坐标w。使用线性插值确定样本的深度值z。片段着色器输入值的插值由插值装饰确定。
以上描述记录了首选的线栅格化方法,当lineRasterizationMode
为VK_LINE_RASTERIZATION_MODE_RECTANGULAR
时,必须使用该方法。
默认情况下,当strictLines
为VK_FALSE
,或者启用了relaxedLineRasterization
功能,并且lineRasterizationMode
为VK_LINE_RASTERIZATION_MODE_DEFAULT
时,线的边缘将生成为围绕原始线的平行四边形。主轴的选择方法是:找出线起点和终点之间距离最大的轴。如果两个方向上的差值相等,则选择 X 轴作为主轴。边缘 2 和 3 与次轴对齐,并以线端点为中心,如图 20。非严格线所示,并且每个边缘的长度为lineWidth
。边缘 0 和 1 与直线平行,并连接边缘 2 和 3 的端点。与平行四边形相交的样本点对应的覆盖位为 1,其他覆盖位为 0。
正好落在平行四边形边缘上的样本遵循多边形栅格化规则。
插值就像平行四边形被分解为两个三角形一样发生,其中每对位于线端点的顶点都具有相同的属性。
当strictLines
为VK_FALSE
或启用relaxedLineRasterization
功能,并且lineRasterizationMode
为VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT
时,实现可能会以下列方式偏离上述非严格线算法
-
实现方式可以改为根据基本线段光栅化中的公式,使用原始线段端点对每个片段进行插值。
-
非抗锯齿、非严格线段的光栅化可以使用Bresenham线段光栅化中定义的规则执行。
如果VkPhysicalDeviceMaintenance5Properties
::nonStrictSinglePixelWideLinesUseParallelogram
为VK_TRUE
,lineRasterizationMode
为VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT
,且strictLines
为VK_FALSE
,则宽度为1.0的非严格线将光栅化为平行四边形,否则使用Bresenham算法进行光栅化。
如果VkPhysicalDeviceMaintenance5Properties
::nonStrictWideLinesUseParallelogram
为VK_TRUE
,lineRasterizationMode
为VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT
,且strictLines
为VK_FALSE
,则宽度大于1.0的非严格线将光栅化为平行四边形,否则使用Bresenham算法进行光栅化。
Bresenham线段光栅化
如果lineRasterizationMode
为VK_LINE_RASTERIZATION_MODE_BRESENHAM
,则以下规则将替换基本线段光栅化中定义的线光栅化规则。
非严格线也可能对非抗锯齿线遵循这些光栅化规则。
如果启用了relaxedLineRasterization
特性,且lineRasterizationMode
为VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT
,则实现必须对宽度为1.0的非抗锯齿线遵循这些光栅化规则。
线段光栅化首先将线段表征为x-主导或y-主导。x-主导线段的斜率在闭区间[-1,1]内;所有其他线段都是y-主导的(斜率由线段的端点确定)。我们仅针对x-主导线段指定光栅化,除非y-主导线段的修改不是显而易见的。
理想情况下,Vulkan使用菱形退出规则来确定通过光栅化线段生成的片段。对于中心位于帧缓冲区坐标xf和yf的每个片段f,定义一个菱形区域,它是四个半平面的交集
本质上,以pa开始并以pb结束的线段会生成与Rf相交的片段f,除非pb包含在Rf中。
为了避免当端点位于Rf的边界上时出现困难,我们(原则上)将提供的端点扰动一个很小的量。令pa和pb分别具有帧缓冲区坐标(xa, ya)和(xb, yb)。获取扰动后的端点pa',由(xa, ya) - (ε, ε2)给出,以及pb',由(xb, yb) - (ε, ε2)给出。光栅化以pa开始并以pb结束的线段会生成与pa'开始并以pb'结束的线段相交的片段f,除非pb'包含在Rf中。ε的选择要足够小,使得当用δ替换ε时,对于任何0 < δ ≤ ε,光栅化线段产生的片段相同。
当pa和pb位于片段中心时,这种片段表征会简化为Bresenham算法,但有一个修改:此描述中生成的线是“半开的”,这意味着不绘制最终片段(对应于pb)。这意味着当光栅化一系列连接的线段时,共享的端点将仅生成一次而不是两次(就像使用Bresenham算法会发生的那样)。
实现方式可以使用其他线段光栅化算法,但须遵守以下规则
-
该算法生成的片段的坐标在x或y帧缓冲区坐标中与菱形退出规则生成的相应片段的偏差不得超过一个单位。
-
该算法生成的片段总数与菱形退出规则生成的片段总数之差不得超过一个。
-
对于x-主导线,不得生成位于同一帧缓冲区坐标列中的两个片段(对于y-主导线,不得生成位于同一帧缓冲区坐标行中的两个片段)。
-
如果两个线段共享一个公共端点,并且两个线段要么都是x-主导的(都是从左到右或都是从右到左),要么都是y-主导的(都是从下到上或都是从上到下),则光栅化这两个线段不得生成重复的片段。片段也不得被省略,以免中断连接线段的连续性。
Bresenham线的实际宽度w由将线宽度四舍五入到最接近的整数来确定,将其钳制为实现相关的lineWidthRange
(两个值都四舍五入到最接近的整数),然后将其钳制为不小于1。
宽度不为 1 的 Bresenham 线段的光栅化是通过在次要方向上偏移它们(对于 x 为主方向的线,次要方向是 y,对于 y 为主方向的线,次要方向是 x),并在次要方向上生成一行或一列片段来实现的。如果线段的端点在帧缓冲区坐标中由 (x0, y0) 和 (x1, y1) 给出,则端点为 和 \((x_1, y_1 - \frac{w-1}{2})\) 的线段会被光栅化,但不是单个片段,而是在每个 x(对于 y 为主方向是 y)位置生成一个高度为 w 的片段列(对于 y 为主方向的线段,则生成长度为 w 的片段行)。此列的最低片段是通过使用修改后的坐标光栅化宽度为 1 的线段而产生的片段。
宽线的首选属性插值方法是为上述行或列中的所有片段生成相同的属性值,就好像调整后的线用于插值并将这些值复制到其他片段一样,但 FragCoord
除外,它会像往常一样进行插值。实现**可能**改为根据基本线段光栅化中的公式对每个片段进行插值,使用原始线段端点。
当光栅化 Bresenham 线时,采样位置**可能**全部被视为位于像素中心(这**可能**会影响属性和深度插值)。
上述采样位置**不**用于确定覆盖率,它们仅用于诸如属性插值之类的事情。确定覆盖率的光栅化规则是根据线是否与**像素**相交来定义的,而不是用于其他图元类型的点采样规则。因此,这些规则独立于采样位置。这样做的一个结果是,无论光栅化采样数量如何,Bresenham 线都覆盖相同的像素,并覆盖这些像素中的所有采样(除非被屏蔽或丢弃)。 |
线段虚线
如果 VkPipelineRasterizationLineStateCreateInfo 的 stippledLineEnable
成员为 VK_TRUE
,则使用由 lineStippleFactor
和 lineStipplePattern
确定的 *线段虚线* 来光栅化线。lineStipplePattern
是一个无符号 16 位整数,用于确定在光栅化线时要绘制或丢弃哪些片段。lineStippleFactor
是一个计数,用于修改有效的线段虚线,方法是使 lineStipplePattern
中的每个位被使用 lineStippleFactor
次。
线段虚线会丢弃光栅化产生的部分片段。掩码是通过使用三个参数实现的:16 位线段虚线模式 p、线段虚线因子 r 和整数虚线计数器 s。设
如果 p 的第 b 位为 1,则生成一个片元,否则丢弃。p 的位的编号从 0 开始,0 为最低有效位,15 为最高有效位。
s 的初始值为零。对于 VK_LINE_RASTERIZATION_MODE_BRESENHAM
直线,每生成一个线段的片元(片元按照从起点到终点的顺序生成)后,s 就会递增。对于 VK_LINE_RASTERIZATION_MODE_RECTANGULAR
和 VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH
直线,矩形区域被细分为相邻的单位长度矩形,并且每个矩形 s 递增一次。如果 s 的值使得 p 的第 b 位为零,则丢弃该矩形。如果线段中的最后一个矩形长度小于单位长度,则剩余部分可能会使用相同的 s 值延续到线带中的下一个线段(这是首选行为,以使点画图案在整个线带中看起来更加一致)。
在每个线带的开始处(对于线带),以及在一组独立线段中的每个线段之前,s 将重置为 0。
如果线段已被裁剪,则线段开始时的 s 值取决于具体实现。
要动态设置线点画状态,请调用
// Provided by VK_VERSION_1_4
void vkCmdSetLineStipple(
VkCommandBuffer commandBuffer,
uint32_t lineStippleFactor,
uint16_t lineStipplePattern);
或等效命令
// Provided by VK_KHR_line_rasterization
void vkCmdSetLineStippleKHR(
VkCommandBuffer commandBuffer,
uint32_t lineStippleFactor,
uint16_t lineStipplePattern);
或等效命令
// Provided by VK_EXT_line_rasterization
void vkCmdSetLineStippleEXT(
VkCommandBuffer commandBuffer,
uint32_t lineStippleFactor,
uint16_t lineStipplePattern);
-
commandBuffer
是将记录命令的命令缓冲区。 -
lineStippleFactor
是虚线光栅化中使用的重复因子。 -
lineStipplePattern
是虚线光栅化中使用的位模式。
在使用着色器对象进行绘制时,或者在创建图形管线时在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_LINE_STIPPLE
时,此命令会设置后续绘制命令的线点画状态。否则,此状态由用于创建当前活动管线的 VkPipelineRasterizationLineStateCreateInfo::lineStippleFactor
和 VkPipelineRasterizationLineStateCreateInfo::lineStipplePattern
值指定。
平滑直线
如果 VkPipelineRasterizationLineStateCreateInfo 的 lineRasterizationMode
成员是 VK_LINE_RASTERIZATION_MODE_RECTANGULAR_SMOOTH
,则将直线视为与 VK_LINE_RASTERIZATION_MODE_RECTANGULAR
直线具有相同几何形状的矩形。确定覆盖哪些像素的规则取决于具体实现,并且可能包括没有覆盖任何采样位置或者矩形根本没有与像素相交的附近像素。对于被视为覆盖的每个像素,片元会计算一个覆盖率值,该值近似于矩形与像素正方形的交集面积,并且该覆盖率值在片段着色后乘以颜色位置 0 的 alpha 值,如 多重采样覆盖率中所述。
光栅化规则和面积计算的细节有意保持模糊,以便允许实现生成美观的覆盖率和值。 |
多边形
多边形是由三角形条带、三角形扇或一系列独立三角形分解而来的。与点和线段一样,多边形光栅化由 VkPipelineRasterizationStateCreateInfo 结构中的几个变量控制。
基本多边形光栅化
多边形光栅化的第一步是确定三角形是背面还是正面。此确定基于在帧缓冲区坐标中计算的(裁剪或未裁剪)多边形面积的符号进行。计算此面积的一种方法是
其中 和 是 n 顶点多边形的第 i 个顶点的 x 和 y 帧缓冲坐标(为了计算的目的,顶点编号从零开始),i ⊕ 1 是 (i + 1) mod n。
a 的符号的解释由当前活动的管线的 VkPipelineRasterizationStateCreateInfo::frontFace
属性决定。可能的值有
// Provided by VK_VERSION_1_0
typedef enum VkFrontFace {
VK_FRONT_FACE_COUNTER_CLOCKWISE = 0,
VK_FRONT_FACE_CLOCKWISE = 1,
} VkFrontFace;
-
VK_FRONT_FACE_COUNTER_CLOCKWISE
指定具有正面积的三角形被认为是正面朝向的。 -
VK_FRONT_FACE_CLOCKWISE
指定具有负面积的三角形被认为是正面朝向的。
任何不是正面朝向的三角形都是背面朝向的,包括零面积的三角形。
要动态设置正面朝向,请调用
// Provided by VK_VERSION_1_3
void vkCmdSetFrontFace(
VkCommandBuffer commandBuffer,
VkFrontFace frontFace);
或等效命令
// Provided by VK_EXT_extended_dynamic_state, VK_EXT_shader_object
void vkCmdSetFrontFaceEXT(
VkCommandBuffer commandBuffer,
VkFrontFace frontFace);
-
commandBuffer
是将记录命令的命令缓冲区。 -
frontFace
是一个 VkFrontFace 值,用于指定用于剔除的正面三角形方向。
当使用着色器对象进行绘制时,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_FRONT_FACE
时创建时,此命令为后续的绘制命令设置正面朝向。否则,此状态由用于创建当前活动管线的 VkPipelineRasterizationStateCreateInfo::frontFace
值指定。
一旦确定了三角形的朝向,它们将根据当前活动管线的 VkPipelineRasterizationStateCreateInfo::cullMode
属性进行剔除。可能的值有
// Provided by VK_VERSION_1_0
typedef enum VkCullModeFlagBits {
VK_CULL_MODE_NONE = 0,
VK_CULL_MODE_FRONT_BIT = 0x00000001,
VK_CULL_MODE_BACK_BIT = 0x00000002,
VK_CULL_MODE_FRONT_AND_BACK = 0x00000003,
} VkCullModeFlagBits;
-
VK_CULL_MODE_NONE
指定不丢弃任何三角形 -
VK_CULL_MODE_FRONT_BIT
指定丢弃正面朝向的三角形 -
VK_CULL_MODE_BACK_BIT
指定丢弃背面朝向的三角形 -
VK_CULL_MODE_FRONT_AND_BACK
指定丢弃所有三角形。
在剔除之后,会为任何未被丢弃的三角形生成片段。
// Provided by VK_VERSION_1_0
typedef VkFlags VkCullModeFlags;
VkCullModeFlags
是一种位掩码类型,用于设置零个或多个 VkCullModeFlagBits 的掩码。
要动态设置剔除模式,请调用
// Provided by VK_VERSION_1_3
void vkCmdSetCullMode(
VkCommandBuffer commandBuffer,
VkCullModeFlags cullMode);
或等效命令
// Provided by VK_EXT_extended_dynamic_state, VK_EXT_shader_object
void vkCmdSetCullModeEXT(
VkCommandBuffer commandBuffer,
VkCullModeFlags cullMode);
-
commandBuffer
是将记录命令的命令缓冲区。 -
cullMode
指定用于绘制的剔除模式属性。
此命令设置使用着色器对象进行绘制时,或在图形管线创建时,在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_CULL_MODE
之后,后续绘图命令的剔除模式。否则,此状态由用于创建当前活动管线的 VkPipelineRasterizationStateCreateInfo::cullMode
值指定。
用于确定多边形光栅化产生哪些片元的规则称为点采样。通过取多边形顶点的 x 和 y 帧缓冲区坐标形成的二维投影。对于任何采样点位于此多边形内的像素的任何片元区域组,都会生成片元。与满足点采样标准的采样点对应的覆盖位为 1,其他覆盖位为 0。对于采样位置位于多边形边缘的采样点,会进行特殊处理。在这种情况下,如果两个多边形位于一个公共边缘的两侧(具有相同的端点),并且采样点位于该公共边缘上,则在光栅化期间,正好其中一个多边形必须为该片元产生覆盖采样点。至于由光栅化多边形产生的每个片元的关联数据,我们首先指定如何为三角形中的片元生成这些值。
重心坐标 是一组三个数字,a、b 和 c,每个数字都在 [0,1] 范围内,且 a + b + c = 1。这些坐标唯一指定三角形内或三角形边界上的任何点 p,如下所示
-
p = a pa + b pb + c pc
其中 pa、pb 和 pc 是三角形的顶点。a、b 和 c 由以下公式确定
其中 A(lmn) 表示顶点为 l、m 和 n 的三角形在帧缓冲区坐标中的面积。
将 pa、pb 或 pc 处的关联数据表示为 fa、fb 或 fc。
三角形的透视插值通过三角形的裁剪坐标,以考虑视口透视的方式正确地插值三个值。插值的值 f 可以通过以下公式确定
其中 wa、wb 和 wc 分别是 pa、pb 和 pc 的裁剪 w 坐标。a、b 和 c 是数据生成位置的重心坐标。
三角形的线性插值直接插值三个值,插值的值 f 可以通过以下公式确定
-
f = a fa + b fb + c fc
其中 fa、fb 和 fc 分别是与 pa、pb 和 pc 关联的数据。
使用透视插值确定样本的裁剪坐标w。使用线性插值确定样本的深度值z。片段着色器输入值的插值由插值装饰确定。
对于具有三个以上边的多边形,例如通过裁剪三角形产生的多边形,必须使用多边形顶点处的数据值的凸组合来获得分配给光栅化算法产生的每个片元的值。也就是说,必须在每个片元都存在以下情况
其中 n 是多边形中顶点的数量,fi 是顶点 i 处 f 的值。对于每个 i,0 ≤ ai ≤ 1 且 。 ai 的值可能因片段而异,但在顶点 i 处,ai = 1 且对于 j ≠ i,aj = 0。
一种实现所需行为的算法是将多边形三角化(不添加任何顶点),然后如前所述分别处理每个三角形。一个扫描线光栅化器,它沿每条边线性插值数据,然后从边到边线性插值每个水平跨度上的数据,也满足限制条件(在这种情况下,透视插值的分子和分母是独立迭代的,并且为每个片段执行除法)。 |
多边形模式
当前活动管道的 VkPipelineRasterizationStateCreateInfo::polygonMode
属性的可能值,指定多边形的栅格化方法为:
// Provided by VK_VERSION_1_0
typedef enum VkPolygonMode {
VK_POLYGON_MODE_FILL = 0,
VK_POLYGON_MODE_LINE = 1,
VK_POLYGON_MODE_POINT = 2,
// Provided by VK_NV_fill_rectangle
VK_POLYGON_MODE_FILL_RECTANGLE_NV = 1000153000,
} VkPolygonMode;
-
VK_POLYGON_MODE_POINT
指定将多边形顶点绘制为点。 -
VK_POLYGON_MODE_LINE
指定将多边形边绘制为线段。 -
VK_POLYGON_MODE_FILL
指定使用本节中的多边形栅格化规则渲染多边形。 -
VK_POLYGON_MODE_FILL_RECTANGLE_NV
指定使用多边形栅格化规则渲染多边形,该规则经过修改,如果采样位置位于投影后三角形的轴对齐边界框内,则将该采样视为在图元内。请注意,当对这些图元进行着色时,属性插值中使用的重心权重可以超出 [0,1] 的范围。对边界框的边界边上的采样位置进行特殊处理。在这种情况下,如果两个矩形位于一个公共边的两侧(具有相同的端点),并且采样位置位于该边上,那么在栅格化期间,恰好一个三角形必须生成覆盖该采样的片段。在
VK_POLYGON_MODE_FILL_RECTANGLE_NV
模式下渲染的多边形可能会被视锥或用户剪裁平面剪裁。如果应用剪裁,则会剔除三角形而不是剪裁。对于
VK_POLYGON_MODE_FILL_RECTANGLE_NV
模式,使用三角形的顶点确定面积计算和朝向性。
这些模式仅影响多边形的最终栅格化:特别是,多边形的顶点会被着色,并且多边形在应用这些模式之前会被剪裁并可能被剔除。
如果 VkPhysicalDeviceMaintenance5Properties
::polygonModePointSize
为 VK_TRUE
,则当 多边形模式 为 VK_POLYGON_MODE_POINT
时,多边形最终栅格化的点大小取自 PointSize
。
否则,如果 VkPhysicalDeviceMaintenance5Properties
::polygonModePointSize
为 VK_FALSE
,则当 多边形模式 为 VK_POLYGON_MODE_POINT
时,多边形最终栅格化的点大小为 1.0。
要动态设置多边形模式,请调用
// Provided by VK_EXT_extended_dynamic_state3, VK_EXT_shader_object
void vkCmdSetPolygonModeEXT(
VkCommandBuffer commandBuffer,
VkPolygonMode polygonMode);
-
commandBuffer
是将记录命令的命令缓冲区。 -
polygonMode
指定多边形模式。
当使用着色器对象绘制时,或当图形管道使用 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置的 VK_DYNAMIC_STATE_POLYGON_MODE_EXT
创建时,此命令会为后续绘制命令设置多边形模式。否则,此状态由用于创建当前活动管道的 VkPipelineRasterizationStateCreateInfo::polygonMode
值指定。
深度偏移
多边形光栅化生成的所有片元的深度值可以通过一个单独的深度偏移值 进行偏移(调整)。该偏移值针对该多边形计算得出。
启用深度偏移
深度偏移计算通过 vkCmdSetDepthBiasEnable 和 vkCmdSetDepthBiasEnableEXT
设置的 depthBiasEnable
启用,或者通过用于创建当前激活管线的相应 VkPipelineRasterizationStateCreateInfo::depthBiasEnable
值启用。如果深度偏移启用为 VK_FALSE
,则不应用任何偏移,并且片元的深度值保持不变。
要动态启用是否偏移片元深度值,请调用
// Provided by VK_VERSION_1_3
void vkCmdSetDepthBiasEnable(
VkCommandBuffer commandBuffer,
VkBool32 depthBiasEnable);
或等效命令
// Provided by VK_EXT_extended_dynamic_state2, VK_EXT_shader_object
void vkCmdSetDepthBiasEnableEXT(
VkCommandBuffer commandBuffer,
VkBool32 depthBiasEnable);
-
commandBuffer
是将记录命令的命令缓冲区。 -
depthBiasEnable
控制是否偏置片段深度值。
当使用着色器对象进行绘制时,或者当图形管线在 VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE
时创建时,此命令设置后续绘制命令的深度偏移启用。否则,此状态由用于创建当前激活管线的 VkPipelineRasterizationStateCreateInfo::depthBiasEnable
值指定。
深度偏移计算
深度偏移取决于三个参数
-
depthBiasSlopeFactor
缩放多边形的最大深度斜率 m -
depthBiasConstantFactor
缩放深度附件的参数 r -
缩放后的项相加,生成一个值,然后将其钳制为
depthBiasClamp
指定的最小值或最大值
depthBiasSlopeFactor
、depthBiasConstantFactor
和 depthBiasClamp
可以为正、负或零。这些参数的设置如下面针对 vkCmdSetDepthBias 和 vkCmdSetDepthBias2EXT 所述。
三角形的最大深度斜率 m 为
其中 (xf, yf, zf) 是三角形上的一个点。 m 可以近似为
在深度偏移表示为 VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT
的管线中,对于给定的图元,r 定义为
-
r = 1
否则,r 是取决于深度附件表示的最小可分辨差异。如果 VkDepthBiasRepresentationInfoEXT
::depthBiasExact
为 VK_FALSE
,则它是样本深度 zf 值中的最小差异,该差异保证在多边形光栅化和深度附件中保持不同。由两个具有其他相同顶点但 zf 值相差 r 的多边形的光栅化生成的所有片元对都将具有不同的深度值。
对于定点深度附件表示,或者在深度偏移表示为 VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT
的管线中,r 在整个深度附件范围内是恒定的。如果 VkDepthBiasRepresentationInfoEXT
::depthBiasExact
为 VK_TRUE
,则其值必须为
-
r = 2-n
否则,其值取决于实现,但必须最大为
-
r = 2 × 2-n
其中 n 是在使用定点附件时用于深度方面的位数,或者在使用浮点附件时是尾数位数加 1。
否则,对于浮点深度附件,没有单个最小可分辨差异。在这种情况下,给定多边形的最小可分辨差异取决于图元跨越的 z 值范围中的最大指数 e。如果 n 是浮点尾数中的位数,则给定图元的最小可分辨差异 r 定义为
-
r = 2e-n
如果使用 VK_POLYGON_MODE_FILL_RECTANGLE_NV
多边形模式光栅化三角形,则对于三角形外部的样本(深度值已外推),此最小可分辨差异可能无法分辨。
如果不存在深度附件,则 r 是未定义的。
多边形的偏移值 o 为
m 如上所述计算。如果深度附件使用定点表示,则 m 是范围 [0,1] 内深度值的函数,并且 o 应用于相同范围内的深度值。
无论多边形模式如何,深度偏移都应用于光栅化器接收的三角形拓扑图元。深度偏移可以也应用于光栅化器接收的线和点拓扑图元。
要动态设置深度偏移参数,请调用
// Provided by VK_VERSION_1_0
void vkCmdSetDepthBias(
VkCommandBuffer commandBuffer,
float depthBiasConstantFactor,
float depthBiasClamp,
float depthBiasSlopeFactor);
-
commandBuffer
是将记录命令的命令缓冲区。 -
depthBiasConstantFactor
是一个标量因子,用于控制添加到每个片段的常量深度值。 -
depthBiasClamp
是片段的最大(或最小)深度偏置。 -
depthBiasSlopeFactor
是一个标量因子,应用于深度偏置计算中片段的斜率。
此命令设置使用着色器对象绘制时,或在VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了VK_DYNAMIC_STATE_DEPTH_BIAS
来创建图形管线时,后续绘制命令的深度偏移参数。否则,此状态由用于创建当前活动管线的相应VkPipelineRasterizationStateCreateInfo::depthBiasConstantFactor
、depthBiasClamp
和 depthBiasSlopeFactor
值指定。
调用此函数等效于调用 vkCmdSetDepthBias2EXT
,且 VkDepthBiasInfoEXT
的 pNext 链中没有 VkDepthBiasRepresentationInfoEXT
。
VkDepthBiasRepresentationInfoEXT
结构定义如下:
// Provided by VK_EXT_depth_bias_control
typedef struct VkDepthBiasRepresentationInfoEXT {
VkStructureType sType;
const void* pNext;
VkDepthBiasRepresentationEXT depthBiasRepresentation;
VkBool32 depthBiasExact;
} VkDepthBiasRepresentationInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
depthBiasRepresentation
是一个 VkDepthBiasRepresentationEXT 值,指定深度偏移表示形式。 -
depthBiasExact
指定不允许实现缩放深度偏移值以确保最小可分辨距离。
指定深度偏移表示形式的 VkDepthBiasRepresentationInfoEXT::depthBiasRepresentation
的可能值如下:
// Provided by VK_EXT_depth_bias_control
typedef enum VkDepthBiasRepresentationEXT {
VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT = 0,
VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT = 1,
VK_DEPTH_BIAS_REPRESENTATION_FLOAT_EXT = 2,
} VkDepthBiasRepresentationEXT;
VkDepthBiasInfoEXT
结构定义如下:
// Provided by VK_EXT_depth_bias_control
typedef struct VkDepthBiasInfoEXT {
VkStructureType sType;
const void* pNext;
float depthBiasConstantFactor;
float depthBiasClamp;
float depthBiasSlopeFactor;
} VkDepthBiasInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
depthBiasConstantFactor
是一个标量因子,用于控制添加到每个片段的常量深度值。 -
depthBiasClamp
是片段的最大(或最小)深度偏置。 -
depthBiasSlopeFactor
是一个标量因子,应用于深度偏置计算中片段的斜率。
如果 pNext
不包含 VkDepthBiasRepresentationInfoEXT 结构,则此命令等效于包含一个 depthBiasExact
设置为 VK_FALSE
且 depthBiasRepresentation
设置为 VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORMAT_EXT
的 VkDepthBiasRepresentationInfoEXT。
要动态设置深度偏移参数,请调用
// Provided by VK_EXT_depth_bias_control
void vkCmdSetDepthBias2EXT(
VkCommandBuffer commandBuffer,
const VkDepthBiasInfoEXT* pDepthBiasInfo);
-
commandBuffer
是将记录命令的命令缓冲区。 -
pDepthBiasInfo
是指向 VkDepthBiasInfoEXT 结构的指针,该结构指定深度偏移参数。
此命令的功能与 vkCmdSetDepthBias 相同,但包含可扩展的子结构,包括 sType
和 pNext
参数,从而使其更容易扩展。
保守光栅化
如果 VkPipelineRasterizationStateCreateInfo 的 pNext
链包含 VkPipelineRasterizationConservativeStateCreateInfoEXT
结构,则该结构包含控制保守光栅化的参数。
VkPipelineRasterizationConservativeStateCreateInfoEXT
定义如下:
// Provided by VK_EXT_conservative_rasterization
typedef struct VkPipelineRasterizationConservativeStateCreateInfoEXT {
VkStructureType sType;
const void* pNext;
VkPipelineRasterizationConservativeStateCreateFlagsEXT flags;
VkConservativeRasterizationModeEXT conservativeRasterizationMode;
float extraPrimitiveOverestimationSize;
} VkPipelineRasterizationConservativeStateCreateInfoEXT;
-
sType
是一个 VkStructureType 值,用于标识此结构。 -
pNext
是NULL
或指向扩展此结构的结构的指针。 -
flags
保留供将来使用。 -
conservativeRasterizationMode
是要使用的保守光栅化模式。 -
extraPrimitiveOverestimationSize
是在屏幕空间中,在VkPhysicalDeviceConservativeRasterizationPropertiesEXT
::primitiveOverestimationSize
中指定的基本高估之外,在每个边缘保守光栅化期间增加生成基元的额外像素大小(以X
和Y
方向相等)。如果conservativeRasterizationMode
不是VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT
,则忽略此值。
如果此结构未包含在 pNext
链中,则 conservativeRasterizationMode
将被视为 VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT
,并且保守光栅化将被禁用。
通过在 VkPipelineRasterizationConservativeStateCreateInfoEXT
中将 conservativeRasterizationMode
设置为 VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT
或 VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
,可以使多边形光栅化变为保守的。
如果支持 |
// Provided by VK_EXT_conservative_rasterization
typedef VkFlags VkPipelineRasterizationConservativeStateCreateFlagsEXT;
VkPipelineRasterizationConservativeStateCreateFlagsEXT
是用于设置掩码的位掩码类型,但目前保留供将来使用。
VkPipelineRasterizationConservativeStateCreateInfoEXT::conservativeRasterizationMode
的可能值,指定了保守光栅化模式如下:
// Provided by VK_EXT_conservative_rasterization
typedef enum VkConservativeRasterizationModeEXT {
VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT = 0,
VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT = 1,
VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT = 2,
} VkConservativeRasterizationModeEXT;
-
VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT
指定禁用保守光栅化,并按正常方式进行光栅化。 -
VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT
指定启用过高估计模式的保守光栅化。 -
VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
指定启用低估模式的保守光栅化。
要动态设置 conservativeRasterizationMode
,请调用
// Provided by VK_EXT_conservative_rasterization with VK_EXT_extended_dynamic_state3, VK_EXT_conservative_rasterization with VK_EXT_shader_object
void vkCmdSetConservativeRasterizationModeEXT(
VkCommandBuffer commandBuffer,
VkConservativeRasterizationModeEXT conservativeRasterizationMode);
-
commandBuffer
是将记录命令的命令缓冲区。 -
conservativeRasterizationMode
指定conservativeRasterizationMode
状态。
当使用着色器对象进行绘制,或者当图形管线在VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT
时,此命令会为后续的绘制命令设置 conservativeRasterizationMode
状态。否则,此状态由用于创建当前活动管线的 VkPipelineRasterizationConservativeStateCreateInfoEXT::conservativeRasterizationMode
值指定。
要动态设置 extraPrimitiveOverestimationSize
,请调用
// Provided by VK_EXT_conservative_rasterization with VK_EXT_extended_dynamic_state3, VK_EXT_conservative_rasterization with VK_EXT_shader_object
void vkCmdSetExtraPrimitiveOverestimationSizeEXT(
VkCommandBuffer commandBuffer,
float extraPrimitiveOverestimationSize);
-
commandBuffer
是将记录命令的命令缓冲区。 -
extraPrimitiveOverestimationSize
指定extraPrimitiveOverestimationSize
。
当使用着色器对象进行绘制,或者当图形管线在VkPipelineDynamicStateCreateInfo::pDynamicStates
中设置了 VK_DYNAMIC_STATE_EXTRA_PRIMITIVE_OVERESTIMATION_SIZE_EXT
时,此命令会为后续的绘制命令设置 extraPrimitiveOverestimationSize
状态。否则,此状态由用于创建当前活动管线的 VkPipelineRasterizationConservativeStateCreateInfoEXT::extraPrimitiveOverestimationSize
值指定。
当启用过高估计的保守光栅化时,不是在单个样本位置评估覆盖率,而是确定像素的任何部分(包括其边缘和角)是否被图元覆盖。如果像素的任何部分被覆盖,则会启用与该像素对应的片段的 覆盖掩码 的所有位。如果渲染通道具有片段密度图附件,并且启用了该片段的 覆盖掩码 的任何位,则会启用该片段的 覆盖掩码 的所有位。
为了评估哪些像素被图元覆盖,实现可以在图元的每个边缘将图元的大小增加最多 VkPhysicalDeviceConservativeRasterizationPropertiesEXT
::primitiveOverestimationSize
个像素。这可能会增加此图元生成的片段数,并表示对像素覆盖率的过高估计。
通过将 extraPrimitiveOverestimationSize
值设置为大于 0.0
的值,并以 VkPhysicalDeviceConservativeRasterizationPropertiesEXT
::extraPrimitiveOverestimationSizeGranularity
为步长,最多可增加到 VkPhysicalDeviceConservativeRasterizationPropertiesEXT
::extraPrimitiveOverestimationSize
,从而可以进一步增加此过高估计大小。这可能会进一步增加此图元生成的片段数。
用于保守光栅化的过高估计大小的实际精度在不同实现之间可能会有所不同,并且产生的结果可能仅近似于 primitiveOverestimationSize
和 extraPrimitiveOverestimationSizeGranularity
属性。当渲染通道具有片段密度图并且片段区域覆盖多个像素时,实现可能会特别更改这些近似值。
对于三角形,如果启用了 VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT
,则当图元区域覆盖片段区域内任何像素的任何部分(包括其边缘或角落)时,将生成片段。 基本多边形光栅化 中描述的平局打破规则在保守光栅化期间不适用,并且会为从多边形共享边缘生成的所有片段设置覆盖率。在光栅化后评估为零面积的退化三角形,即使对于包含零面积多边形的顶点或边缘的像素,如果 VkPhysicalDeviceConservativeRasterizationPropertiesEXT
::degenerateTrianglesRasterized
为 VK_FALSE
,则会被剔除;如果 degenerateTrianglesRasterized
为 VK_TRUE
,则会生成片段。这些退化三角形的片段输入值会从激发顶点获取其属性和深度值。退化三角形被认为是背面朝向的,如果需要,应用程序**可以**启用背面剔除。无论如何,在光栅化之前面积为零的三角形**可能**会被剔除。
对于直线,如果启用了 VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT
并且实现设置了 VkPhysicalDeviceConservativeRasterizationPropertiesEXT
::conservativePointAndLineRasterization
为 VK_TRUE
,则当直线覆盖片段区域内任何像素的任何部分(包括其边缘或角落)时,将生成片段。在光栅化后评估为零长度的退化直线,如果 VkPhysicalDeviceConservativeRasterizationPropertiesEXT
::degenerateLinesRasterized
为 VK_FALSE
,则会被剔除;如果 degenerateLinesRasterized
为 VK_TRUE
,则会生成片段。这些退化直线的片段输入值会从激发顶点获取其属性和深度值。无论如何,在光栅化之前长度为零的直线**可能**会被剔除。
对于点,如果启用了 VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT
并且实现设置了 VkPhysicalDeviceConservativeRasterizationPropertiesEXT
::conservativePointAndLineRasterization
为 VK_TRUE
,则当点正方形覆盖片段区域内任何像素的任何部分(包括其边缘或角落)时,将生成片段。
当启用低估保守光栅化时,不是在单独的采样位置评估覆盖率,而是确定像素的全部(包括其边缘和角落)是否被图元覆盖。如果整个像素被覆盖,则会生成片段,其中其 覆盖率掩码 的所有位都对应于启用的像素;否则,即使像素的某些部分被覆盖,该像素也不会被认为是覆盖的。如果片段区域内的像素未被认为是覆盖的,则会丢弃该片段。如果渲染通道具有片段密度图附件,并且片段区域内的任何像素未被认为是覆盖的,则即使某些像素被认为是覆盖的,也会丢弃该片段。
对于三角形,如果启用了 VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
,则仅当片段区域内的任何像素被生成的图元完全覆盖(包括其边缘和角落)时,才会生成片段。
对于直线,如果启用了 VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
,则当片段区域内的任何像素(包括其边缘和角落)被直线完全覆盖时,才会生成片段。
对于点,如果启用了 VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
,则仅当点正方形覆盖片段区域内任何像素正方形的全部(包括其边缘或角落)时,才会生成片段。
如果渲染通道具有片段密度图并且启用了 VK_CONSERVATIVE_RASTERIZATION_MODE_UNDERESTIMATE_EXT
,则仅当片段区域内所有像素的全部都被生成的图元、直线或点覆盖时,才会生成片段。
对于高估和低估保守光栅化模式,如果实现启用 VkPhysicalDeviceConservativeRasterizationPropertiesEXT
::fullyCoveredFragmentShaderInputVariable
特性,则片段的所有像素正方形被生成的图元完全覆盖**必须**将 FullyCoveredEXT
设置为 VK_TRUE
。