DLSS

1. DLSS 总览

由于NVIDIA的宣传问题,DLSS实际并不仅仅是狭义SS(super sampling)。它实际包含了以下四个方面:

技术主要解决的问题输入核心输出
DLSS Super Resolution分辨率不足、抗锯齿低分辨率画面、运动矢量、历史帧等更高分辨率画面
DLSS Ray Reconstruction光追样本太少、噪声严重稀疏光线样本、G-buffer、历史信息去噪并重建反射、阴影、GI
DLSS Frame Generation显示帧率不足前后帧、运动/光流信息额外的中间帧
DLSS 5传统实时着色难以达到电影级材质和光照效果游戏渲染的颜色帧、运动矢量重新增强光照、材质与角色外观
  • 1. DLSS Super Resolution

这项技术主要是用来和传统AA对比,如最广泛使用的TAA。实际上TAA是通过采样历史帧,来扩大采样减少锯齿。而DLSS这里用了一个Transformer模型,来预测模型的超分缺失信息(类似生图的套路,只是信息更全面)

  • 2. DLSS Ray Reconstruction

这一部分的应用场景是传统path tracing,而不是任意ray tracing。实际更像是一个高效的neural denoiser。当然,从AMD相关的技术进展来看,神经网络方法很有希望应用在radiance cache上,从而接近RTPT。

  • 3 DLSS Frame Generation

感觉上和超分差不多。DLSS 4.5宣称能够达到最高 render 1 gen 5,但从感受上,这个feature应该比超分更不适应高速运动场景,除非其在处理当前帧的时候,能够看到和TAA类似的信息(但这样输入就太多了吧,而且极度依赖定制化)。光流/运动信息是?

  • 4. DLSS 5

这个技术看着更抽象了,宣传上的说法类似,理解PBR材质,类似头发,布料,皮肤这些不好处理的部分,进行重光照。更像是生成模型的路径,也就是如果要实际应用的话,大概率需要对应的fine tune,不然相当于为美术风格各异的画面加上了一层一样的滤镜?在卡渲上更不现实。性能上,据说展示会上专门用一张5090来运行模型,显然距离生产应用还有距离。

2. DLSS 2 细节拆解

DLSS 2 内部仅提供一个超分的功能,因为有点老,所以仅用作技术参考。

DLSS 2 的本体是一个CNN,由5层encode和5层decode构成,参数总和约1M。

其中,接收信息的形式有点像TAA,dlss内部会维护一个历史帧,包含高分辨率的一张历史图像

生成新帧的方式:

DLSS 的 CNN 不直接输出最终 RGB。它输出三个各向异性高斯核形状参数 z0、z1、z2,五个下一帧隐藏状态参数,以及两个时空混合参数 z8、z9

  • z0、z1、z2:决定当前帧空间滤波核的宽度、形状和方向。
  • z8:控制当前帧颜色进入历史缓冲区的速度,即 Temporal 累计强度。
  • z9:控制空间滤波结果与时域累计结果之间的最终混合。

1. 将高分辨率输出像素映射到低分辨率图像

对于每一个高分辨率输出像素 p=(x,y),首先计算它在低分辨率输入图像中的连续亚像素位置:

q=(p+0.5)SinSout0.5+Jq=(p+0.5)\odot\frac{S_{\mathrm{in}}}{S_{\mathrm{out}}}-0.5+J

其中,J 是当前帧的 Jitter, 表示宽度和高度分别相乘。接着找到最近的低分辨率像素中心,并计算亚像素偏移:

n=round(q),δ=nqn=\operatorname{round}(q),\qquad \delta=n-q

例如,输入图像为 4×4、输出图像为 6×6,计算输出像素 p=(2,2),并假设 Jitter 为 0:

qx=qy=(2+0.5)×460.5=1.1667q_x=q_y=(2+0.5)\times\frac{4}{6}-0.5=1.1667
n=(1,1),δ=(0.1667,0.1667)n=(1,1),\qquad \delta=(-0.1667,-0.1667)

因此,该高分辨率输出像素对应低分辨率图像中的连续位置 (1.1667,1.1667),最近的低分辨率像素中心是 (1,1)

2. 决定使用 3×3 还是 5×5 邻域

3×3 或 5×5 不是 CNN 对每个像素单独选择的,而是在创建 DLSS Feature 时根据初始输入/输出比例全局确定:

rscale=WinputWoutputr_{\mathrm{scale}}=\frac{W_{\mathrm{input}}}{W_{\mathrm{output}}}
rscale<0.45×5,rscale0.43×3r_{\mathrm{scale}}<0.4\Rightarrow 5\times5,\qquad r_{\mathrm{scale}}\geq0.4\Rightarrow3\times3

当宽度比小于 0.4 时,输入分辨率很低,3×3 邻域能够提供的样本不足,因此使用 5×5 获取更大范围的信息。否则默认使用 3×3。

这项选择对整个 DLSS 实例统一生效。CNN 动态预测的是高斯核的形状和方向,而不是每个像素使用 3×3 还是 5×5。

3. 用 CNN 参数构造各向异性高斯核

