想象你是一座未来城市的规划师。旧办法是“流水线搬砖”:工人们排成一排,第一个给砖上色,第二个搬到位,第三个检查用不用,第四个砌进墙里。每块砖,不管最后要不要,都得走完全程——大量算力花在了没人看得见的废料上。图形渲染里的传统几何管线,干的就是这种活:顶点着色器逐顶点处理,几何着色器逐图元处理,剔除却发生在很晚的阶段。 Mesh Shader 给出的是“施工队承包制”:城市图纸被切成一块块街区,每支施工队独立承包一块。施工队能自己决定:这片地在山后,整片不建;这个街区离得远,盖成简装拉倒。开工前还有一位总调度,站在沙盘前看一眼全局地图,提前把用不上的区域一笔划掉。 一句话:传统管线是“一人一块砖”的流水线,Mesh Shader 是“一队一个街区”的承包制。这篇文章会用这套比喻,把 Mesh Shader 的原理、写法和性能账本一次讲透。

岗位关联

掌握 Mesh Shader,你就能从“只懂搬砖的流水线工人”升级为“能调度整座城市的工程队队长”——这正是现代游戏引擎与实时渲染处理超复杂场景的核心竞争力。

目录
  1. 可视化演示
  2. 传统管线局限
  3. 网格着色原理
  4. 网格化分块
  5. 放大着色器
  6. 编程核心要点
  7. 性能提升原理
  8. 应用与生态
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

本节配有交互动效(进入视口后自动加载,约 3KB)。

传统管线局限

想象你负责建造一座未来城市,用的是最老派的“流水线搬砖”:工人们排成一排,第一个给砖上色,第二个把砖搬到指定位置,第三个检查这块砖该不该砌,第四个才把它砌进墙里。最无奈的是,每块砖无论最后用不用得上,都得从第一个工位走到最后一个。

传统图形管线的几何处理,就是这条流水线。输入装配把顶点数据送上工位,顶点着色器逐个变换顶点,几何着色器再逐图元加工,最后才轮到光栅化。整个过程中,每个顶点只能按固定顺序走,谁也不能提前把它拦下来。

于是三个局限被摆上台面:第一,逐顶点处理让每个线程眼里只有“自己那块砖”,看不到整栋楼;第二,几何着色器一次只处理一个图元,吞吐量上不去;第三,剔除发生得太晚,大量不可见顶点已经把变换、上色的算力全花掉了。把这三条写成一个“白干账本”:

流水线搬砖的悲剧在于:你明明知道东南角那栋楼没人看,砖还是走完了全程,最后才被扔进废料堆。传统管线最疼的,就是这些“走完全程才被扔掉的砖”。

Wwaste=Nvertex×Sstages×rcull\displaystyle W_{\text{waste}} = N_{\text{vertex}} \times S_{\text{stages}} \times r_{\text{cull}}
无用工作量 = 顶点总数 × 固定阶段数 × 后期剔除率。三个因子越大,传统管线“白干”的算力越多。
  1. 顶点总数 \(N_{\text{vertex}}\)场景中需要送入管线的顶点个数。传统模式下,这些顶点无论最终可见与否,都要先进入流水线。
    Nvertex\displaystyle N_{\text{vertex}}
  2. 流水线阶段数 \(S_{\text{stages}}\)顶点从输入装配到光栅化前经过的固定工位数量,传统管线中这些阶段一步都不能跳。
    Sstages\displaystyle S_{\text{stages}}
  3. 后期剔除率 \(r_{\text{cull}}\)最终被判定为不可见、需要在光栅化前丢弃的顶点/图元比例。
    rcull\displaystyle r_{\text{cull}}
  4. 乘出浪费工作量三个因子相乘,就是传统管线中“全程白干”的总工作量,这正是 Mesh Shader 最想省掉的部分。
    Wwaste=Nvertex×Sstages×rcull\displaystyle W_{\text{waste}} = N_{\text{vertex}} \times S_{\text{stages}} \times r_{\text{cull}}

