7.2 网格着色与可变速率着色


文档摘要

7.2 网格着色与可变速率着色 本节摘要:两个改写「算力花在哪」的扩展:网格着色把几何管线换成任务加网格的两阶段编程模型,让剔除与生成在进光栅化之前发生;可变速率着色按内容分配片段着色密度,把看不见的区域的算力省下来。本节讲两者的模型、粒度与收益算法,并给出组合实战。 别以为图形管线的起点永远是「CPU 读顶点缓冲、硬件做图元装配」——这套 1990 年代定型的流程在超多边形场景里有个结构性浪费:所有几何先装配、先变换,再在光栅化时被大量丢弃。网格着色(VKEXTmeshshader)干脆换了起点;可变速率着色(VKKHRfragmentshadingrate)则从管线末端继续省钱。两者一前一后,把「按需分配算力」做成了 API 能力。

7.2 网格着色与可变速率着色

本节摘要:两个改写「算力花在哪」的扩展:网格着色把几何管线换成任务加网格的两阶段编程模型,让剔除与生成在进光栅化之前发生;可变速率着色按内容分配片段着色密度,把看不见的区域的算力省下来。本节讲两者的模型、粒度与收益算法,并给出组合实战。

别以为图形管线的起点永远是「CPU 读顶点缓冲、硬件做图元装配」——这套 1990 年代定型的流程在超多边形场景里有个结构性浪费:所有几何先装配、先变换,再在光栅化时被大量丢弃。网格着色(VK_EXT_mesh_shader)干脆换了起点;可变速率着色(VK_KHR_fragment_shading_rate)则从管线末端继续省钱。两者一前一后,把「按需分配算力」做成了 API 能力。

一、网格着色:任务与网格两阶段

新管线只有两个可编程阶段。任务着色器(task,可选):决定「派多少个网格工作组」,做粗粒度剔除与放大控制;网格着色器(mesh):直接产出顶点与图元索引,绕过顶点装配硬件。输入不再是顶点缓冲的隐式绑定,而是你自定义的数据(典型是 meshlet 列表——把大网格预切成几十到上百顶点的小簇,簇带包围球)。

#version 450 #extension GL_EXT_mesh_shader : require layout(local_size_x = 32) in; taskPayloadSharedEXT struct { uint meshletIds[32]; } payload; void main() { uint mId = gl_WorkGroupID.x * 32 + gl_LocalInvocationID.x; Meshlet m = meshlets[mId]; // 粗剔除:整簇包围球不可见则整组不派发 payload.meshletIds[gl_LocalInvocationID.x] = sphereVisible(m.sphere) ? mId : INVALID; EmitMeshTasksEXT(1, 1, 1); // 派发给网格阶段 }

网格阶段随后逐簇输出:可见簇的顶点进 mesh 输出数组、图元写索引,不可见簇零成本跳过。收益的算法很直白:省下的是「变换与装配被光栅化丢弃」的那部分。植被、毛发、城市这类「多边形海量、屏幕覆盖小」的内容,丢弃率常在高位,收益巨大;全屏覆盖的地面拼片反而几乎无收益。迁移成本集中在资产管线(切 meshlet、建簇包围体)与代码架构(放弃固定顶点输入的假设)。

二、可变速率着色:片段密度即预算

传统管线每个像素跑一次片段着色器。可变速率着色(VRS)允许按块(例如两个像素乘两个像素一个着色点)执行,四档粒度从粗到细:

粒度 指定方式 适用
管线级 管线创建时声明 整个通道统一降率(如模糊链)
绘制级 vkCmdSetFragmentShadingRate 按物体粗调(天空、远景)
图元级 着色器输出 primitive shading rate 按三角形精细控制
屏幕分块 速率图像附件 按区域自适应(中央清晰边缘粗)

粒度可以叠加组合器(combiner)决定多层速率怎么合并(取更粗或更细)。内容自适应的标准做法是屏幕分块:CPU 或计算着色器按亮度梯度、运动向量、注视点(配合眼动追踪扩展)为每个分块定速率——快动区域人眼分辨不出细节,两个像素一块毫无感知。移动端还有一笔额外账:片段着色次数直接关联功耗与发热,VRS 是续航工具而不只是帧率工具。

三、案例:植被场景的组合改造

背景:一款开放世界 Demo 的森林场景瓶颈明确:四十万实例植被的几何处理占帧时间四成,全屏后处理又把片段着色推满,两头都挤。

操作:双管齐下。几何侧迁移网格着色:资产管线按簇预切植被网格(每簇约六十四顶点),任务阶段按包围球与朝向剔除整簇,风场摆动在网格阶段以簇为单位完成;被遮挡与远距离簇在进入光栅化之前清零。片段侧接 VRS:主场景全速率,远景植被带两个像素一块,运动模糊触发时分块速率再放粗一档,速率由计算着色器按运动向量每帧生成。

结果:几何段耗时降到原来的四成,片段着色开销按速率图实际分布下降约三成;两个扩展的可探测性检查让老设备自动回退到传统管线(植被改用实例剔除加 LOD 链兜底)。

解读:这个案例里两个扩展解决的是同一预算表的两行——顶点处理与片段处理,互不替代。值得注意的是回退路径的成本:网格着色的 meshlet 资产在传统管线下要能拼回顶点缓冲,资产格式设计时就该为双路线留门。

变式:纯性能视角之外,VRS 在注视点渲染(VR/AR)里是刚需级能力——外围视场以粗速率着色,与眼动数据联动后省率可达数倍。那一场景下分块速率图像由系统层注入,应用只需声明支持。

四、两个高频疑问

接入前被问得最多的两个问题,提前放在这里。其一,「meshlet 切多大合适?」经验区间是每簇六十四到一百二十八个顶点、约等于簇顶点数四分之一的图元数——簇越小剔除越精细,但任务与网格调度的固定开销占比越高;官方示例的切簇参数可以直接当起点,再按自家内容扫描几组对比。其二,「VRS 会让画质明显变糊吗?」粗速率块的边界在静态画面里肉眼可辨,但在运动画面与后处理(抗锯齿、上采样)之后基本被掩盖——把速率图与运动强度、深度差绑定,只对「人眼本来就不看细节」的块放粗,是画质无损的关键约束。

还有一个工程提醒:两个扩展都改动了「管线假设」——网格着色管线没有顶点输入状态结构,VRS 改变片段调用量会影响时间戳与占用率的解读。做性能对比时,新旧路径要分别基线测量,别拿旧管线的数字直接对照。

五、要点回顾

  • 换起点:网格着色以任务加网格两阶段取代顶点装配,剔除与生成发生在光栅化之前。
  • 收益有形态:海量低覆盖几何(植被、毛发、城市)收益最大,全屏高覆盖内容几乎不赚。
  • 密度即预算:VRS 四档粒度(管线、绘制、图元、分块)逐级精细,分块速率图是内容自适应的主载体。
  • 移动端双收益:VRS 同时是帧率与续航工具,功耗视角在移动选型里权重更高。
  • 回退要预设:能力探测不通过时自动落回传统路线,资产格式为双路线留门。

收尾给一条组合建议:两个扩展的探测、启用、回退框架可以共用同一套「能力分级」代码(与 7.3 的体检三步法一致),项目里做成统一的扩展管理模块——高级特性接得越多,这套基建的复利越明显。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U