【Vulkan】Variable Rate Shading(一)
Variable Rate Shading
配置
依赖、特性、属性
-
使能 Device 扩展:
VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME
或者 “VK_KHR_fragment_shading_rate” -
查询 DeviceFeature(依赖
vkGetPhysicalDeviceFeatures2
)
VkPhysicalDeviceFragmentShadingRateFeaturesKHR
pipelineFragmentShadingRate
:per-draw fragment shading rate 基于 drawcall 粒度primitiveFragmentShadingRate
:per-triangle fragment shading rate 基于 triangle 粒度attachmentFragmentShadingRate
:per-screen-region fragment shading rate 基于屏幕空间区域粒度
-
查询 DeviceProperties(依赖
vkGetPhysicalDeviceProperties2
)
typedef struct VkPhysicalDeviceFragmentShadingRatePropertiesKHR {
VkStructureType sType;
void* pNext;
VkExtent2D minFragmentShadingRateAttachmentTexelSize;
VkExtent2D maxFragmentShadingRateAttachmentTexelSize;
uint32_t maxFragmentShadingRateAttachmentTexelSizeAspectRatio;
VkBool32 primitiveFragmentShadingRateWithMultipleViewports;
VkBool32 layeredShadingRateAttachments;
VkBool32 fragmentShadingRateNonTrivialCombinerOps;
VkExtent2D maxFragmentSize;
uint32_t maxFragmentSizeAspectRatio;
uint32_t maxFragmentShadingRateCoverageSamples;
VkSampleCountFlagBits maxFragmentShadingRateRasterizationSamples;
VkBool32 fragmentShadingRateWithShaderDepthStencilWrites;
VkBool32 fragmentShadingRateWithSampleMask;
VkBool32 fragmentShadingRateWithShaderSampleMask;
VkBool32 fragmentShadingRateWithConservativeRasterization;
VkBool32 fragmentShadingRateWithFragmentShaderInterlock;
VkBool32 fragmentShadingRateWithCustomSampleLocations;
VkBool32 fragmentShadingRateStrictMultiplyCombiner;
} VkPhysicalDeviceFragmentShadingRatePropertiesKHR;
-
查询 FragmentShadingRates
fragment shading rate 与 MutliSample 密切相关,可通过vkGetPhysicalDeviceFragmentShadingRatesKHR
返回一组排序后的 Device 支持的 [fragmentSize, multiSample] 配置。- width 与 height 必须为 2^N
- width * height * maxSample <=
maxFragmentShadingRateCoverageSamples
厂商实现必须至少支持:
samplerCounts fragmentSize VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT {2,2} VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT {2,1} ~0 {1,1}
Pipeline Fragment Shading Rate (per draw)
typedef struct VkPipelineFragmentShadingRateStateCreateInfoKHR {
VkStructureType sType;
const void* pNext;
VkExtent2D fragmentSize;
VkFragmentShadingRateCombinerOpKHR combinerOps[2];
} VkPipelineFragmentShadingRateStateCreateInfoKHR;
fragmentSize :定义使用当前 pso 绘制区域 pipeline fragment shadeing rate 的大小。
combinerOps[0] :组合 pipeline and primitive
combinerOps[1] :组合 [0] 结果 和 attachment
组合选项:
CombinerOp | result |
---|---|
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR | Combine(A, B) = A |
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE_KHR | Combine(A, B) = B |
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MIN_KHR | Combine(A, B) = min(A, B) |
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MAX_KHR | Combine(A, B) = max(A, B) |
VK_FRAGMENT_SHADING_RATE_COMBINER_OP_MUL_KHR | Combine(A, B) = A * B |
简单的 4 x 4 pipeline perDraw 试验,下图左边三角形关闭 vrs,右边开启
Primitive Fragment Shading Rate (per primitive)
主要在 shader 中进行处理,需要 glsl 扩展 GL_EXT_fragment_shading_rate
新增关键字:
关键字 | 说明 |
---|---|
gl_ShadingRateEXT | primitive shading rate 输出 |
gl_ShadingRateFlag2VerticalPixelsEXT | Vertical2Pixels,bitValue: 1 |
gl_ShadingRateFlag4VerticalPixelsEXT | Vertical4Pixels,bitValue: 2 |
gl_ShadingRateFlag2HorizontalPixelsEXT | Horizontal2Pixels,bitValue: 4 |
gl_ShadingRateFlag4HorizontalPixelsEXT | Horizontal4Pixels,bitValue: 8 |
gl_PrimitiveShadingRateEXT | fragment shader 输入 |
VS 中处理示例:
void main() {
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
gl_PrimitiveShadingRateEXT = gl_ShadingRateFlag2VerticalPixelsEXT | gl_ShadingRateFlag2HorizontalPixelsEXT;
// gl_PrimitiveShadingRateEXT = gl_ShadingRateFlag2VerticalPixelsEXT | gl_ShadingRateFlag4HorizontalPixelsEXT;
// gl_PrimitiveShadingRateEXT = gl_ShadingRateFlag4VerticalPixelsEXT | gl_ShadingRateFlag2HorizontalPixelsEXT;
// gl_PrimitiveShadingRateEXT = gl_ShadingRateFlag4VerticalPixelsEXT | gl_ShadingRateFlag4HorizontalPixelsEXT;
outColor = color[gl_VertexIndex];
}
Attachment Fragment Shading Rate (per screen retion)
使用 RenderPass 进行配置,需要 ‘vkCreateRenderPass2’,基于 SubPass 粒度,pNext 添加结构体
typedef struct VkFragmentShadingRateAttachmentInfoKHR {
VkStructureType sType;
const void* pNext;
const VkAttachmentReference2* pFragmentShadingRateAttachment;
VkExtent2D shadingRateAttachmentTexelSize;
} VkFragmentShadingRateAttachmentInfoKHR;
shadingRateAttachmentTexelSize
受以下限制
minFragmentShadingRateAttachmentTexelSize
, 需要 2^N, Spec 保证至少支持(32, 32)maxFragmentShadingRateAttachmentTexelSize
, 需要 2^N, Spec 保证至少支持(8, 8)maxFragmentShadingRateAttachmentTexelSizeAspectRatio
添加 ShadingRateAttachment,同时增加
- Access Flag:
VK_ACCESS_FRAGMENT_SHADING_RATE_ATTACHMENT_READ_BIT_KHR
同VK_ACCESS_SHADING_RATE_IMAGE_READ_BIT_NV
- PipelineStage:
VK_PIPELINE_STAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
同VK_PIPELINE_STAGE_SHADING_RATE_IMAGE_BIT_NV
- Image Usage:
VK_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR
同VK_IMAGE_USAGE_SHADING_RATE_IMAGE_BIT_NV
- Image Layout:
VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR
同VK_IMAGE_LAYOUT_SHADING_RATE_OPTIMAL_NV
对应的 FrameBuffer 只需要添加对应的 slot 的 ImageView 即可,需要控制 ShadingRate Attachment 大小
- width:fbWidth / texelWidth
- height: fbHeight / texelHeight