网格着色原理

于是有人提出了“施工队承包制”:城市图纸被切成一块块街区,每支施工队承包一块,自己读图纸、自己定方案,队友之间还能互相递砖递瓦,不用等前面的人干完。

技术上的本质是:Mesh Shader 完全借用了计算着色器(Compute Shader)的模型。GPU 不再安排“一个线程伺候一个顶点”,而是启动一个线程组,让几十上百个线程协作处理一小块网格。数据读取也不再被顶点缓冲区的固定布局束缚,想读哪块读哪块。

工作组内部有三种协作方式:共享显存上的中间数据,共同决定这个街区要不要输出,分工填充顶点与三角形索引。每条任务的输出量由线程组自己掌控,多退少补。GPU 的并行能力就这样被更充分地释放——用阿姆达尔定律可以估算这笔账:

施工队能共享图纸、灵活分工,当然比“每人只摸一块砖”的流水线更会用人和用人。更重要的是:每个街区(meshlet)都是独立任务,正好把 GPU 的上千条“手臂”同时用起来。

Sp=1(1−p)+pN\displaystyle S_{p} = \frac{1}{(1 - p) + \dfrac{p}{N}}
加速比取决于并行比例 p 和处理器数量 N。Mesh Shader 把每个街区变成独立任务,让 p 接近 1,从而逼近并行极限。
  1. 可并行比例 \(p\)任务中能被多个线程并行处理的部分占整体任务的比值。Mesh Shader 中每个 meshlet 的处理基本互不依赖,p 通常很高。
    p\displaystyle p
  2. 处理器数量 \(N\)GPU 能同时执行的线程或计算单元数量,现代独显有上千个核心。
    N\displaystyle N
  3. 加速比 \(S_{p}\)并行后相对完全串行的速度提升倍数,阿姆达尔定律给出理论上限。
    Sp=1(1−p)+pN\displaystyle S_{p} = \frac{1}{(1 - p) + \frac{p}{N}}
  4. 极限趋势当 N 趋于无穷时,加速比趋近于 \(1/(1-p)\),说明剩下的串行部分决定了性能天花板。
    lim⁡N→∞Sp=11−p\displaystyle \lim_{N \to \infty} S_{p} = \frac{1}{1 - p}

网格化分块

承包制虽好,队伍规模毕竟有限:一支施工队人手就那么多,一张图纸能画的楼也有上限。城市图纸必须被切成不大不小的“街区”——专业里叫 Meshlet。

Meshlet 就是 Mesh Shader 的任务单元,是一小簇顶点加一小撮三角形。它既要小到能塞进一个线程组的输出上限,又要大到不浪费调度成本,切分尺寸本身就是门手艺。

工程经验通常是:每个 meshlet 约 64~128 个顶点、126~256 个三角形。切分工具还会顺手为每个街区生成包围盒、法线锥这些“辅助情报”,让后续剔除跑得更快。不同距离上选择不同精度的 meshlet 拼法,就构成了 LOD 的网格版实现。需要多少街区,算一下就知道:

街区划得越合理,施工越省力:近处精装、远处简装、山后不建,全在图纸(meshlet 切分)阶段定好,根本不劳施工队跑腿。