CNN 输出的 z0、z1、z2 首先被转换为三个协方差参数:

a=(1.7σ(z0)+0.17)2a=\left(1.7\,\sigma(z_0)+0.17\right)^2
b=(1.7σ(z1)+0.17)2b=\left(1.7\,\sigma(z_1)+0.17\right)^2
c=ab0.95tanh(z2)c=\sqrt{ab}\cdot0.95\tanh(z_2)

其中,Sigmoid 函数为:

σ(z)=11+ez\sigma(z)=\frac{1}{1+e^{-z}}

然后构造二维协方差矩阵:

Σ=[accb]\Sigma=\begin{bmatrix}a&c\\c&b\end{bmatrix}

ab 控制高斯核在两个方向上的宽度,c 控制高斯核的旋转和方向相关性。

假设 CNN 为当前区域输出:

z0=z1=z2=0z_0=z_1=z_2=0

由于 sigmoid(0)=0.5tanh(0)=0,可得:

a=b=(1.7×0.5+0.17)2=1.0404,c=0a=b=(1.7\times0.5+0.17)^2=1.0404,\qquad c=0
Σ=[1.0404001.0404],Σ1=[0.96117000.96117]\Sigma=\begin{bmatrix}1.0404&0\\0&1.0404\end{bmatrix},\qquad \Sigma^{-1}=\begin{bmatrix}0.96117&0\\0&0.96117\end{bmatrix}

此时得到的是一个没有旋转、接近圆形的高斯核。如果 a≠b,高斯核会沿某一方向拉长;如果 c≠0,高斯核会发生旋转,从而沿着图像边缘方向进行滤波。

4. 计算 3×3 邻域的高斯权重

对低分辨率像素中心周围的每个邻域位置 (i,j),其中 3×3 模式下 i,j∈{-1,0,1},先计算考虑亚像素偏移后的距离:

dij=[i+δxj+δy]d_{ij}=\begin{bmatrix}i+\delta_x\\j+\delta_y\end{bmatrix}

然后计算未归一化高斯权重:

w~ij=exp(12dijTΣ1dij)\widetilde{w}_{ij}=\exp\left(-\frac{1}{2}d_{ij}^{T}\Sigma^{-1}d_{ij}\right)

再将所有邻域权重归一化:

wij=w~ijm=rrn=rrw~mnw_{ij}=\frac{\widetilde{w}_{ij}}{\displaystyle\sum_{m=-r}^{r}\sum_{n=-r}^{r}\widetilde{w}_{mn}}

将前面的 δ=(-0.1667,-0.1667) 和协方差矩阵代入后,得到以下 3×3 归一化权重矩阵:

W=[0.054700.103820.075360.103820.197050.143030.075360.143030.10382]W=\begin{bmatrix}0.05470&0.10382&0.07536\\0.10382&0.19705&0.14303\\0.07536&0.14303&0.10382\end{bmatrix}

因为目标亚像素位置位于中心像素的右下方,所以右侧和下侧的像素权重相对较大。

5. 计算当前帧的空间重建结果

假设低分辨率像素中心周围的 3×3 灰度值为:

C=[0.100.100.200.100.400.800.200.801.00]C=\begin{bmatrix}0.10&0.10&0.20\\0.10&0.40&0.80\\0.20&0.80&1.00\end{bmatrix}

使用高斯权重对邻域颜色加权求和:

Cfilter=i=rrj=rrwijC(nx+i,ny+j)C_{\mathrm{filter}}=\sum_{i=-r}^{r}\sum_{j=-r}^{r}w_{ij}\,C(n_x+i,n_y+j)

代入例子中的数值:

Cfilter=0.05470×0.10+0.10382×0.10+0.07536×0.20+0.10382×0.10+0.19705×0.40+0.14303×0.80+0.07536×0.20+0.14303×0.80+0.10382×1.000.46787\begin{aligned}C_{\mathrm{filter}}={}&0.05470\times0.10+0.10382\times0.10+0.07536\times0.20\\&+0.10382\times0.10+0.19705\times0.40+0.14303\times0.80\\&+0.07536\times0.20+0.14303\times0.80+0.10382\times1.00\\\approx{}&0.46787\end{aligned}

因此,该输出像素仅根据当前低分辨率图像得到的空间重建结果为 0.46787

真实图像是 RGB 图像时,同一组空间权重分别作用于三个颜色通道:

Rfilter=wijRij,Gfilter=wijGij,Bfilter=wijBijR_{\mathrm{filter}}=\sum w_{ij}R_{ij},\qquad G_{\mathrm{filter}}=\sum w_{ij}G_{ij},\qquad B_{\mathrm{filter}}=\sum w_{ij}B_{ij}

6. Temporal:将当前帧加入高分辨率历史

z8 控制当前低分辨率像素中心颜色进入历史缓冲区的速度。首先计算:

gj=σ(z8)g_j=\sigma(z_8)

实际的当前帧历史更新率为:

α=αlearnedWoutWinHoutHingj\alpha=\alpha_{\mathrm{learned}}\cdot\frac{W_{\mathrm{out}}}{W_{\mathrm{in}}}\cdot\frac{H_{\mathrm{out}}}{H_{\mathrm{in}}}\cdot g_j

