AMD FidelityFX™ Contrast Adaptive Sharpening (CAS)
AMD FidelityFX Contrast Adaptive Sharpening (CAS) 提供了混合能力,可以锐化并可选地缩放图像。

AMD FidelityFX 对比度自适应锐化 (CAS) 是 AMD 新推出的开源库,它通过极低的集成成本即可同时提高图像质量和性能。
CAS 提供两项主要功能:
CAS 的设计旨在将源代码集成到您的引擎中。因此,代码可在 GitHub 上通过 MIT 开源许可证获取。核心 CAS 功能完全包含在一个 C++ 和 HLSL/GLSL 着色器专用的头文件库中。
集成 CAS 的过程并不比在引擎中实现新的全屏着色器通道复杂。您的引擎通过函数调用级别与 CAS 交互。CAS 不会直接与任何着色器资源绑定点交互,而这通常是集成中间件时的常见阻碍。
由于没有需要初始化的外部库或子系统,因此无需创建或管理额外的 GPU 资源,也无需进行 CPU 端内存分配。CAS 也不需要您为其准备诸如运动矢量之类的资源。任何转换处理都发生在着色器内部。
CAS 最适合集成的具体点会因引擎而异。我建议在现代引擎的渲染管线中有一个通用点:在所有渲染和后期处理完成,处于线性空间后,应用 SDR/HDR 传输函数和 UI 渲染之前。这是 FidelityFX 的自然归宿,因为它在 **线性空间** 中运行并期望匹配的输入。
目前,CAS 需要一个计算着色器来促进一些优化。因此,我们将把线性输入纹理作为 SRV(着色器资源视图)进行读取,并写入 UAV(无序访问视图)。
此着色器需要几个简单的集成点:
CAS 头文件的设计旨在用于 C++ 或着色器代码。要在 HLSL 着色器中使用这些头文件,我们必须定义 `A_GPU` 和 `A_HLSL`。首先,我们 `#include "ffx_a.h"`,它在 CPU 和 GPU 之间提供了统一的类型和函数集。在定义了几个接口函数后,我们就可以包含主头文件 ffx_cas.h。
由于 CAS 不会假设或要求我们如何访问或存储数据,因此我们必须提供函数供其访问我们的数据。这些函数是 `CasLoad()` 和 `CasInput()`。
`CasLoad()` 加载指定 xy 位置的纹理单元。由于我们提供代码,因此我们可以保证它与我们的着色器绑定方案相符。命名方案、寄存器绑定点或绑定无绑定方式之间不会发生冲突。
Texture2D srvInputTexture;AF3 CasLoad( ASU2 p ){ return srvInputTexture.Load( int3( p, 0 ) ).rgb;}`CasInput()` 提供了一个执行任何颜色空间转换到线性空间的选项。由于我假设我们的输入处于管线的线性空间部分,因此 `CasInput()` 只是一个空函数。
void CasInput( inout AF1 r, inout AF1 g, inout AF1 b ) {}CAS 需要存储在 cbuffer 中的一些处理后的数据。由于 CAS 通过函数参数接受这些数据,因此我们可以将这些数据放置在单独的或合并的 cbuffer 中。数据只是 3 个 uint4。
cbuffer cb : register( b0 ){ uint4 const0; uint4 const1; uint4 const2;};CAS 采用了与典型的 8x8 或 8x4 像素线程数安排略有不同的计算着色器结构。CAS 的模板着色器通过混淆计算着色器线程索引,以实现更有效的像素着色器寻址模式。这种结构在宽度和高度上都进行了 2 倍展开,进一步提高了效率。尽管进行了循环展开,但仍然创建了足够的线程来使现代 GPU 保持满负荷运行,即使在 1080p 分辨率下也是如此。
CAS 的主要工作函数是 `CasFilter()`。此函数的最后两个参数决定了缩放和质量。如果我们为第一个参数传递 true,则仅锐化图像,而不调整大小。如果我们为第二个参数传递 true,我们将运行一个成本稍低的算法版本。为了达到最高效率,我建议将不同的函数变体编译掉。
`CasFilter( …, true, false )` – 仅锐化 `CasFilter( …, false, false )` – 高质量缩放 `CasFilter( …, false, true )` – 低质量缩放
RWTexture2D uavOutputTexture;[ numthreads( 64, 1, 1 ) ]void cs_cas_sharpen_only( uint3 LocalThreadId : SV_GroupThreadID, uint3 WorkGroupId : SV_GroupID ){ AU2 gxy = ARmp8x8( LocalThreadId.x ) + AU2( WorkGroupId.x << 4u, WorkGroupId.y << 4u );
AF3 c; CasFilter( c.r, c.g, c.b, gxy, const0, const1, true, false ); uavOutputTexture[ ASU2( gxy ) ] = AF4( c, 1 ); gxy.x += 8u;
CasFilter( c.r, c.g, c.b, gxy, const0, const1, true, false ); uavOutputTexture[ ASU2( gxy ) ] = AF4( c, 1 ); gxy.y += 8u;
CasFilter( c.r, c.g, c.b, gxy, const0, const1, true, false ); uavOutputTexture[ ASU2( gxy ) ] = AF4( c, 1 ); gxy.x -= 8u;
CasFilter( c.r, c.g, c.b, gxy, const0, const1, true, false ); uavOutputTexture[ ASU2( gxy ) ] = AF4( c, 1 );}尽管线程组维度不同寻常,但着色器仍然以 ((width + 15) / 16, (height + 15) / 16, 1) 进行调度。
显然,实现全屏着色器通道的细节大部分将取决于宿主引擎。CAS 在 CPU 端所需的唯一工作是填充 cbuffer。这就像调用 CAS 在 ffx_cas.h 中提供的函数一样简单。
#define A_CPU 1#include "../../../../shaders_2019/cas/ffx_a.h"#include "../../../../shaders_2019/cas/ffx_cas.h"
CasSetup( const0, const1, sharpness, AF1( inputWidth ), AF1( inputHeight ), AF1(outputWidth ), AF1(outputHeight) );实现缩放所需的工作量很小。如前所述,着色器仅需要正确的函数参数。宿主引擎负责提供适当大小的输入和输出纹理。CAS 支持高达 4 倍的面积缩放,但显然限制缩放比例会带来更高的图像质量。`CasSupportScaling()` 可用于检查配置是否受支持。
CAS 非常高效。它的成本通常为零点几毫秒,这对于现代 GPU 上的全屏操作来说是典型的成本。此外,CAS 的设计自然适合集成到其他通道中,从而最大限度地降低成本。
CAS 为《F1 2019》带来了图像质量的明显提升,并且考虑到其集成所需时间有限,我们认为它为该游戏增添了非常有用的功能。从下载到原型中所有功能正常工作,仅用了两天的工作量。
我们没有观察到图像质量上有任何明显的缺点。我们无法检测到任何通常与锐化滤镜相关的伪影。
以下是一些示例。可以使用滑块观察差异。左侧是没有应用 CAS 的效果,右侧是应用了 CAS 的效果。
注意:您可能需要调整窗口大小才能正确查看这些 100% 的截图。
AMD FidelityFX CAS 以极低的性能成本提供了非常有用的图像质量提升。该套件设计精良,易于集成,且集成所需的时间和精力极少。最后,集成没有任何技术或法律障碍——AMD FidelityFX v1.1.4 可在所有类型的现代 GPU 上运行,并采用 MIT 开源许可证。
AMD FidelityFX 可在 https://github.com/GPUOpen-Effects/FidelityFX 获取。