Mmeshlet=⌈TtotalTmax⌉\displaystyle M_{\text{meshlet}} = \left\lceil \frac{T_{\text{total}}}{T_{\text{max}}} \right\rceil
街区总数 = 总三角形数 ÷ 单街区上限,向上取整。这是建筑总图上要画多少个“承包地块”的公式。
  1. 总三角形数 \(T_{\text{total}}\)场景模型总共包含的三角形数量,是网格化分块的输入总量。
    Ttotal\displaystyle T_{\text{total}}
  2. 单网格上限 \(T_{\text{max}}\)一个 meshlet 最多能容纳的三角形数量,由硬件输出限制和工程经验共同决定。
    Tmax\displaystyle T_{\text{max}}
  3. 向上取整运算除法若有余数,也要单独切出一个街区来装,所以用向上取整。
    ⌈TtotalTmax⌉\displaystyle \left\lceil \frac{T_{\text{total}}}{T_{\text{max}}} \right\rceil
  4. 网格总数 \(M_{\text{meshlet}}\)场景被切分出的 meshlet 总数,也是放大着色器需要逐块评估是否施工的对象数。
    Mmeshlet=⌈TtotalTmax⌉\displaystyle M_{\text{meshlet}} = \left\lceil \frac{T_{\text{total}}}{T_{\text{max}}} \right\rceil

放大着色器

施工队上场之前,还有一位总调度站在沙盘前。他把整个城市地图扫一遍:东南角没人来,划掉;西北角要建地标,派两支队精工细作。他一句话,能让一支队伍连路都不用跑。

这位总调度就是放大着色器(Amplification Shader,也叫 Task Shader)。它跑在 Mesh Shader 之前,通过 DispatchMesh 接口决定这次派出多少支 Mesh Shader 工作组,并给每支队伍捎带“工作指令”(载荷 Payload)。

放大阶段最擅长两件事:一是全局剔除,用 meshlet 的包围盒和法线锥,把屏幕外、背对相机、被遮挡的街区整块跳过;二是动态 LOD,根据相机距离决定这个街区派生精细版还是粗糙版。它一次能派出的队伍总数,由三个维度相乘得到:

没有总调度的施工队再快,也可能跑到没人的街区空忙一场;有了总调度,连路费都省了——这是传统管线最羡慕的“开局一张图,后面全靠省”。

Gdispatch=Nx×Ny×Nz\displaystyle G_{\text{dispatch}} = N_x \times N_y \times N_z
一次调度派发的工作组总数,等于 x、y、z 三个方向派发数的乘积。这个数可以大于、等于或小于街区总数,取决于每块街区的施工量。
  1. 三个方向的派发数 \(N_x, N_y, N_z\)放大着色器在 x、y、z 三个维度上各派发多少组任务。
    Nx,  Ny,  Nz\displaystyle N_x, \; N_y, \; N_z
  2. 三维相乘把三个方向的组数乘起来,得到这次 DispatchMesh 派发的 Mesh Shader 工作组总数。
    Nx×Ny×Nz\displaystyle N_x \times N_y \times N_z
  3. 派发总数 \(G_{\text{dispatch}}\)工作组总数不必等于 meshlet 数,可以大于它(一个街区多队细分),也可以小于它(一队承包多块),实际按硬件上限灵活调整。
    Gdispatch=Nx×Ny×Nz\displaystyle G_{\text{dispatch}} = N_x \times N_y \times N_z

编程核心要点

接下来给施工队写《工作手册》。手册上要写清楚:每队多少人、每人什么岗位、一队最多出几栋楼,以及最后怎么向上汇报。

Mesh Shader 的代码骨架同样有三件事:声明线程数、读取 meshlet 数据、声明输出。HLSL 里用 [numthreads(64,1,1)] 声明一队 64 人;用 SV_GroupThreadID、SV_GroupID 区分每个人在队里的编号和队伍编号;最后用 SetMeshOutputCounts 告诉硬件这队实际交了多少顶点和图元。

输出结构是“先写顶点数组,再写三角形索引数组”:把定好的顶点塞进 OutputVertices,再用一个图元数组按三个顶点索引拼出三角形。因为硬件对输出有硬性上限,meshlet 的切分尺寸必须与手册里的限制对齐:

手册写得越清楚,施工越顺:谁搬砖、谁砌墙、一队最多出几栋楼,白纸黑字,绝不超编也不窝工。

