Chapter 5: GPU Performance Constraints
实时渲染里的性能问题要落到一帧里判断。本章使用同一帧作为贯穿材料:一个城市广场场景,目标是 60 FPS,单帧预算约 16.67 ms。场景包含阴影贴图、G-buffer、延迟光照、透明玻璃、草地实例、后处理和 UI。读完本章后,读者应能定位一帧耗时来自 CPU 提交、GPU pass、shader 执行、带宽、draw call、同步等待还是呈现链路,并能根据硬件特性选择调优方向。
GPU 性能约束通常表现为“某个 pass 慢”“帧时间波动”“同样画面在移动设备上掉帧”“draw 数量上去后 CPU 时间增加”。这些症状背后对应不同资源路径:CPU 负责生成和提交命令,GPU 负责执行图形和计算任务,显存或统一内存负责搬运纹理、buffer 和 render target 数据,驱动与 API 负责状态合法性、队列依赖和呈现协调。
本章的主线是把性能现象还原为一条 frame 路径。先建立性能限制的分类,再给出一套可复用的帧分析流程,随后讨论 draw call 与状态切换成本,最后把 tile-based、immediate-mode、unified memory、RT core、mesh shader 等硬件特性放回调优判断中。
5.1 性能限制的主要来源
性能限制的来源可以按资源路径分成三类:带宽约束、执行瓶颈和资源竞争。带宽约束发生在数据搬运路径上,执行瓶颈发生在 shader、固定功能单元或专用单元上,资源竞争发生在多个 pass、队列、buffer、纹理、cache 或同步点争用同一类资源时。用这三个入口分类,能让一帧的性能分析从“感觉慢”变成“哪条路径受限”。
在城市广场这一帧里,最先观察的是 frame breakdown:shadow pass、G-buffer pass、lighting pass、transparent pass、post-processing pass、UI pass 和 present。单看总耗时只能知道帧超预算,无法判断根因。每个 pass 都需要继续拆成输入资源、管线阶段和输出资源:shadow pass 主要读取场景几何并写深度贴图;G-buffer pass 读取顶点、材质纹理并写多个 render target;lighting pass 读取 G-buffer、shadow map 和 light buffer 并写 HDR color;transparent pass 读取颜色与深度并执行混合;post-processing 读取 HDR color 并写中间纹理或 swapchain。
带宽约束的典型路径是“读写字节量超过内存系统能稳定供应的吞吐”。G-buffer pass 常见带宽压力来自多个 render target 写入,例如 albedo、normal、roughness、metallic、depth。每个像素写入的字节数越高,分辨率越高,MSAA sample 数越高,render target 带宽压力越高。纹理采样也会形成带宽压力:高分辨率材质、随机 UV、缺少 mipmap、各向异性采样倍率过高,都会让 texture cache 命中率下降,并把成本转移到内存系统。
执行瓶颈的典型路径是“GPU 计算单元或固定功能单元忙于执行当前任务”。fragment shader 中的复杂 BRDF、多个动态光源循环、阴影采样、噪声函数、分支发散,会增加 ALU 和 texture 单元压力。vertex shader 中的 skinning、morph target、过多矩阵读取,会增加顶点阶段成本。光栅化阶段的大面积透明物体、过多 overdraw、深度测试失效,会让同一屏幕区域反复执行片元工作。
资源竞争的典型路径是“多个任务需要同一类硬件或同一份数据,调度只能串行推进或产生等待”。例如 compute shader 在同一帧内写入一个后续 graphics pass 要读取的 texture,这个边界需要资源状态转换和同步。Vulkan 的 Synchronization 文档强调,应用需要管理同步原语,使用不当会产生难以定位的错误和 GPU 空闲。对性能分析来说,同步点既是正确性边界,也是潜在等待来源。
可以用一个资源路径图把三类限制放到同一帧里。图中的节点代表分析对象,箭头代表一次可观察的耗时归因路径。
这张图的读法是:帧耗时先拆到 CPU、GPU 和呈现三个区域;GPU 区域再拆成 shader 执行、资源读取、render target 写入和同步;资源读取与写入共同指向带宽;shader 指向执行单元;同步指向 idle 或 stall。一次性能分析应沿这条路径收集证据,而非直接套用某个优化技巧。
性能限制还需要区分“平均慢”和“波动慢”。平均慢表示某条路径稳定超预算,例如 G-buffer 每帧都占 7 ms。波动慢表示某些帧突然超预算,例如上传纹理、编译 pipeline、读取 query、等待 fence 或 swapchain 背压。平均慢通常从 pass 和 shader 开始定位,波动慢通常从资源生命周期、缓存、同步和呈现队列开始定位。
一个实用分类表如下。
| 症状 | 首先观察的对象 | 常见根因 | 可验证证据 |
|---|---|---|---|
| GPU 时间稳定偏高 | pass timing | fragment shader、overdraw、render target 写入 | GPU timer、draw event、pixel cost |
| CPU 时间稳定偏高 | command recording 和 submit | draw call 多、状态切换多、descriptor 更新多 | CPU profiler、API trace |
| 分辨率升高后耗时接近平方增长 | full-screen pass 和 render target | 像素带宽、后处理、透明混合 | 降分辨率对比、RT 格式对比 |
| 材质数量增多后耗时升高 | pipeline state 和 resource binding | state change、shader variant、descriptor churn | draw sorting 对比、pipeline switch 统计 |
| 偶发尖峰 | upload、pipeline creation、fence、query readback | 同步等待或运行时资源创建 | timeline、queue wait、allocation trace |
在城市广场这一帧里,如果关闭草地后 GPU 时间下降明显,草地可能受顶点数量、实例数据读取、alpha test、overdraw 或阴影投射影响。下一步需要分别观察 shadow pass、G-buffer pass 和透明或 alpha cutout draw。相同视觉对象可能在多个 pass 中重复贡献成本,分析时要按 pass 归因,再回到对象层合并判断。
5.2 实时渲染性能分析流程
实时渲染性能分析应按固定顺序推进:先分离 CPU 与 GPU,再定位慢 pass,再进入 draw 和 shader,再验证带宽与同步,最后检查呈现链路。这个顺序的价值在于每一步都减少候选根因。跳过 CPU/GPU 分界直接改 shader,会把提交开销、同步等待和呈现阻塞误判成 shader 问题。
第一步是建立帧预算和测量边界。60 FPS 对应约 16.67 ms,120 FPS 对应约 8.33 ms。测量时要区分 CPU frame time、GPU frame time 和 wall-clock frame time。CPU frame time 表示应用线程组织一帧所需时间;GPU frame time 表示 GPU 执行已提交命令所需时间;wall-clock frame time 还会包含 VSync、swapchain、窗口系统和调度影响。三者需要分别观察。
第二步是使用时间戳或 profiler 把一帧拆成 pass。RenderDoc、NVIDIA Nsight Graphics、Xcode GPU tools、PIX、Radeon GPU Profiler 都可以提供不同生态下的入口。工具名称本身不构成结论;工具提供的计时、draw event、resource binding、pipeline state、shader 统计和同步信息,才是判断依据。
第三步是在最慢 pass 内定位 draw 或 dispatch。以 G-buffer pass 为例,如果这个 pass 占 6 ms,需要按 material、mesh、instance group 或 render queue 分组查看 draw。一个 draw 慢,常见原因是 shader 复杂、纹理采样多、几何量大、overdraw 高或 render target 写入重。大量 draw 累积慢,常见原因是 CPU 提交、状态切换、descriptor 更新和资源绑定成本。
第四步是进入 shader 与资源。shader 分析要看输入属性、uniform 或 constant buffer、texture、sampler、分支、循环、输出 render target。fragment shader 受屏幕覆盖面积影响;vertex shader 受顶点数量和属性读取影响;compute shader 受 dispatch 规模、group size、shared memory、buffer 访问模式和 barrier 影响。相同 shader 在不同 draw 上成本可能不同,因为覆盖面积、纹理局部性和分支路径不同。
第五步是验证带宽。最直接的实验是改变数据量:降低分辨率、减少 render target 数量、改用压缩纹理、降低采样次数、关闭某个全屏 pass、切换 RT 格式、关闭 MSAA 或降低 shadow map 尺寸。如果耗时随像素数、采样数或写入字节数同步下降,带宽或像素路径就是主要候选。实验需要一次只改变一个变量,并记录原始帧、修改帧和视觉差异。
第六步是验证同步与队列等待。现代 API 中,barrier、fence、semaphore、event、resource state transition 和 queue ownership 都可能影响执行顺序。同步问题的证据通常表现为队列空洞、某个 pass 前后存在等待、CPU 读取 GPU query 触发阻塞、present 等待过长或资源上传与渲染共享同一临时 buffer。Vulkan 同步文档中的 pipeline barrier 描述指出,barrier 控制 command buffer 执行时哪些 pipeline stage 需要等待前序 stage;这类等待在调试正确性时必要,在性能路径上需要收窄到实际依赖。
第七步是检查呈现链路。present 相关耗时来自 swapchain image 获取、VSync、buffer count、窗口系统合成、GPU 队列背压和 CPU/GPU 帧延迟。若 GPU pass 总耗时低于预算,但应用仍然掉帧,呈现链路和帧 pacing 就进入分析范围。此时继续压缩 shader 成本的收益有限,应该观察 acquire、present、wait 和帧队列深度。
这个流程可以写成一套最小判断顺序。
这套流程的关键点是分界先于优化。CPU 高时,目标是降低命令构建、状态切换、资源绑定和驱动提交成本。GPU 高时,目标是定位具体 pass、draw、shader 和资源路径。present 高时,目标是检查 swapchain、VSync 和帧队列。每个分支都有不同的证据来源。
在城市广场这一帧中,假设 profiler 显示 CPU 5 ms、GPU 22 ms、present 1 ms。结论是当前帧主要受 GPU 限制。继续拆分后得到 shadow 3 ms、G-buffer 8 ms、lighting 5 ms、transparent 4 ms、post 2 ms。G-buffer 和 lighting 是优先对象。若把分辨率从 4K 降到 1080p 后 G-buffer 与 lighting 接近按像素数下降,就说明像素路径、render target 写入和纹理读取是主候选。若下降幅度小,说明顶点、固定开销、同步或非像素资源路径需要进一步检查。
再假设 transparent pass 在相机看向玻璃幕墙时从 1 ms 升到 4 ms。这个波动通常与 overdraw、深度排序、混合写入、早期深度测试失效和屏幕覆盖面积有关。排查时应先固定相机,再分别切换透明物体、混合状态、深度写入策略和渲染分辨率。若覆盖面积缩小后耗时下降明显,问题属于片元路径;若覆盖面积变化不大但 draw 数量上升导致 CPU 高,问题属于提交路径。
性能分析还需要保留视觉约束。降低 shadow map 尺寸能减少带宽和采样成本,但阴影边缘会变粗。减少 G-buffer 通道能降低写入成本,但会压缩材质表达。合并 pass 能减少中间纹理读写,但会增加 shader 复杂度或状态约束。调优结论必须同时记录性能收益、视觉影响和工程代价。
5.3 减少状态切换与 Draw Call 开销
Draw call 开销来自 CPU 侧命令构建、API 调用、驱动校验、pipeline 或 program 切换、descriptor 或资源绑定、常量更新和 GPU 侧状态生效。现代显式 API 把许多成本前移到 pipeline state object、descriptor set、root signature 或 argument buffer 的创建与组织阶段,但每帧仍然需要控制 draw 数量、状态切换顺序和资源绑定频率。
在城市广场这一帧里,草地、窗户、路灯、广告牌和重复建筑构件适合用 batching 或 instancing 处理。batching 的目标是把多个小网格或小材质组整理成较少 draw;instancing 的目标是用同一 mesh 和 material 绘制多个实例,并通过 instance buffer 提供每个实例的 transform、color、wind 参数或材质索引。Microsoft 的 Direct3D 文档在 system-generated values 中说明,InstanceID 由 Input Assembler 阶段生成,并可供后续 shader 使用;这说明实例编号是 shader 读取实例数据的基础入口。
减少 draw call 的第一类方法是 batching。静态场景可以离线合并 mesh,按材质和 lightmap 分组,生成更大的 vertex buffer 和 index buffer。动态场景可以使用动态 batching 或 GPU-driven compaction,把小对象整理成可批量提交的数据。batching 的收益来自减少 CPU 提交和状态切换,代价是裁剪粒度变粗、资源更新变重、内存布局更复杂。城市广场里的静态窗框、墙面装饰和路面小块适合离线 batching;移动角色、破碎物、需要独立剔除的对象更适合保持独立实例或分块。
第二类方法是 instancing。草地、树、路灯、窗户、重复建筑模块和粒子都适合 instancing。它保留 mesh 复用,把每个实例的差异放进 instance buffer、texture buffer 或 structured buffer。instancing 的收益来自减少 draw 次数和重复 vertex buffer 绑定,代价是实例数据读取增加、剔除策略需要配合、材质差异需要编码。若每个实例材质都不同、纹理绑定频繁变化,instancing 的收益会被资源绑定成本抵消。
第三类方法是 material sorting。渲染队列应按 pass、pipeline state、shader variant、material、resource set 和 mesh 组织,减少高成本状态切换。Opaque pass 通常适合按 pipeline 和 material 排序,再配合 front-to-back 降低 overdraw。Transparent pass 受混合和深度排序影响,通常需要按距离排序,因此它的状态切换控制空间较小。阴影 pass 可按 depth-only shader 和 mesh 组织,减少材质分支。
第四类方法是 descriptor strategy 或 bindless strategy。传统绑定方式会在 draw 之间频繁切换 texture、sampler、buffer 和 uniform。descriptor set、descriptor heap、argument buffer、bindless texture array 等策略把资源索引交给 shader 或较粗粒度的绑定表,从而减少每 draw 绑定动作。它的代价是资源表管理、平台 feature 差异、shader 索引安全、缓存局部性和调试复杂度。对材质数量大、纹理种类多的城市建筑场景,这类策略能降低 CPU 绑定成本,但需要配合材质排序和资源 residency 管理。
可以用下面这张表判断 draw call 优化方向。
| 优化方向 | 主要降低的成本 | 适用对象 | 主要代价 | 验证方法 |
|---|---|---|---|---|
| Static batching | CPU submit、state change | 静态小网格、同材质场景块 | 裁剪变粗、内存增加 | draw count 与 CPU time 下降 |
| Instancing | draw 数量、mesh 绑定 | 重复 mesh、大量实例 | 实例数据读取、材质编码 | draw count 下降且 GPU 未被实例读取拖慢 |
| Material sorting | pipeline switch、descriptor update | opaque pass、shadow pass | 排序成本、透明排序约束 | state switch 统计下降 |
| Multi-draw / indirect draw | CPU submit、GPU-driven 渲染入口 | 大量可剔除实例 | GPU 生成命令和同步边界 | CPU time 下降且 GPU queue 空洞减少 |
| Bindless / descriptor table | 资源绑定频率 | 大量材质和纹理 | feature 差异、资源表管理 | descriptor update 下降 |
状态切换优化需要关注 pipeline state 的组成。图形 pipeline 通常包含 shader、vertex layout、raster state、depth/stencil state、blend state、render target format、sample count 和部分动态状态。任何会改变 pipeline object 或 program 的操作,都可能比更新少量 uniform 成本更高。把材质参数放入 buffer 并复用同一 shader variant,通常比为每个小差异生成一个新 shader variant 更稳定。
Draw call 开销还会受 API 模型影响。OpenGL 这类隐式状态 API 中,驱动需要在调用序列中维护大量状态并延迟校验。Vulkan、Direct3D 12、Metal 这类显式 API 中,开发者提前创建 pipeline、明确资源状态和同步,CPU 提交路径更可控。显式 API 并不会自动让 draw 变便宜;它提供了把成本前移、批量化和多线程录制的空间。若应用仍然每帧频繁创建 pipeline、descriptor 或 buffer,显式 API 的低开销优势会被资源生命周期问题抵消。
在城市广场这一帧里,优化 draw call 的一条可执行路径如下:先统计每个 pass 的 draw 数量和 pipeline switch 数量;再把 opaque draw 按 pipeline 与 material 排序;然后把重复网格改成 instancing;接着把小静态件离线合并;最后把大量材质的 texture 绑定改成 descriptor table 或 bindless 索引。每一步都要记录 CPU frame time、GPU pass time、draw count、state switch 和视觉结果。若 CPU 时间下降但 GPU 时间上升,需要检查 batching 后裁剪粒度、实例数据读取、overdraw 和 cache 行为。
5.4 硬件特性对性能的影响与调优策略
硬件特性决定同一渲染策略在不同设备上的成本分布。tile-based、immediate-mode、unified memory、RT core、mesh shader 都会改变数据停留位置、提交方式、pass 组织、shader 结构和调试证据。调优时应先识别硬件与 API 能力,再选择策略。把桌面独显上的经验直接放到移动 GPU 或 Apple silicon 上,常会误判带宽、tile memory、统一内存和同步成本。
Tile-based renderer 会把屏幕划分为 tile,在片上内存中处理局部像素,再把最终结果写回外部内存。这个模式对带宽敏感应用有优势,因为中间颜色、深度和 stencil 数据可以在 tile 内复用。它也要求应用减少不必要的 render target store、跨 pass 读取和会破坏 tile locality 的操作。Vulkan Guide 的目录中有 Tile Based Rendering best practices 页面,Metal 生态也强调 Apple GPU 的 tile-based deferred rendering 特性。对这类设备,memoryless attachment、合理 load/store action、pass 合并和减少中间纹理写回,是优先观察方向。
Immediate-mode renderer 通常按 draw 顺序推进管线,把片元结果写向 render target 和外部显存层级。桌面独显常见的调优重点包括保持高 occupancy、减少 overdraw、控制 render target 带宽、使用压缩格式、提高 cache locality、减少 CPU 提交和利用异步队列。它对大 render target、全屏后处理和高采样纹理同样敏感,但 tile store/load 这类边界的权重较低。
Unified memory 改变 CPU 与 GPU 共享数据的方式。Apple silicon 和部分集成 GPU 让 CPU 与 GPU 访问同一物理内存池,减少显式拷贝路径,但内存带宽仍然是共享资源。统一内存下,大量 CPU 写入、GPU 读取、缓存同步和资源 hazard 仍会造成等待。对动态图形数据,策略应关注 buffer 环形分配、写入范围、同步边界、storage mode 或 resource option,以及 CPU 写入与 GPU 读取之间的帧延迟。
RT core 这类专用单元改变 ray tracing 的瓶颈结构。硬件加速可以降低 ray traversal 和 intersection 的成本,但整体帧时间还受 acceleration structure build/refit、ray generation shader、closest-hit shader、any-hit shader、材质访问、denoising、G-buffer 复用和内存带宽影响。对城市广场场景,开启反射 ray tracing 后,慢点可能在 BVH 更新、反射射线数量、透明材质 any-hit、降噪 pass 或历史缓存重投影上。调优顺序应先缩小 ray tracing 使用范围,再降低 ray 数量和 bounce,再观察 acceleration structure 与 denoising 成本。
Mesh shader 改变传统 vertex processing、primitive assembly 和部分 culling 的组织方式。它允许应用以 meshlet 或 task/mesh 形式组织几何,在 GPU 上完成更细粒度的剔除、LOD 和 primitive 生成。收益来自减少无效顶点工作、降低 CPU 组织压力、提高大规模几何的 GPU 驱动能力。代价是硬件覆盖范围、工具链支持、meshlet 构建、shader 复杂度和调试成本。对城市建筑和草地实例,mesh shader 适合海量小几何或 GPU culling 场景;对简单全屏后处理没有直接收益。
硬件特性需要和 API feature query 连接。实际工程中应在启动阶段查询 adapter、device、feature bits、limits、format support、descriptor indexing、ray tracing tier、mesh shader support、timestamp support 和 memory model。然后把渲染路径分成 baseline path 和 feature path。baseline path 保证视觉核心稳定,feature path 根据硬件能力打开更高性能或更高质量的实现。
下面的对照表把硬件特性和调优方向放到同一组维度里。
| 硬件或架构特性 | 影响的资源路径 | 优先调优方向 | 观察证据 |
|---|---|---|---|
| Tile-based rendering | tile memory、render target load/store | 合并 pass、减少 store、使用 memoryless attachment | render pass load/store、外部带宽、tile statistics |
| Immediate-mode rendering | 显存读写、ROP、cache | 控制 overdraw、压缩 RT、优化全屏 pass | bandwidth、ROP busy、pixel throughput |
| Unified memory | CPU/GPU 共享内存与同步 | ring buffer、帧延迟、写入范围控制 | CPU/GPU wait、resource hazard、upload timing |
| RT core | ray traversal、AS build、hit shader | 降低 ray 数量、限制材质路径、优化 denoise | RT pass timing、AS build timing、shader table |
| Mesh shader | 几何生成、剔除、primitive 输出 | meshlet、GPU culling、LOD | vertex workload、primitive count、mesh shader timing |
把这些特性落回城市广场这一帧,可以得到不同平台的策略。移动或 Apple GPU 上,先检查 G-buffer 的 render target 数量、store action、MSAA resolve、post-processing 中间纹理和 pass 边界。桌面独显上,先检查 overdraw、shader occupancy、纹理采样、RT 格式、descriptor 绑定和 draw 提交。开启 ray tracing 时,先把反射限定在主要材质和屏幕区域,再观察 acceleration structure 与 denoising。使用 mesh shader 时,先把场景切成 meshlet,再验证 GPU culling 是否真的减少顶点和 primitive 工作。
最终的调优判断应写成“现象 → 证据 → 根因候选 → 实验 → 取舍”。例如:G-buffer 在 4K 下耗时 8 ms,降到 1080p 后接近按像素数下降;normal RT 从 16-bit 改成 packed format 后耗时下降且视觉误差可接受;因此当前瓶颈主要来自 render target 带宽,调优方向是压缩 G-buffer、减少全分辨率写入和整理 pass store。这样的结论可以复查,也能迁移到其他 frame。
最小自检任务
给定一帧城市广场场景,目标 60 FPS。Profiler 数据如下:CPU frame time 为 6 ms,GPU frame time 为 24 ms,present 为 1 ms。GPU pass 拆分为 shadow 3 ms、G-buffer 9 ms、lighting 5 ms、transparent 5 ms、post-processing 2 ms。把分辨率从 4K 降到 1080p 后,G-buffer 变为 3 ms,lighting 变为 2 ms,transparent 变为 2 ms,shadow 基本不变。draw count 为 4800,其中草地实例占 1800 draw,材质切换频繁。
请判断这一帧的主要性能限制、优先排查顺序,以及三条可执行调优动作。答案需要说明 CPU/GPU 分界、pass 归因、带宽判断、draw call 策略和硬件边界。
答案要点
主要限制在 GPU 侧,因为 GPU frame time 24 ms 超过 16.67 ms 预算,CPU 6 ms 和 present 1 ms 暂时居次。pass 归因显示 G-buffer、lighting 和 transparent 是主要对象。分辨率下降后这三个 pass 明显变快,说明像素路径、render target 写入、纹理读取、透明 overdraw 和全屏或大面积片元工作是主候选;shadow 基本不变,说明 shadow 更可能受几何、draw 或深度写入路径影响。
优先排查顺序应为:先固定相机并记录基线;再进入 G-buffer,检查 render target 数量、格式、MSAA、材质纹理采样和 store action;然后进入 transparent pass,检查覆盖面积、排序、混合、深度策略和 overdraw;接着检查草地实例 1800 draw 是否可以改成 instancing、multi-draw 或 GPU culling;最后根据平台判断 tile-based 设备上的 render pass load/store 和 memoryless attachment,或桌面独显上的 ROP、带宽、texture cache 与 overdraw。
三条可执行调优动作可以是:第一,压缩或减少 G-buffer 写入,例如 packed normal、合并材质通道、降低全分辨率中间 RT 数量,并用视觉误差和 GPU timer 验证;第二,把草地从大量独立 draw 改成 instancing 或 indirect draw,并按材质排序,观察 draw count、CPU time 和 GPU pass time;第三,重做透明路径,把大面积玻璃和草地 alpha cutout 分开处理,控制 overdraw、深度预处理或分层渲染,并记录透明 pass 在固定相机下的耗时变化。
本章知识点总结
- 帧内归因:性能分析应先把一帧拆成 CPU、GPU 和 present,再进入 pass、draw、shader、资源和同步路径。
- 带宽约束:render target 写入、纹理采样、buffer 访问和 MSAA resolve 会共同形成内存系统压力。
- 执行瓶颈:复杂 shader、分支发散、顶点处理、片元 overdraw 和固定功能单元都会限制 GPU 执行吞吐。
- 资源竞争:barrier、fence、semaphore、queue wait 和资源状态转换会把正确性依赖转化为等待成本。
- 流程优先:CPU/GPU 分界、pass 定位、draw 定位、shader 与资源检查、带宽实验和同步检查构成稳定排查顺序。
- 像素证据:降低分辨率、减少 RT、降低采样数或关闭全屏 pass 后耗时同步下降,通常指向像素路径或带宽路径。
- Draw 成本:draw call 开销来自命令构建、状态校验、pipeline 切换、资源绑定和每帧常量更新。
- Batching 边界:batching 降低提交和状态切换成本,同时会带来裁剪粒度、内存布局和资源更新代价。
- Instancing 边界:instancing 适合重复 mesh 和大量实例,但需要控制实例数据读取、材质差异和剔除策略。
- 材质排序:opaque pass 通常按 pipeline 与 material 排序,transparent pass 还要服从距离、混合和深度约束。
- 绑定策略:descriptor table、argument buffer 和 bindless 索引能降低资源绑定频率,同时增加资源表管理和平台差异成本。
- Tile 特性:tile-based renderer 对 render pass load/store、中间纹理写回和 tile locality 更敏感。
- 统一内存:unified memory 减少显式拷贝路径,但 CPU/GPU 同步、缓存可见性和共享带宽仍需纳入判断。
- 专用单元:RT core 和 mesh shader 改变特定阶段的成本分布,调优仍需回到 AS build、hit shader、denoise、meshlet 和 GPU culling 证据。
- 调优结论:可复查的性能结论应包含现象、证据、根因候选、实验结果和视觉或工程取舍。