图形学知识经常被分成几门互不相干的课:线性代数、微积分、相机、抗锯齿、GPU 和性能分析。但在真实项目里,它们是一条连续的因果链:参数改变画面,采样把连续信号变成像素,GPU 执行这些工作,同步决定结果是否正确,性能门禁则判断下一次提交有没有破坏预算。
这条链对应站内的多元微积分、梯度与自动微分、相机、采样与重建以及GPU 执行模型、同步与性能门禁三页。
一、梯度是“参数改哪里”的语言
对标量函数,梯度给出局部上升最快的方向;对向量函数,雅可比描述输入变化如何影响多个输出;链式法则把这些局部关系沿计算图连接起来。图形学里,参数可以是相机、灯光、材质、几何或神经表示,输出可以是图像误差、深度误差或其他损失。
自动微分(Automatic Differentiation, AD)不是有限差分,也不是把每个公式都手推一遍。它沿程序的计算图应用链式法则:
- 前向模式同时传播值和导数,适合输入维度较小、输出较多的函数;
- 反向模式先记录中间状态,再从输出传播伴随量,适合参数很多、损失是标量的优化;
- 有限差分适合做黑盒校验,但步长过大会产生截断误差,过小会产生消减误差。
工程上最重要的不是“接上梯度”,而是明确哪些操作可微、哪些操作会破坏梯度,以及反向模式需要多少中间状态。碰撞、排序、硬可见性和离散状态通常需要平滑近似、分段处理或混合求解。
二、相机和采样决定你究竟在测量什么
常见的变换链可以写成:
模型、视图和投影矩阵的顺序只是起点。深度范围、坐标手性、NDC 约定、Y 方向和近远裁剪面必须与目标图形 API 对齐。相机的 FOV、纵横比、分辨率、抖动和动态缩放共同决定屏幕上实际采到的信号。
渲染器并不是把“连续画面”直接保存下来,而是在像素区域上进行有限采样和重建。信号频率超过采样频率,就会出现混叠;缩小纹理需要预过滤,空间采样可以使用多样本、抖动或分层策略,时间采样则依赖运动矢量和历史有效性。
因此,看到伪影时不要马上增加样本数:
- 远处纹理闪烁或出现摩尔纹,先检查高频是否被预过滤;
- 运动物体拖影或出现鬼影,检查历史拒绝、运动矢量、深度和曝光变化;
- 边缘锯齿,区分空间样本不足和重建滤波问题;
- 镜头切换或瞬移后异常,先清除不再对应当前相机的历史缓存。
滤波半径越大不一定越好:它可以减少闪烁,也可能让画面变糊、产生拖影或吞掉细节。时间问题还必须在运动、旋转和镜头切换中验收,不能只看静帧。
三、GPU 占用率不是性能答案
GPU 往往以线程组、wavefront 或 warp 为调度单位。寄存器压力、共享内存、分支发散、带宽、缓存命中和等待依赖都会影响并发执行。占用率高只说明有更多线程能够驻留,不代表关键 pass 已经更快;如果瓶颈在带宽、同步或固定功能阶段,继续提高占用率可能没有收益。
同步也不只是“加一个 barrier”。一次资源交接至少要说明:
- 哪个执行依赖必须先完成;
- 写入何时对后续读取可见;
- 资源当前处于什么状态或布局;
- 图形、计算和复制队列如何转移所有权。
D3D12 fence、Vulkan synchronization primitives 和引擎抽象的名字不同,但都应该服务于这些语义。过度同步会制造气泡,缺失同步则会产生非确定性画面、数据竞争或设备错误。性能优化前,先证明资源依赖正确,否则只是“更快地显示错误”。
四、把性能分析变成门禁
不要把完整 profiling 塞进每一次提交,也不要等到发布前才第一次测量。分层门禁更适合真实团队:
- 快速门禁:固定少量场景,检查包体、编译、冒烟和明显的帧时间回归;
- 夜间门禁:覆盖代表性设备和长时间运行,观察温控、泄漏、碎片化和长尾;
- 发布候选门禁:保存完整基线、原始采样、提交哈希、设备、驱动和配置,允许回到 RenderDoc、Nsight 或 PIX 做根因定位。
指标要先定义测量条件,再定义阈值。可以记录 P50/P95 帧时间、CPU/GPU 帧时间、峰值显存、加载时长、Shader 编译时间、包体和功耗;但只有固定场景、分辨率、画质、驱动、预热方式和采样窗口,它们才可比较。
对有噪声的指标,使用分位数、置信区间或连续多次触发,避免一次温度抖动阻断流水线。与此同时,不能用平均值掩盖 P95/P99 长尾,因为长尾更接近玩家在复杂场景中的体验。
五、把三层知识串成一次诊断
假设一次提交让动态镜头出现闪烁并让 GPU 时间上升,可以按下面顺序排查:
- 数学与参数层:相机矩阵、抖动序列、投影参数和历史坐标是否一致;
- 采样与重建层:高频信号是否预过滤,历史是否被错误复用,运动矢量是否覆盖实际变化;
- 执行与同步层:资源布局、队列依赖、带宽和同步气泡是否改变了关键 pass;
- 门禁与证据层:固定场景的 P95 帧时间、GPU/CPU 分解和原始采样是否能复现回归。
这比“换一个抗锯齿开关”或“把占用率调高”更稳健,因为每一步都对应一个可以验证的假设。