Vout≤Vmax,Pout≤Pmax,Tgroup≤Tmax\displaystyle V_{\text{out}} \leq V_{\text{max}}, \quad P_{\text{out}} \leq P_{\text{max}}, \quad T_{\text{group}} \leq T_{\text{max}}
一个线程组输出的顶点数、图元数和线程数都有硬件上限。超出上限的 shader 连编译都过不了。
  1. 输出顶点上限 \(V_{\text{max}}\)硬件规定一个 Mesh Shader 线程组最多能输出的顶点数,超了就编译失败。
    Vout≤Vmax\displaystyle V_{\text{out}} \leq V_{\text{max}}
  2. 输出图元上限 \(P_{\text{max}}\)一个线程组能输出的三角形或图元数同样有上限,meshlet 尺寸要据此反推。
    Pout≤Pmax\displaystyle P_{\text{out}} \leq P_{\text{max}}
  3. 线程数上限 \(T_{\text{max}}\)numthreads 声明的线程数不能超过硬件允许的工作组规模。
    Tgroup≤Tmax\displaystyle T_{\text{group}} \leq T_{\text{max}}

性能提升原理

承包制为什么快?说穿了就一句话:不干没用的活。流水线上所有砖都走完全程,承包制下看不见的街区从根上就不去。

性能红利有两个来源:一是剔除更早,放大阶段和网格阶段直接把不可见几何整块扔掉,比起传统后期裁剪,等于省下了整个前面工段;二是带宽更省,被丢弃的数据压根没进入渲染管线,显存读取量大幅下降。GPU 是“以数据搬运为命”的,少读一方数据,就多一分帧时间。

不过收益不是白来的,它取决于场景的“可见率”——看得见的部分在总几何里占多大比例:

换句话讲,Mesh Shader 的加速本质是“让 GPU 只给看得见的城市干活”。可见率越高,优势越明显;即便全部可见,它还能靠并行结构本身带来额外收益。

η=NvisibleNvisible+Nculled\displaystyle \eta = \frac{N_{\text{visible}}}{N_{\text{visible}} + N_{\text{culled}}}
可见率 = 可见图元数 ÷ 总图元数。可见率越高,说明可剔除的冗余越少;但它越低,Mesh Shader 的提前剔除就越赚。
  1. 可见图元数 \(N_{\text{visible}}\)最终真正进入光栅化渲染的图元数量。
    Nvisible\displaystyle N_{\text{visible}}
  2. 被剔除图元数 \(N_{\text{culled}}\)被放大阶段或网格阶段提前丢掉的图元数量,这些在传统管线里都白走了一遍。
    Nculled\displaystyle N_{\text{culled}}
  3. 可见率 \(\eta\)可见图元占总图元的比例,直接反映“提前剔除”能带来多大的性能空间。
    η=NvisibleNvisible+Nculled\displaystyle \eta = \frac{N_{\text{visible}}}{N_{\text{visible}} + N_{\text{culled}}}

应用与生态

施工队再神勇,也要有趁手的图纸工具和愿意改革的开发商。好消息是,这套“承包制”的生态已经开始跑起来了。

开发者主要通过 DirectX 12(Shader Model 6.5)和 Vulkan(VK_EXT_mesh_shader)标准接口使用 Mesh Shader。游戏引擎这边,虚幻引擎 5 的 Nanite 是标志性实践,AMD 的 FidelityFX 也提供了配套工具链,把 meshlet 的生成、剔除和 LOD 打包成开箱即用的方案。

硬件方面,NVIDIA Turing/Ampere 及后续架构、AMD RDNA 2 及后续架构都已原生支持;调试可以用 RenderDoc、Nsight Graphics 这类工具,直接看到每个 meshlet 和线程组的执行情况。学习路线上,建议先吃透计算着色器,再迁移到 Mesh Shader 的写法,会顺手很多。至于这套技术值不值得上,可以算一笔带宽账:

当整个行业都学会了“承包制”,游戏世界的城市规模就会迎来一次真正的扩建。Mesh Shader 现在要做的,就是让每个开发者都能画出这种“带街区的图纸”。

