[前沿技术] AMD FSR 1.0源码分析(一)

FSR技术分析

1. SIGGRAPH课程分析

1.1 源码介绍

FSR源码核心是两个文件:

  • ffx_a.h:Portability header(可移植头文件)
  • ffx_fsr1.h:核心算法集合:
    • EASU:边缘自适应空间升频Edge Adaptive Spatial Upsampling
    • RCAS:鲁棒的对比度自适应锐化(Robust Contrast Adaptive Sharpening
    • LFGA:Linear Film Grain Applicator
    • SRTM:Simple Reversible Tonemapper
    • TEPD:Temporal Energy Preserving Dither

1.2 EASU简单介绍

1️⃣EASU最好的描述是:一个局部自适应的椭圆Lanczos式滤波器Lanczos是一种重采样算法,是一个sinc函数。这是一个理论上最佳的重建滤波器

EASU需要有良好的抗锯齿输入作为基础——它本身并不是一个抗锯齿的解决方案,因此它需要良好的抗锯齿来作为输入。

2️⃣EASU使用的是一个如下所示的**12-tap的窗口来进行空间升频**:

在这里插入图片描述

使用12 tap的好处之一,就是如果我们使用Float32,那么我们只需要32个寄存器来存储: 1 6 r e g i s t e r = 1 2 t a p ∗ 3 r g b 16_{register}=12_{tap}*3_{rgb} 16register=12tap3rgb。由后续算法可知, 窗口内的数据都要使用两次,与其每次都读取纹理,不如直接存储下来使用,这也是一种==以空间换取时间==了。

读取得到RGB数据,和很多DLAA算法类似,需要转换成luma,这里的转换算法非常简单:

float RGB2Luma(float3 rgb)
{
	return rgb.x + 2.0 * rgb.y + rgb.z;
}

对于这个**12-tap的窗口**,算法会进行四次+类型的分析,如下所示:
在这里插入图片描述

3️⃣每次+类型分析,其实就是边缘检测特征长度计算Feature length ),关于后者:EASU会忽略单像素特征,也就是完全翻转(例如:黑-白-黑,滤波器核变得对称无方向性),而关心部分翻转不翻转。如下图所示:

此外,EASU最好运行在感知空间(例如:sRGBGamma 2.0),线性空间虽然也可以,但效果会变差。

4️⃣正如之前所说,+分析之后,我们会得到两个结果:

  • direction:每个+类型分析的结果有三个类型:水平、垂直、对角线。我们要进行四次分析,对四次分析结果进行双线性插值,得到最终的方向。我们根据这个方向来旋转过滤核
  • length长度用于在XY轴上对旋转后的内核进行缩放

对于缩放,更加准确的算法解释是:

  • X轴:缩放区间是 [ 1 , 2 ] [1,\sqrt{2}] [1,2 ],对应的是从轴对齐对角线。这意味着:对角线情况下使用更大的内核,来避免带状伪影band)。
  • Y轴:缩放区间是 [ 1 , 2 ] [1,2] [1,2]​,对应的是从small featurelarge feature。这意味着:对小的特征使用无比例,这样就得到了一个小的对称核,它不会在特征本身之外采样。而当特征变大时,使用一个较长的核,这样我们可以更好地还原边缘

5️⃣正如一开始所说,算法使用的过滤核是lanczos核,但是原始内核的计算太过昂贵,所以EASU使用了多项式近似
[ 25 16 ( 2 5 x 2 − 1 ) 2 − ( 25 16 − 1 ) ] ( w x 2 − 1 ) 2 [\frac{25}{16}(\frac{2}{5}x^2-1)^2-(\frac{25}{16}-1)](wx^2-1)^2 [1625(52x21)2(16251)](wx21)2
其中,w可以看作是控制窗口的基数。以下图为例子:当 w = 1 / 4 w=1/4 w=1/4时,内核是宽的,范围是 [ − 2 , 2 ] [-2,2] [2,2];当 w = 1 / 2 w=1/2 w=1/2时,内核是窄的,范围是 [ − 2 , 2 ] [-\sqrt{2},\sqrt{2}] [2 ,2 ]

2. EASU源码分析

2.1 FsrEasuCon分析

根据官方信息,我们可以知道:在CPU端,我们需要调用此函数,来设置EASU算法所需的四个const vec4常量,我们接下来分析这些常量都填充了什么。