其中,αlearned 是模型保存的基础历史融合系数。它可以理解为历史更新率,但不是训练神经网络时优化器使用的 learning rate。

继续使用前面的 4×4 → 6×6 例子。假设:

αlearned=0.035,z8=0,gj=σ(0)=0.5\alpha_{\mathrm{learned}}=0.035,\qquad z_8=0,\qquad g_j=\sigma(0)=0.5

则当前帧的历史更新率为:

α=0.035×1.5×1.5×0.5=0.039375\alpha=0.035\times1.5\times1.5\times0.5=0.039375

假设当前低分辨率像素中心颜色为:

Ccurrent=0.40C_{\mathrm{current}}=0.40

运动矢量对齐后的高分辨率历史颜色为:

Chistory=0.55C_{\mathrm{history}}=0.55

时域累计结果为:

Ctemporal=αCcurrent+(1α)ChistoryC_{\mathrm{temporal}}=\alpha C_{\mathrm{current}}+(1-\alpha)C_{\mathrm{history}}
Ctemporal=0.039375×0.40+0.960625×0.550.54409C_{\mathrm{temporal}}=0.039375\times0.40+0.960625\times0.55\approx0.54409

因此,这一帧只用约 3.94% 的比例更新历史,剩余约 96.06% 来自已经运动补偿的历史结果。这样可以稳定地积累不同帧 Jitter 带来的亚像素采样信息。

7. 历史帧是怎样逐帧累计的

历史更新是一个递归过程:

Ht=αCt+(1α)Ht1H_t=\alpha C_t+(1-\alpha)H_{t-1}

将上一帧历史继续展开:

Ht=αCt+α(1α)Ct1+α(1α)2Ct2+H_t=\alpha C_t+\alpha(1-\alpha)C_{t-1}+\alpha(1-\alpha)^2C_{t-2}+\cdots

因此,距离当前帧 k 帧的颜色贡献权重为:

wk=α(1α)kw_k=\alpha(1-\alpha)^k

α=0.039375 时:

w0=0.039375w_0=0.039375
w1=0.039375×0.9606250.03782w_1=0.039375\times0.960625\approx0.03782
w2=0.039375×0.96062520.03633w_2=0.039375\times0.960625^2\approx0.03633
w10=0.039375×0.960625100.02635w_{10}=0.039375\times0.960625^{10}\approx0.02635

虽然越早的单帧权重会逐渐衰减,但很多历史帧的贡献相加后仍然非常明显。最近 N 帧累计进入历史的总权重为:

AN=1(1α)NA_N=1-(1-\alpha)^N

代入 α=0.039375

A10=10.9606251033.1%A_{10}=1-0.960625^{10}\approx33.1\%
A30=10.9606253070.1%A_{30}=1-0.960625^{30}\approx70.1\%
A60=10.9606256091.0%A_{60}=1-0.960625^{60}\approx91.0\%

这体现了时域累计的作用:单帧只加入少量新信息,但经过几十帧不同 Jitter 位置的采样后,历史缓冲区可以逐渐积累更多亚像素信息。

当物体运动、发生反遮挡或历史颜色不再可信时,CNN 的门控以及运动矢量差异、颜色差异和深度信息会降低历史的可信度,使结果更偏向当前帧。

8. Spatial:混合空间滤波与时域累计结果

z9 决定空间滤波结果 Cfilter 与时域累计结果 Ctemporal 的最终混合比例。首先计算空间门控:

g=clamp(1.25(σ(z9)0.5)+0.5, gmin, 1)g=\operatorname{clamp}\left(1.25\left(\sigma(z_9)-0.5\right)+0.5,\ g_{\min},\ 1\right)

最终输出颜色为:

Cout=(1g)Ctemporal+gCfilterC_{\mathrm{out}}=(1-g)C_{\mathrm{temporal}}+gC_{\mathrm{filter}}

在当前例子中,假设 z9=0,则:

g=1.25(σ(0)0.5)+0.5=0.5g=1.25\left(\sigma(0)-0.5\right)+0.5=0.5

代入前面计算出的时域结果和空间滤波结果:

Cout=0.5×0.54409+0.5×0.467870.50598C_{\mathrm{out}}=0.5\times0.54409+0.5\times0.46787\approx0.50598

整个例子的关键数值如下:

  • 低分辨率中心颜色:0.40000
  • 神经空间滤波结果:0.46787
  • 运动补偿历史颜色:0.55000
  • 时域累计结果:0.54409
  • 最终输出颜色:0.50598

z9 越大,最终结果越相信当前帧的空间滤波重建;z9 越小,最终结果越相信经过运动补偿的多帧历史。

总结:DLSS 的 CNN 不直接生成最终 RGB,而是预测空间滤波核的形状、方向和时域融合门控。GPU 针对每个高分辨率输出像素,从低分辨率当前帧的邻域中进行动态高斯重建,再与运动补偿后的高分辨率历史融合。历史结果通过递归更新逐帧积累不同 Jitter 位置提供的亚像素信息,最终生成稳定的高分辨率图像。

“`

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