Bsaved=Bfull−BafterBfull×100%\displaystyle B_{\text{saved}} = \frac{B_{\text{full}} - B_{\text{after}}}{B_{\text{full}}} \times 100\%
带宽节省率 =(优化前带宽 − 优化后带宽)÷ 优化前带宽 × 100%。剔除的数据越早被扔掉,省下的显存搬运越多。
  1. 优化前带宽 \(B_{\text{full}}\)传统管线要把全部几何数据读进 GPU 所需的显存带宽。
    Bfull\displaystyle B_{\text{full}}
  2. 优化后带宽 \(B_{\text{after}}\)Mesh Shader 经过提前剔除后,实际只搬运可见数据所需的带宽。
    Bafter\displaystyle B_{\text{after}}
  3. 带宽节省率用两者差值除以优化前带宽并百分化,就是这套管线省下的搬运成本。
    Bsaved=Bfull−BafterBfull×100%\displaystyle B_{\text{saved}} = \frac{B_{\text{full}} - B_{\text{after}}}{B_{\text{full}}} \times 100\%

AI 应用场景

场景一:开放世界程序化场景实时渲染

阶段:内容生成与渲染优化(程序化几何生成 + 网格级剔除)

解决的问题:AI 程序化生成的地形、植被和建筑会产生海量三角形,传统顶点流水线逐个处理顶点,百万级几何体很快把 GPU 算力耗尽。Mesh Shader 把生成结果切分成街区(meshlet),由总调度按可见性整块派活,AI 生成的几何再多也不怕。

具体案例:某开放世界游戏的森林场景,AI 实时生成数万棵树木,每棵树数万三角形。使用 Mesh Shader 后,远处树木用粗粒度 meshlet,视锥外的树木在放大阶段整块跳过,帧时间从 30ms 降到 12ms。

场景二:虚拟制片与数字人实时预览

阶段:推理后处理与实时显示(AI 重建资产 + meshlet LOD 管理)

解决的问题:影视级扫描资产经 AI 重建后常达上亿三角形,传统流程只能离线渲染。Mesh Shader 支持按 meshlet 动态加载与丢弃,导演实时转动视角时,只有可见且近处的街区被精细施工。

具体案例:虚拟片场里,AI 重建的实景扫描模型在引擎中实时预览,灯光与角度自由调整,监看画面始终流畅,后期团队不用再等离线渲染。

场景三:元宇宙大规模虚拟活动

阶段:实时渲染与人群模拟(多智能体生成 + 网格化裁剪)

解决的问题:AI 驱动的数万个虚拟观众、摊位和装置同时出现在一个场景,传统管线难以承受。放大着色器按观众位置与朝向整块丢弃背面街区,计算量随“看得见的区域”而非“总资产量”增长。

具体案例:元宇宙演唱会中,五万名 AI 驱动的观众各自携带高精度服装与表情网格,Mesh Shader 保证普通显卡也能流畅观看面向舞台的画面。

Python 演示