1️⃣首先是con0,它的第一个和第二个成员,填充的是输入/输出的分辨率比
c o n 0. x y = i n p u t V i e w p o r t I n P i x e l s o u t p u t S i z e I n P i x e l s con0.xy=\frac{inputViewportInPixels}{outputSizeInPixels} con0.xy=outputSizeInPixelsinputViewportInPixels
它的第三个和第四个成员,则是使用了类似 [ 0 , 1 ] → [ − 1 , 1 ] [0,1]\rightarrow [-1,1] [0,1][1,1] 的映射公式:
c o n 0. z w = 0.5 ∗ i n p u t V i e w p o r t I n P i x e l s o u t p u t S i z e I n P i x e l s − 0.5 con0.zw=0.5 *\frac{inputViewportInPixels}{outputSizeInPixels}-0.5 con0.zw=0.5outputSizeInPixelsinputViewportInPixels0.5
2️⃣在分析其他常量之前,我们需要参考如下图片:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bN7xETeC-1660286480418)(FSR技术分析.assets/image-20220321180118495.png)]

然后直接看看代码(分析也在代码处给了):

// Note : 
// ARcpF1(x) : 1/x
// AU1_AF1 : 打包函数
// AF1_ : 类型转换函数

// This is used to get upper-left of 'F' tap.
// 所以采样原点是`F`tap的左上方那个空白处
con1[0] = AU1_AF1(ARcpF1(inputSizeInPixelsX));
con1[1] = AU1_AF1(ARcpF1(inputSizeInPixelsY));

// Centers of gather4, first offset from upper-left of 'F'
// 根据后续代码可以知道,con1.zw是用来以`F`为原点,来定位`(0)`处
con1[2] = AU1_AF1(AF1_( 1.0) * ARcpF1(inputSizeInPixelsX));
con1[3] = AU1_AF1(AF1_(-1.0) * ARcpF1(inputSizeInPixelsY));

// These are from (0) instead of 'F'.
// 依据注释,以上四个偏移是以(0)为原点的
// 下面依次是 : (1) (2) (3) (0)的位置
con2[0] = AU1_AF1(AF1_(-1.0) * ARcpF1(inputSizeInPixelsX));
con2[1] = AU1_AF1(AF1_( 2.0) * ARcpF1(inputSizeInPixelsY));

con2[2] = AU1_AF1(AF1_( 1.0) * ARcpF1(inputSizeInPixelsX));
con2[3] = AU1_AF1(AF1_( 2.0) * ARcpF1(inputSizeInPixelsY));

con3[0] = AU1_AF1(AF1_( 0.0) * ARcpF1(inputSizeInPixelsX));
con3[1] = AU1_AF1(AF1_( 4.0) * ARcpF1(inputSizeInPixelsY));

con3[2] = con3[3] = 0;

ToDo:暂时先不管了,先来看之后的源码吧

2.2 FidelityFXSuperResolution分析

根据PostProcessFFX_FSR.usfMainPs函数,我们可以知道EASU算法的实现是在FidelityFXSuperResolution()中的,现在让我们来分析它。

AF4 FidelityFXSuperResolution(AU2 gxy)
{
	// FSR / EASU()
	AF3 Gamma2Color = AF3(0,0,0);
	FsrEasuF(Gamma2Color, gxy, Const0, Const1, Const2, Const3);
	
	AF3 OutColor = AF3(Gamma2Color);
	
	// Grain()
	// if RCAS & ChromAb are not running, we will apply Grain Intensity post-upscale here.
	// App should disable this path based on pass inputs on the CPU-side;
	#if USE_GRAIN_INTENSITY
		AF3 LinearColor = Gamma2ToLinear(AF3(Gamma2Color));
		ApplyUE4Grain(LinearColor, gxy, VPColor_ExtentInverse);
	#endif // USE_GRAIN_INTENSITY
	
	// 一些颜色空间的变换操作
    ...
    return AF4(OutColor, 1);
}

仔细一看,其实核心也是调用的函数:FsrEasuF。我们暂且不管ApplyUE4Grain,而直接去分析FsrEasuF

3. 之后

主要就是分析FsrEasuF,希望秋招一切顺利,然后有时间我会尽快更新之后的 [源码分析(二)][源码分析(三)]

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JMXIN422

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值