python40 行
import mathimport random  class MeshletPipeline:    """Simulate meshlet-based culling vs traditional pipeline."""     def __init__(self, total_tri, max_tri_per_meshlet, visible_ratio):        self.total_tri = total_tri        self.max_tri = max_tri_per_meshlet        self.visible_ratio = visible_ratio        self.meshlet_count = math.ceil(total_tri / max_tri_per_meshlet)        self.culled = 0     def cull_simulate(self, seed=42):        rnd = random.Random(seed)        self.culled = 0        for _ in range(self.meshlet_count):            if rnd.random() > self.visible_ratio:                self.culled += 1     def report(self):        trad_work = self.total_tri * 4   # 传统管线4个固定阶段        mesh_work = (self.meshlet_count - self.culled) * 64  # 64线程一组        saved = (trad_work - mesh_work) / trad_work * 100        print("total triangles:", self.total_tri)        print("meshlets:", self.meshlet_count,              "(max", self.max_tri, "tri per meshlet)")        print("culled meshlets:", self.culled,              "(%.1f%%)" % (self.culled / self.meshlet_count * 100))        print("traditional work units:", trad_work)        print("mesh shader work units:", mesh_work)        print("saved ratio: %.1f%%" % saved)  if __name__ == "__main__":    sim = MeshletPipeline(total_tri=1000000, max_tri_per_meshlet=126,                          visible_ratio=0.6)    sim.cull_simulate()    sim.report()
目的:用 Python 模拟传统流水线与 Mesh Shader 网格化剔除的工作量差异,直观感受“看不见的街区整块跳过”带来的算力节省。
  1. self.meshlet_count = math.ceil(total_tri / max_tri_per_meshlet)把总三角形切分成街区,向上取整得到网格数。
  2. if rnd.random() > self.visible_ratio:模拟总调度判断这个街区是否可见,不可见就整块跳过。
  3. self.culled += 1被扔掉的街区计数累加,对应放大阶段的整块剔除。
  4. trad_work = self.total_tri * 4传统管线里每块砖都要走 4 个固定工位,全部算作工作量。
  5. mesh_work = (self.meshlet_count - self.culled) * 64网格着色器只派工给可见街区,每队 64 个线程。
  6. saved = (trad_work - mesh_work) / trad_work * 100计算“白干”减少的比例,即正文中算力/带宽节省的简化模型。

常见误区

误区初学者看名字里都有"Shader",以为 Mesh Shader 就是把几何着色器改快一点,处理逻辑完全一样。

正解几何着色器仍是“一个线程处理一个图元”的流式模型,Mesh Shader 则是“一个线程组合作处理一个街区”的计算模型。如同流水线工人(一个人搬一块砖)与施工队(一群人盖一栋楼)的区别,底层模型根本不同。

为何常见:因为两者都出现在顶点着色和光栅化之间,位置相近,很容易被归为同类。

误区觉得 Mesh Shader 是“黑科技”,GPU 会自动把看不见的几何全扔掉,性能自动起飞。

正解Mesh Shader 只是提供了更早、更灵活的剔除位置,视锥剔除、背面剔除、遮挡剔除这些判断都要开发者自己写。它更像给了你一把“提前扔砖”的特权,用不用、怎么用,由代码决定。

为何常见:厂商演示里 Mesh Shader 场景几何量惊人,容易让人误以为一切都是自动完成的。

误区既然处理单位越小越精细,那就把 meshlet 切成几个三角形,剔除精度肯定更高。

正解meshlet 太小会导致调度开销和线程利用率双重恶化:每块街区都派一支施工队,人还没站好就干完了。通常每个 meshlet 64~128 顶点、126~256 三角形是工程上较平衡的规模。

为何常见:从“剔除粒度越细越高效”的直觉出发,忽略了任务调度本身也有固定成本。

误区Mesh Shader 出现后,顶点/几何着色器很快会消失,所有项目都必须迁移。

正解传统管线在简单场景下依旧简单高效,且兼容性广泛;Mesh Shader 是处理超复杂场景的“重兵器”,是否使用取决于场景复杂度与目标硬件,很多引擎仍以传统路径为默认。

为何常见:新技术的宣传节奏容易让人产生“非黑即白”的换代错觉。

面试题

Q1. Mesh Shader 处理几何体的核心思路是什么?

单选题 · easy

  • A.固定流水线顺序执行
  • B.计算着色器并行思路← 正确答案
  • C.仅靠 CPU 软件模拟
  • D.像素着色器逐像素上色

答案:B。Mesh Shader 的本质是“用计算着色器的协作模型处理几何”,线程组共同处理一个街区;它不是固定流水线顺序,也不依赖 CPU 模拟或像素级处理。

Q2. 下列哪项是 meshlet 的正确描述?

单选题 · easy

  • A.一张完整的城市总图纸
  • B.被切分的小块几何网格← 正确答案
  • C.负责光照的专用着色器
  • D.一种显存容量计量单位

答案:B。meshlet 是网格切分后的小块几何单元,包含若干顶点和三角形,是 Mesh Shader 的任务单位;它是“街区”而非常景总图、光照器或容量单位。

Q3. 一个 Mesh Shader 线程组通常包含约多少线程?

单选题 · easy

  • A.只有一个线程独立作业
  • B.三十二到一百二十八个← 正确答案
  • C.恰好等于屏幕像素数量
  • D.数量必须超过一万个

答案:B。工程上常用 32~128 线程匹配 meshlet 规模;单线程无法协作,像素数量或万级线程都不符合实际硬件和任务特征。

Q4. Amplification Shader 的核心职责是什么?

单选题 · mid

  • A.决定派发多少网格工作组← 正确答案
  • B.负责给所有顶点逐一上色
  • C.把像素合成到最终画面
  • D.管理 CPU 的内存分配

答案:A。放大着色器(Task Shader)在网格着色器前运行,通过 DispatchMesh 决定派发多少工作组;上色、合成、内存分配都不是它的职责。

Q5. 与传统管线相比,Mesh Shader 的剔除优势体现在哪?

单选题 · mid

  • A.剔除发生在更早的阶段← 正确答案
  • B.剔除完全不需要再执行
  • C.剔除只能在光栅化后做
  • D.剔除结果不影响性能

答案:A。Mesh Shader 让剔除发生在放大/网格阶段,几何还没进光栅就被整块丢弃;但剔除仍需开发者写,其执行时机正是性能优势的来源。

Q6. 关于 Mesh Shader 的输出限制,下列说法正确的是?

单选题 · mid

  • A.输出顶点与图元数有上限← 正确答案
  • B.输出颜色必须全部为黑色
  • C.输出数据不能写入显存
  • D.输出结果只能有一根线段

答案:A。硬件规定每个线程组的顶点/图元输出上限,超限编译失败;颜色、显存写入、线段数量都不是它的核心限制。

Q7. 场景可见率 η 的数学定义是什么?

单选题 · hard

  • A.可见图元数除以总图元数← 正确答案
  • B.总图元数除以可见图元数
  • C.被剔除图元占可见图元比
  • D.顶点数量乘以流水阶段数

答案:A。可见率 η = 可见图元数 / 总图元数,用来衡量可剔除冗余的空间;其余选项要么把分子分母颠倒,要么混入了无关量。

Q8. 传统几何管线的局限有哪些?

多选题 · mid

  • A.逐顶点处理难以纵览全局← 正确答案
  • B.剔除发生太晚浪费算力← 正确答案
  • C.几何着色器吞吐量偏低← 正确答案
  • D.完全不需要任何数据输入

答案:ABC。逐顶点无全局视野、剔除晚导致浪费、几何着色器单图元吞吐低,都是传统管线痛点;D 与事实完全相反,管线必须有数据输入。

Q9. Mesh Shader 提升性能的主要原因是什么?

多选题 · hard

  • A.提前整块剔除不可见几何← 正确答案
  • B.降低显存带宽占用开销← 正确答案
  • C.让 GPU 不再处理任何几何
  • D.更充分利用线程并行性← 正确答案

答案:ABD。提前剔除、带宽降低、并行度提升是三大红利;即使剔除再高效,GPU 仍要处理可见几何,所以 C 是误解。

Q10. DirectX 12 在哪个着色器模型中引入 Mesh Shader?

单选题 · extreme

  • A.六点五版本着色器模型← 正确答案
  • B.五点零版本着色器模型
  • C.六点零版本着色器模型
  • D.七点零版本着色器模型

答案:A。DirectX 12 的 Shader Model 6.5 引入 Mesh Shader(及 Amplification Shader),这是判断技术代际的行业常识;其余版本号错误。