跳至内容

FidelityFX Super Resolution 2.3.3 (FSR2)

Screenshot

AMD FidelityFX Super Resolution 2 (FSR2) 是一款开源的高质量解决方案,用于从低分辨率输入生成高分辨率帧。

目录

引言

FidelityFX Super Resolution 2(简称 **FSR2**)是一种先进的 upscale 技术,从头开始开发,用于从低分辨率输入生成高分辨率帧。

invert

FSR2 利用时间反馈来重建高分辨率图像,同时保持甚至改善与原生渲染相比的图像质量。

FSR2 可以为耗时的渲染操作(如硬件光线追踪)实现“实际性能”。

着色语言要求

  • HLSL
    • CS_6_2
    • CS_6_6†

† 在某些支持 64 位宽波前的硬件上使用 CS_6_6

快速入门清单

要使用 FSR2,您应该遵循以下步骤:

  1. 生成 Visual Studio 解决方案

    终端窗口
    > <installation path>\BuildSamplesSolution.bat

    批处理文件将询问是否应将解决方案构建为 DLL(如果不提供‘n’,则会作为静态链接库构建)以及应包含哪些示例。请使用‘1’来构建包含所有示例的解决方案,或使用‘8’仅包含 FSR 示例。

    这将生成一个 build\ 目录,您将在其中找到 SDK 示例的解决方案(FidelityFX SDK Samples.sln)。

  2. 打开解决方案并进行构建。

  3. 将 API 库 ffx_fsr2_x64.libbin/ffx_sdk 复制到包含您项目中包含第三方库的文件夹的文件夹中。

  4. 复制与您要使用的 FFX 后端匹配的库,例如:DirectX 12 使用 bin/ffx_sdk/ffx_backend_dx12_x64.lib

  5. 将以下核心 API 头文件从 src/ffx-fsr2-api 复制到您的项目中:ffx_fsr2.hffx_types.hffx_error.hffx_interface.hffx_util.hshaders/ffx_fsr2_common.hshaders/ffx_fsr2_resources.h。复制文件时应注意保持目标目录中相对的目录结构。

  6. 复制您选择的 API 后端的头文件,例如 DirectX 12,您将复制 dx12/ffx_fsr2_dx12.hdx12/shaders/ffx_fsr2_shaders_dx12.h。复制文件时应注意保持目标目录中相对的目录结构。

  7. 在您希望与 FSR2 交互的代码库中包含 ffx_fsr2.h 头文件。

  8. 为您的目标 API 创建一个后端。例如,对于 DirectX 12,您应该调用 ffxGetInterfaceDX12。应该分配一个大小等于调用 ffxGetScratchMemorySizeDX12 返回的大小的一个临时缓冲区,并将该缓冲区的指针传递给 ffxGetInterfaceDX12

  9. 通过调用 ffxFsr2ContextCreate 来创建 FSR2 上下文。参数结构应根据您的应用程序的配置进行填写。有关更多详细信息,请参阅 API 参考文档。

  10. 每一帧您都应该调用 ffxFsr2ContextDispatch 来启动 FSR2 工作负载。参数结构应根据您的应用程序的配置进行填写。有关更多详细信息,请参阅 API 参考文档,并确保 frameTimeDelta 字段以毫秒为单位提供

  11. 当您的应用程序终止时(或您因其他原因需要销毁上下文时),您应该调用 ffxFsr2ContextDestroy。在调用此函数之前,GPU 应该处于空闲状态。

  12. 应将亚像素抖动应用于您的应用程序的投影矩阵。这应该在您的应用程序进行主渲染时完成。您应该使用 ffxFsr2GetJitterOffset 函数来计算精确的抖动偏移。有关更多详细信息,请参阅 相机抖动 部分。

  13. 为获得最佳 upscale 质量,强烈建议您根据我们的指南填写 反应性蒙版透明度与组合蒙版。您也可以使用 ffxFsr2ContextGenerateReactiveMask 作为起点。

  14. 应用程序应在其用户界面中按以下顺序公开 缩放模式:质量、平衡、性能,以及(可选)超高性能。

  15. 应用程序还应公开一个锐化滑块,允许最终用户获得额外的质量。

集成指南

缩放模式

为了方便最终用户,FSR2 API 提供了一些命名预设的缩放比例。

画质每维缩放因子
画质1.5x
平衡1.7x
性能2.0x
超高性能3.0x

我们强烈建议应用程序在其用户界面中采用一致的命名和缩放比例。这样可以确保您的应用程序用户的体验一致,他们可能已经体验过使用 FSR2 的其他应用程序。

性能

根据您的目标硬件和操作系统配置,FSR2 将以不同的性能级别运行。

下表总结了 FSR2 在各种硬件上的 DX12 性能测量结果。

目标分辨率画质RX 7900 XTXRX 6950 XTRX 6900 XTRX 6800 XTRX 6800RX 6700 XTRX 6650 XTRX 5700 XTRX Vega 56RX 590
3840x2160质量 (1.5x)0.7 毫秒1.1 毫秒1.2 毫秒1.2 毫秒1.4 毫秒2.0 毫秒2.8 毫秒2.4 毫秒4.9 毫秒5.4 毫秒
平衡 (1.7x)0.6 毫秒1.0 毫秒1.0 毫秒1.1 毫秒1.4 毫秒1.8 毫秒2.6 毫秒2.2 毫秒4.1 毫秒4.9 毫秒
性能 (2x)0.6 毫秒0.9 毫秒1.0 毫秒1.0 毫秒1.3 毫秒1.7 毫秒2.3 毫秒2.0 毫秒3.6 毫秒4.4 毫秒
超高性能 (3x)0.5 毫秒0.8 毫秒0.8 毫秒0.9 毫秒1.1 毫秒1.5 毫秒1.8 毫秒1.7 毫秒2.9 毫秒3.7 毫秒
2560x1440质量 (1.5x)0.3 毫秒0.5 毫秒0.5 毫秒0.5 毫秒0.7 毫秒0.9 毫秒1.2 毫秒1.1 毫秒1.9 毫秒2.3 毫秒
平衡 (1.7x)0.3 毫秒0.5 毫秒0.5 毫秒0.5 毫秒0.6 毫秒0.8 毫秒1.1 毫秒1.0 毫秒1.7 毫秒2.1 毫秒
性能 (2x)0.3 毫秒0.4 毫秒0.4 毫秒0.4 毫秒0.6 毫秒0.8 毫秒0.9 毫秒0.9 毫秒1.5 毫秒1.9 毫秒
超高性能 (3x)0.2 毫秒0.4 毫秒0.4 毫秒0.4 毫秒0.5 毫秒0.7 毫秒0.8 毫秒0.8 毫秒1.2 毫秒1.7 毫秒
1920x1080质量 (1.5x)0.2 毫秒0.3 毫秒0.3 毫秒0.3 毫秒0.4 毫秒0.5 毫秒0.6 毫秒0.6 毫秒1.0 毫秒1.3 毫秒
平衡 (1.7x)0.2 毫秒0.3 毫秒0.3 毫秒0.3 毫秒0.4 毫秒0.5 毫秒0.6 毫秒0.6 毫秒0.9 毫秒1.2 毫秒
性能 (2x)0.2 毫秒0.2 毫秒0.2 毫秒0.3 毫秒0.3 毫秒0.5 毫秒0.5 毫秒0.5 毫秒0.8 毫秒1.1 毫秒
超高性能 (3x)0.1 毫秒0.2 毫秒0.2 毫秒0.2 毫秒0.3 毫秒0.4 毫秒0.4 毫秒0.4 毫秒0.7 毫秒0.9 毫秒

数字四舍五入到最接近的 0.1 毫秒,并且不包含额外的 sharpness,并且可能会发生变化。

内存要求

使用 FSR2 需要分配一些额外的 GPU 本地内存供 GPU 使用。在使用 FSR2 API 时,此内存会在创建 FSR2 上下文时分配,并且通过构成后端接口的回调系列进行分配。此内存用于存储 FSR2 算法计算的中间表面以及应用程序许多帧之间持久的表面。下表包括 FSR2 在各种操作条件下的内存使用量。“工作集”列表示 FSR2 在 GPU 上执行时使用的内存总量;这是 FSR2 运行所需的内存量。“持久内存”列表示“工作集”列中有多少内存需要为应用程序的后续帧保持不变;此内存存储 FSR2 使用的时间数据。“可别名内存”列表示“工作集”列中有多少内存可以被 FSR2 操作边界之外的应用程序使用的表面或其他资源别名。

通过覆盖 FSR2 后端接口的资源创建和销毁部分,并转发别名标志,您可以控制 FSR2 中的资源创建。这意味着,为了完美集成 FSR2,根据您的操作条件,需要额外的内存,其大小等于下表中“持久内存”列的值。

分辨率画质工作集 (MB)持久内存 (MB)可别名内存 (MB)
3840x2160质量 (1.5x)448MB354MB93MB
平衡 (1.7x)407MB330MB77MB
性能 (2x)376MB312MB63MB
超高性能 (3x)323MB281MB42MB
2560x1440质量 (1.5x)207MB164MB43MB
平衡 (1.7x)189MB153MB36MB
性能 (2x)172MB143MB29MB
超高性能 (3x)149MB130MB19MB
1920x1080质量 (1.5x)115MB90MB24MB
平衡 (1.7x)105MB85MB20MB
性能 (2x)101MB83MB18MB
超高性能 (3x)84MB72MB11MB

使用 RX 6700XT GPU 和 DX12,数据为近似值,向上取整到最接近的 MB,并且可能会发生变化。

有关如何管理 FSR2 内存需求的详细信息,请参阅本文档中有关 内存管理 的部分。

输入资源

FSR2 是一个时间算法,因此需要访问当前帧和上一帧的数据。下表列出了 FSR2 所需的所有外部输入。

分辨率列表示数据应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序执行渲染的分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。所有资源均来自当前渲染的帧,对于 DirectX(R)12 和 Vulkan(R) 应用程序,在调用 ffxFsr2ContextDispatch 之前,所有输入资源应分别转换为 D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCEVK_ACCESS_SHADER_READ_BIT

名称分辨率格式类型说明
颜色缓冲区渲染应用程序指定纹理应用程序提供的当前帧的渲染分辨率颜色缓冲区。如果颜色缓冲区的内容是高动态范围 (HDR),则应在创建 FfxFsr2ContextDescription 结构体的 flags 字段中设置 FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE 标志。
深度缓冲区渲染应用程序指定 (1x FLOAT)纹理应用程序提供的当前帧的渲染分辨率深度缓冲区。数据应作为单个浮点值提供,其精度由应用程序控制。创建 FfxFsr2Context 时,深度配置应通过 flags 字段通知 FSR2。如果您的深度缓冲区是反转的(即 [1..0] 范围),则应设置 FFX_FSR2_ENABLE_DEPTH_INVERTED 标志,如果您的深度缓冲区具有无限远平面,则应设置 FFX_FSR2_ENABLE_DEPTH_INFINITE 标志。如果应用程序提供 D32S8 格式的深度缓冲区,则 FSR2 将忽略缓冲区的模板分量,并创建一个 R32_FLOAT 资源来处理深度缓冲区。在 GCN 和 RDNA 硬件上,深度缓冲区与模板缓冲区分开存储。
运动矢量渲染或呈现应用程序指定 (2x FLOAT)纹理应用程序在 **[<-width, -height> … <width, height>]** 范围内提供的当前帧的 2D 运动矢量。如果您的应用程序以不同的范围渲染运动矢量,您可以使用 FfxFsr2DispatchDescription 结构体的 motionVectorScale 字段来调整它们以匹配 FSR2 的预期范围。在内部,FSR2 在许多情况下使用 16 位量来表示运动矢量,这意味着虽然可以提供更高精度的运动矢量,但 FSR2 将无法从中受益。运动矢量缓冲区的分辨率应等于渲染分辨率,除非在创建 FfxFsr2Context 时在 flags 字段中设置了 FFX_FSR2_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS 标志,在这种情况下,它应等于显示分辨率。
反应式遮罩渲染R8_UNORM纹理由于渲染图像的某些区域在深度缓冲区中不留下足迹或不包含运动矢量,FSR2 支持反应性蒙版纹理,可用于向 FSR2 指示这些区域的位置。这些区域的好例子是粒子或未写入深度或运动矢量的 alpha 混合对象。如果未设置此资源,则 FSR2 的着色变化检测逻辑将尽力处理这些情况,但为了获得最佳结果,应设置此资源。有关反应性蒙版的更多信息,请参阅 反应性蒙版 部分。
曝光1x1R32_FLOAT纹理一个 1x1 纹理,包含为当前帧计算的曝光值。此资源是可选的,如果创建 FfxFsr2Context 时在 flags 字段中设置了 FFX_FSR2_ENABLE_AUTO_EXPOSURE 标志,则可以省略它。

所有在渲染分辨率下提供的输入(运动矢量除外)都应使用抖动进行渲染。运动矢量不应应用抖动,除非存在 FFX_FSR2_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION 标志。

深度缓冲区配置

强烈建议使用反转的、无限的深度缓冲区与 FSR2 结合使用。但是,也支持其他深度缓冲区配置。应用程序应通过在创建 FfxFsr2Context 时设置相应的标志来通知 FSR2 API 其深度缓冲区配置。下表包含相应的标志。

FSR2 标志说明
FFX_FSR2_ENABLE_DEPTH_INVERTED一个位,指示提供的输入深度缓冲区数据是反转的 [max..0]。
FFX_FSR2_ENABLE_DEPTH_INFINITE一个位,指示提供的输入深度缓冲区数据使用的是无限远平面。

提供运动矢量

空间

时间算法(无论是抗锯齿还是 upscale)的关键部分是提供运动矢量。FSR2 接受 2D 运动矢量,这些运动矢量编码了当前帧像素到上一帧相同像素位置的运动。FSR2 期望应用程序提供的运动矢量范围为 [**<-width, -height>**..**<width, height>**];这与屏幕空间匹配。例如,屏幕左上角像素的运动矢量值 <width, height> 将表示一个运动,该运动遍历了输入表面的完整宽度和高度,起源于右下角。

invert

如果您的应用程序在其他空间(例如归一化设备坐标空间)计算运动矢量,那么您可以使用 FfxFsr2DispatchDescription 结构体的 motionVectorScale 字段来指示 FSR2 将其调整为匹配 FSR2 的预期范围。下面的代码示例说明了如何将运动矢量缩放到屏幕空间。下面的 HLSL 和 C++ 代码示例说明了如何使用 FSR2 主机 API 将 NDC 空间运动矢量进行缩放。

// GPU: Example of application NDC motion vector computation
float2 motionVector = (previousPosition.xy / previousPosition.w) - (currentPosition.xy / currentPosition.w);
// CPU: Matching FSR 2.0 motionVectorScale configuration
dispatchParameters.motionVectorScale.x = (float)renderWidth;
dispatchParameters.motionVectorScale.y = (float)renderHeight;

精度和分辨率

在内部,FSR2 在许多情况下使用 16 位量来表示运动矢量,这意味着虽然可以提供更高精度的运动矢量,但 FSR2 目前将无法从中受益。运动矢量缓冲区的分辨率应等于渲染分辨率,除非在创建 FfxFsr2Context 时在 flags 字段中设置了 FFX_FSR2_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS 标志,在这种情况下,它应等于显示分辨率。

覆盖率

当更多对象提供其运动矢量时,FSR2 的 upscale 质量会更好。因此,建议所有不透明、alpha 测试和 alpha 混合对象都应为其所有覆盖的像素写入运动矢量。如果应用了顶点着色器效果(如滚动 UV),这些计算也应纳入运动计算中以获得最佳结果。对于 alpha 混合对象,还强烈建议将每个覆盖像素的 alpha 值存储到反应性蒙版中对应的像素。这将使 FSR2 在 upscale 过程中更好地处理 alpha 混合对象。反应性蒙版对于写入运动矢量可能很困难的 alpha 混合对象(例如粒子)尤其重要。

反应式遮罩

在 FSR2 的上下文中,“反应性”是指当前帧渲染的样本对最终 upscale 图像的产生有多大影响。通常,当前帧渲染的样本对 FSR2 计算的结果贡献相对较小;但是,也有例外。为了对快速移动的 alpha 混合对象产生最佳效果,FSR2 需要为这些像素使“重投影与累积”阶段更加具有反应性。由于无法从颜色、深度或运动矢量中很好地确定哪些像素是使用 alpha 混合渲染的,因此当应用程序明确标记这些区域时,FSR2 的效果最好。

因此,强烈建议应用程序为 FSR2 提供反应性蒙版。反应性蒙版指导 FSR2 在何时应减少对历史信息的依赖来合成当前像素,而应让当前帧的样本更多地贡献给最终结果。反应性蒙版允许应用程序提供一个 [0.0..1.0] 范围内的值,其中 0.0 表示像素根本不具有反应性(应使用默认的 FSR2 组合策略),而 1.0 表示像素应具有完全反应性。这是一个浮点范围,可以根据不同情况进行调整。

虽然反应式遮罩还有其他应用,但其主要应用是改善包含 Alpha 混合对象的图像放大结果。Alpha 混合对象组合到场景中的 Alpha 值实际上是反应性的良好代理,因此,应用程序应将 alpha 写入反应式遮罩。需要注意的是,反应性值接近 1 可能不太可能产生好的结果。因此,我们建议将最大反应性值钳制在 0.9 左右。

如果未向 FSR2 提供 反应性蒙版(通过将 FfxFsr2DispatchDescriptionreactive 字段设置为 NULL),则将使用一个带有已清除反应性值的内部生成的 1x1 纹理。

自动生成反应性

为了帮助应用程序生成 反应性蒙版透明度与组合蒙版,FSR2 提供了一个可选的辅助 API。该 API 在后台启动一个计算着色器,该着色器使用基于亮度的启发式方法为每个像素计算这些值。

希望执行此操作的应用程序可以调用 ffxFsr2ContextGenerateReactiveMask 函数,并应传递颜色缓冲区的两个版本:一个版本包含仅不透明几何体,另一个版本包含不透明和 alpha 混合对象。

透明度和合成遮罩

除了 反应性蒙版 之外,FSR2 还允许应用程序标记应该在 upscale 过程中考虑的其他专业渲染区域。这类特殊渲染的例子包括光线追踪反射区域或动画纹理。

虽然 反应性蒙版 调整累积平衡,但 透明度与组合蒙版 调整像素历史保护机制。该蒙版还会消除亮度不稳定性因子的影响。在 透明度与组合蒙版 中值为 0 的像素不会对该像素的锁定进行任何额外修改。相反,值为 1 表示该像素的锁定应完全移除。

如果未向 FSR2 提供 透明度与组合蒙版(通过将 FfxFsr2DispatchDescriptiontransparencyAndComposition 字段设置为 NULL),则将使用一个带有已清除透明度和组合值的内部生成的 1x1 纹理。

自动生成透明度和组合蒙版

FSR2.2 包含一个实验性功能,用于自动生成 反应性蒙版透明度与组合蒙版。要启用此功能,需要将 FfxFsr2DispatchDescriptionenableAutoReactive 字段设置为‘TRUE’,并在 ‘colorOpaqueOnly’ 中提供不透明几何体部分的 الخلفية 副本。然后,FSR2 将在内部自动生成并使用 反应性蒙版透明度与组合蒙版。通过分析不带透明几何体和带透明几何体的颜色缓冲区的差异,以及将其与上一帧进行比较,在计算通道中生成蒙版。基于这些计算结果,每个像素将被分配 反应性蒙版透明度与组合蒙版 值。要使用蒙版的自动生成,还需要提供以下 4 个用于缩放和限制蒙版强度的值(注意,提到的默认值是建议的起始值,但应根据具体游戏进行调整):

  • ‘autoTcThreshold’:将此值设置得太小会导致视觉不稳定。较大的值可能导致拖影。建议的默认值为 0.05f。
  • ‘autoTcScale’:较小的值可以提高半透明物体硬边缘的稳定性。建议的默认值为 1.0f。
  • ‘autoReactiveScale’:较大的值会增加像素的反应性。建议的默认值为 5.00f。
  • ‘autoReactiveMax’:反应性可以达到的最大值。建议的默认值为 0.90f。

此功能旨在帮助将 FSR2.2 集成到新的引擎或游戏中。但是,为了获得最佳质量,我们仍然建议您自己渲染 反应性蒙版透明度与组合蒙版,因为从最终图像自动生成这些值比基于材质生成它们更不可靠。

请注意,此功能仍处于实验阶段,未来可能会发生重大变化。

曝光

FSR2 提供了两个控制 upscale 过程中使用的曝光值的参数。它们如下:

  1. 预曝光:一个值,我们将输入信号除以它,以恢复游戏在打包到低精度渲染目标之前生成的原始信号。
  2. 曝光:一个值,它乘以预曝光颜色值的计算结果。

曝光值应与应用程序在后续色调映射传递中使用的值相匹配。这意味着 FSR2 的运行将与最终色调映射图像中可能显示的内容一致。

在本文档所述的 FSR2 算法的各个阶段,FSR2 会计算其内部使用的曝光值。值得注意的是,FSR2 的所有输出在写入最终输出之前都会反转其内部色调映射。这意味着 FSR2 返回的结果与原始输入信号的域相同。

选择不当的曝光值会对 FSR2 放大输出的最终质量产生巨大影响。因此,除非有特殊原因,否则建议应用程序使用 FFX_FSR2_ENABLE_AUTO_EXPOSURE。当在 FfxFsr2ContextDescription 结构体的 flags 字段中设置 FFX_FSR2_ENABLE_AUTO_EXPOSURE 时,将使用下面 HLSL 代码中显示的曝光计算来计算曝光值,该值与 ISO 100 胶片曝光响应匹配。

float ComputeAutoExposureFromAverageLog(float averageLogLuminance)
{
const float averageLuminance = exp(averageLogLuminance);
const float S = 100.0f; // ISO arithmetic speed
const float K = 12.5f;
const float exposureIso100 = log2((averageLuminance * S) / K);
const float q = 0.65f;
const float luminanceMax = (78.0f / (q * S)) * pow(2.0f, exposureIso100);
return 1 / luminanceMax;
}

在帧中的位置

FSR2 的主要目标是通过使用依赖于多种输入的时域放大算法来提高应用程序的渲染性能。因此,其在渲染管线中的位置对于确保最高视觉质量和出色性能之间的平衡至关重要。

invert

对于任何图像放大方法,了解如何将其他图像空间算法与放大算法进行放置都很重要。将这些其他图像空间效果放在放大算法之前,优点是它们在较低的分辨率下运行,这当然为应用程序带来了性能优势。但是,这可能不适用于某些类别的图像空间技术。例如,许多应用程序可能会在最终图像中引入噪点或颗粒,可能用于模拟物理相机。在放大器之前这样做可能会导致放大器放大噪点,从而在放大的图像中产生不良伪影。下表将常见的实时图像空间技术分为两列。“后期处理 A”包含所有通常在 FSR2 放大之前运行的技术,这意味着它们都将在渲染分辨率下运行。相反,“后期处理 B”列包含所有建议在 FSR2 之后运行的技术,这意味着它们将在较大的显示分辨率下运行。

后期处理 A后期处理 B
屏幕空间反射胶片颗粒
屏幕空间环境光遮蔽色差
去噪器(阴影、反射)晕影
曝光(可选)色调映射
光晕
景深
动态模糊

请注意,此处提出的建议仅供参考,具体取决于你的应用程序实现的具体特性。

主机 API

虽然可以生成适当的中间资源、编译着色器代码、设置绑定并提交调度,但使用提供的 FSR2 主机 API 要容易得多。

要使用 API,您应该链接 FSR2 库(稍后将详细介绍),并包含 ffx_fsr2.h 头文件,该文件又具有以下头文件依赖项。

ffx_assert.h
ffx_error.h
ffx_fsr2_interface.h
ffx_types.h
ffx_util.h

要使用 FSR2 API,您应该链接 ffx_fsr2_api_x64.lib,它将提供面向应用程序的 API 的符号。但是,FSR2 的 API 具有模块化后端,这意味着可以使用匹配的后端来针对不同的图形 API 和平台。因此,您应该进一步包含符合您要求的后端库,并参考下表。

目标库名
DirectX(R)12ffx_fsr2_dx12_x64.lib
Vulkan(R)ffx_fsr2_vk_x64.lib

请注意,FSR2 API 的模块化架构允许实现自定义后端。有关更多详细信息,请参阅模块化后端部分。

要开始使用 API,应用程序应首先创建一个 FfxFsr2Context 结构。此结构应位于生命周期与后备缓冲区大致匹配的位置;通常将其放在应用程序的堆上是一个不错的选择。通过调用 ffxFsr2ContextCreateFfxFsr2Context 结构将填充所需的数据。此外,ffxFsr2ContextCreate 将从作为 FfxFsr2ContextDescription 结构一部分提供的后端进行多次调用。这些调用将执行创建 FSR2 所需的中间资源以及设置着色器及其关联的管道状态等任务。FSR2 API 不执行任何动态内存分配。

在应用程序的每个需要放大的帧中,您都应该调用 ffxFsr2ContextDispatch。此函数接受在应用程序生命周期早期创建的 FfxFsr2Context 结构,以及一个描述放大应如何执行以及对哪些数据的精确说明。此说明通过应用程序填充 FfxFsr2DispatchDescription 结构来提供。

通过调用 ffxFsr2ContextDestroy 来销毁上下文。请注意,在尝试调用 ffxFsr2ContextDestroy 之前,GPU 应该处于空闲状态,并且该函数不执行隐式同步以确保 FSR2 正在访问的资源当前未处于飞行状态。选择此项的原因是为了避免 FSR2 为那些已经在可能希望销毁 FfxFsr2Context 的点执行了足够同步的应用程序引入额外的 GPU 刷新,这允许应用程序在需要时以最高效率创建和拆除 FSR2 API。

FSR2 API 提供了一些额外的辅助函数。这些辅助函数执行诸如计算亚像素抖动偏移以及基于调度分辨率和 FSR2 提供的默认 缩放模式计算渲染分辨率等任务。

有关 FSR2 API 的更详尽文档,您可以参考提供的 API 参考文档。

模块化后端

FSR2 API 的设计意味着 FSR2 算法的核心实现不知道它位于哪个渲染 API 之上。相反,FSR2 通过接口调用提供的函数,允许 FSR2 使用不同的后端。此设计还允许应用程序集成 FSR2 提供自己的后端实现,这意味着 FSR2 当前不支持的平台可以通过实现少量函数来定位。此外,拥有自己渲染抽象的应用程序也可以实现自己的后端,从而控制 FSR2 底层功能的各个方面,包括内存管理、资源创建、着色器编译、着色器资源绑定以及将 FSR2 工作负载提交到图形设备。

invert

开箱即用,FSR2 API 将编译成多个库,遵循已概述的核心 API 和后端之间的分离。这意味着如果您想使用 FSR2 提供的后端,您应该同时链接核心 FSR2 API 库以及符合您要求的后端。

FSR2 的公开版本附带 DirectX(R)12 和 Vulkan(R) 后端,但其他后端可根据要求提供。请与您的 AMD 开发者技术代表联系以获取更多信息。

内存管理

如果 FSR2 API 与提供的后端之一(例如:DirectX(R)12 或 Vulkan(R))一起使用,那么 FSR2 所需的所有资源将直接作为已提交资源创建,使用主机应用程序提供的图形设备。但是,通过覆盖后端接口中存在的创建和销毁函数系列,应用程序可以更精确地控制 FSR2 的内存管理。

为此,您可以向 ffxFsr2ContextCreate 函数传递的 FfxFsr2ContextDescription 结构提供一个完整的自定义后端,或者您可以检索所需 API 的后端并覆盖资源创建和销毁函数以自行处理。为此,只需覆盖 fpCreateResourcefpDestroyResource 函数指针。

// Setup DX12 interface.
const size_t scratchBufferSize = ffxGetScratchMemorySizeDX12();
void* scratchBuffer = malloc(scratchBufferSize);
FfxErrorCode errorCode = ffxGetInterfaceDX12(&contextDescription.callbacks, m_pDevice->GetDevice(), scratchBuffer, scratchBufferSize);
FFX_ASSERT(errorCode == FFX_OK);
// Override the resource creation and destruction.
contextDescription.callbacks.createResource = myCreateResource;
contextDescription.callbacks.destroyResource = myDestroyResource;
// Set up the context description.
contextDescription.device = ffxGetDeviceDX12(m_pDevice->GetDevice());
contextDescription.maxRenderSize.width = renderWidth;
contextDescription.maxRenderSize.height = renderHeight;
contextDescription.displaySize.width = displayWidth;
contextDescription.displaySize.height = displayHeight;
contextDescription.flags = FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE
| FFX_FSR2_ENABLE_DEPTH_INVERTED
| FFX_FSR2_ENABLE_AUTO_EXPOSURE;
// Create the FSR2 context.
errorCode = ffxFsr2ContextCreate(&context, &contextDescription);
FFX_ASSERT(errorCode == FFX_OK);

应用程序控制 FSR2 所需内存管理的一个有趣优点是可以执行资源别名,这可以节省内存。内存要求中的表格显示了通过使用此技术可节省的内存。为了实现此表中显示的节省,应找到一块适当的内存区域(其内容在调用 FSR2 调度后无需保留),以与 FSR2 所需的可别名资源共享。FSR2 的核心 API 通过 FSR2 后端接口进行的每个 FfxCreateResourceFunc 调用都包含 FfxCreateResourceDescription 结构中的一组标志。如果 flags 字段中设置了 FFX_RESOURCE_FLAGS_ALIASABLE,则表示该资源可以与渲染帧中的其他资源安全地别名。

时间抗锯齿

时域抗锯齿 (TAA) 是一种使用上一帧输出来构建当前帧更高质量输出的技术。由于 FSR2 具有类似的目标——尽管还增加了提高渲染图像分辨率的目标——因此不再需要在应用程序中包含单独的 TAA 传递。

相机抖动

FSR2 依赖应用程序在渲染时应用亚像素抖动——这通常包含在相机的投影矩阵中。为了简化相机抖动的应用,FSR2 API 提供了一组小型实用函数,用于计算特定帧在一系列单独抖动偏移量中的亚像素抖动偏移量。

int32_t ffxFsr2GetJitterPhaseCount(int32_t renderWidth, int32_t displayWidth);
FfxErrorCode ffxFsr2GetJitterOffset(float* outX, float* outY, int32_t jitterPhase, int32_t sequenceLength);

内部,这些函数实现了 Halton[2,3] 序列 [Halton]。Halton 序列的目标是提供空间分离的点,这些点覆盖了可用空间。

invert

了解从 ffxFsr2GetJitterOffset 返回的值是以像素为单位的,并且为了正确地将其复合到投影矩阵中,我们必须将其转换为投影偏移量。上面的图显示了单位像素空间中的单个像素,以及投影空间中的单个像素。下面的代码列表显示了如何将亚像素抖动偏移值正确地复合到投影矩阵中。

根据变换串联约定(换句话说,矩阵乘法的顺序),有两种方法可以计算 jitteredProjectionMatrix

  • 预乘顺序(DirectXMath 风格的数学)。
const int32_t jitterPhaseCount = ffxFsr2GetJitterPhaseCount(renderWidth, displayWidth);
float jitterX = 0;
float jitterY = 0;
ffxFsr2GetJitterOffset(&jitterX, &jitterY, index, jitterPhaseCount);
// Calculate the jittered projection matrix.
const float jitterX = 2.0f * jitterX / (float)renderWidth;
const float jitterY = -2.0f * jitterY / (float)renderHeight;
const Matrix4 jitterTranslationMatrix = translateMatrix(Matrix3::identity, Vector3(jitterX, jitterY, 0));
const Matrix4 jitteredProjectionMatrix = jitterTranslationMatrix * projectionMatrix;
  • 后乘顺序(OpenGL® 风格的数学)。
const int32_t jitterPhaseCount = ffxFsr2GetJitterPhaseCount(renderWidth, displayWidth);
float jitterX = 0;
float jitterY = 0;
ffxFsr2GetJitterOffset(&jitterX, &jitterY, index, jitterPhaseCount);
// Calculate the jittered projection matrix.
const float jitterX = 2.0f * jitterX / (float)renderWidth;
const float jitterY = -2.0f * jitterY / (float)renderHeight;
const Matrix4 jitterTranslationMatrix = translateMatrix(Matrix3::identity, Vector3(jitterX, jitterY, 0));
const Matrix4 jitteredProjectionMatrix = projectionMatrix * jitterTranslationMatrix;

有关此主题的更多信息,请参阅矩阵汇编,您可以在其中找到计算机图形中所有可能约定下的 jitteredProjectionMatrix 的最终形式。

抖动应应用于所有渲染。这包括不透明、Alpha 透明和光线追踪对象。对于光栅化对象,可以通过相机投影矩阵应用 ffxFsr2GetJitterOffset 函数计算出的亚像素抖动值,该矩阵最终用于在顶点着色期间执行变换。对于光线追踪渲染,亚像素抖动应应用于射线的起点——通常是相机的位置。

无论您选择使用推荐的 ffxFsr2GetJitterOffset 函数还是自己的序列生成器,您都必须设置 FfxFsr2DispatchDescription 结构体的 jitterOffset 字段,以告知 FSR2 已应用抖动偏移量以渲染每一帧。此外,如果不使用推荐的 ffxFsr2GetJitterOffset 函数,应注意确保您的抖动序列永远不会生成空向量,即 X 和 Y 维度均为 0 的值。

下表显示了每个默认质量模式的抖动序列长度。

质量模式缩放因子序列长度
画质1.5x (每维)18
平衡1.7x (每维)23
性能2.0x (每维)32
超高性能3.0x (每维)72
自定义[1..n]x (每维)ceil(8 * n^2)

相机跳切

大多数具有实时渲染的应用程序在任何两个连续帧之间都具有高度的时域一致性。但是,有时相机变换的变化可能会导致渲染内容的突然变化。在这种情况下,FSR2 不太可能重用它从先前帧累积的任何数据,并且应该清除这些数据以将其排除在复合过程的考虑之外。为了向 FSR2 表明相机发生了跳帧,您应该在不连续相机变换的第一帧中将 FfxFsr2DispatchDescription 结构体的 reset 字段设置为 true

使用 reset 标志时,渲染性能可能略低于典型的帧间操作,因为 FSR2 将清除一些额外的内部资源。

Mipmap 偏差

应用负的 mipmap 偏差通常会生成具有更好纹理细节的放大图像。我们建议将以下公式应用于你的 Mipmap 偏差:

mipBias = log2(renderResolution/displayResolution) - 1.0;

建议应用程序为特定的高频纹理内容调整 MIP 偏差,这些内容容易出现时间混叠问题。

下表说明了根据上述伪代码计算出的、与应用程序应向最终用户提供的建议画质模式相匹配的缩放比例所产生的Mipmap偏置因子。

质量模式缩放因子Mipmap偏置
画质1.5倍 (每维度)-1.58
平衡1.7倍 (每维度)-1.76
性能2.0倍 (每维度)-2.0
超高性能3.0倍 (每维度)-2.58

帧时间增量输入

FSR2 API 要求应用程序通过 FfxFsr2DispatchDescription 结构提供 frameTimeDelta。此值以毫秒为单位:如果以 60fps 运行,则传递的值应约为16.6f

该值用于 FSR 2 自动曝光功能的时域部分。这允许为了质量目的对历史累积进行调整。

HDR 支持

FSR2 支持高动态范围图像。要启用此功能,您应在 FfxFsr2ContextDescription 结构的 flags 字段中设置 FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE 位。图像应以线性色彩空间提供给 FSR2。

未来版本的 FSR2 可能会提供对其他色彩空间的支持。

回退到 32 位浮点

FSR2 的设计旨在利用半精度 (FP16) 硬件加速以实现最高的性能。但是,为了提供最大的兼容性和灵活性,FSR2 还能够使用全精度 (FP32) 操作来编译着色器。

建议在所有支持 FP16 的硬件上使用 FSR2 的 FP16 版本。您可以通过查询 DirectX(R)12 中的 D3D12_FEATURE_DATA_SHADER_MIN_PRECISION_SUPPORT 功能来查询显卡的 FP16 支持级别——您应该检查是否设置了 D3D[11/12]_SHADER_MIN_PRECISION_16_BIT,如果未设置,则回退到 FSR2 的 FP32 版本。对于 Vulkan,如果未设置 VkPhysicalDeviceFloat16Int8FeaturesKHR::shaderFloat16,则应回退到 FSR2 的 FP32 版本。同样,如果未设置 VkPhysicalDevice16BitStorageFeatures::storageBuffer16BitAccess,您也应回退到 FSR2 的 FP32 版本。

要启用 FSR2 着色器源代码中的 FP32 路径,您应该将 FFX_HALF 定义为 0。为了在 FP16 和 FP32 之间共享算法的大部分源代码(确保高度的代码共享以支持持续维护),您会注意到 FSR2 着色器源代码使用一组类型宏,这些宏可以轻松地在着色器源代码的 16 位和 32 位基本类型之间切换。

FidelityFX 类型FP32FP16
FFX_MIN16_Ffloatmin16float
FFX_MIN16_F2float2min16float2
FFX_MIN16_F3float3min16float3
FFX_MIN16_F4float4min16float4

上表列出了抽象的 FidelityFX SDK 类型与基础内在类型之间的映射,后者将根据编译期间着色器源代码的配置进行替换。

64 位宽波前

现代 GPU 以 SIMT 方式一起执行线程集合(称为波前)。构成单个波精的确切线程数是特定于硬件的数量。某些硬件,例如 AMD 的 GCN 和 RDNA 系列 GPU,支持将 64 个线程组合成单个波前。根据算法执行的精确特性,偏好特定波前宽度可能更有利或更有利。随着 Shader Model 6.6 的引入,Microsoft 添加了通过 HLSL 指定波前宽度的功能。对于支持 32 位和 64 位波前宽度的硬件(如 RDNA),这是优化用途的一个非常有用的工具,因为它提供了一种清晰且可移植的方式来请求驱动程序软件堆栈执行特定宽度的波前。

对于运行在 RDNA 和 RDNA2 GPU 上并使用 Microsoft Agility SDK 的 DirectX(R)12 应用程序,FSR2 主机 API 将选择一个 64 位波前宽度。

调试器

启用调试检查器以在调度放大时验证应用程序提供的输入。此功能可以在运行时(例如,来自PrebuiltSignedDll文件夹的发布二进制文件或调试构建)的任何构建配置中启用。建议仅在游戏的开发构建中启用此功能。

在传递 FfxFsr2ContextDescription 的 flags 成员中的 FFX_FSR2_ENABLE_DEBUG_CHECKING 标志将在默认情况下将 FSR2 的文本警告输出到调试器 TTY。应用程序可以设置运行时回调函数,将消息传递到底层应用程序。应用程序可以将 FfxFsr2ContextDescriptionfpMessage 成员分配给合适的函数。fpMessage 的类型为 FfxFsr2Message,它是一个函数指针,用于传递各种类型的字符串消息。如果使用 ffx-api,另一种方法是在上调用 ffx::Configure fpMessage ffxConfigureDescGlobalDebug1 上下文。

当检查器检测到潜在问题时可能发生的输出示例如下:

FSR2_API_DEBUG_WARNING: FFX_FSR2_ENABLE_DEPTH_INFINITE and FFX_FSR2_ENABLE_DEPTH_INVERTED present, cameraFar value is very low which may result in depth separation artefacting
FSR2_API_DEBUG_WARNING: frameTimeDelta is less than 1.0f - this value should be milliseconds (~16.6f for 60fps)

技术

算法结构

FSR2 算法实现为一系列阶段,如下所示:

  1. 计算亮度金字塔
  2. 重构与膨胀
  3. 深度剪辑
  4. 创建锁
  5. 重投影与累积
  6. 鲁棒对比度自适应锐化 (RCAS)

算法的每个传递阶段都布局在本节之后的各节中,但完整的 FSR2 算法的数据流如下图所示。

invert

计算亮度金字塔

计算亮度金字塔阶段有两个职责:

  1. 生成输入颜色亮度的低分辨率版本。这用于累积阶段的着色变化检测。
  2. 生成一个 1x1 的曝光纹理,该纹理可选择用于应用色调映射,以及用于在 FSR2 产生输出之前反转局部色调映射的重新投影与累积阶段。

资源输入

下表包含 计算亮度金字塔 阶段所消耗的所有资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
颜色缓冲区当前帧渲染应用程序指定纹理应用程序提供的当前帧的渲染分辨率颜色缓冲区。如果颜色缓冲区的内容是高动态范围 (HDR),则应在创建 FfxFsr2ContextDescription 结构体的 flags 字段中设置 FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE 标志。

资源输出

下表包含 计算亮度金字塔 阶段产生或修改的所有资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
曝光当前帧1x1R32_FLOAT纹理包含当前帧计算出的曝光值的 1x1 纹理。此资源是可选的,除非在创建 FfxFsr2Context 时在 FfxFsr2ContextDescription 结构的 flags 字段中设置了 FFX_FSR2_ENABLE_AUTO_EXPOSURE 标志,否则可以省略。
当前亮度当前帧渲染 * 0.5 + MipChainR16_FLOAT纹理一个分辨率为渲染分辨率 50% 的纹理,其中包含当前帧的亮度。分配了完整的 mip 链。

描述

计算亮度金字塔 阶段使用 FidelityFX 单通道下采样器 实现,这是一种使用单个计算着色器调度来生成 mipmap 链的优化技术。与传统的(完整)金字塔方法不同,SPD 提供了一种机制来为任意输入纹理生成特定级别的 mipmap,并在将数据存储到内存中的目标位置时对该数据执行任意计算。在 FSR2 中,我们有兴趣生成最多两个中间资源,具体取决于 FfxFsr2Context 的配置。第一个资源是当前亮度的低分辨率表示,FSR2 稍后使用它来尝试检测着色变化。第二个是曝光值,虽然它总是被计算,但只有在创建上下文时在 FfxFsr2ContextDescription 结构的 flags 字段中设置了 FFX_FSR2_ENABLE_AUTO_EXPOSURE 标志时,后续阶段才会使用它。曝光值——无论是来自应用程序还是来自 计算亮度金字塔 阶段——都用于 FSR2 的 调整输入颜色 阶段,以及 重新投影与累积 阶段。

invert

FSR2 使用的 SPD 配置为仅写入第二个(半分辨率)和最后一个(1x1)mipmap级别。此外,在每个级别上应用不同的计算来计算 FSR2 算法后续阶段所需的值。这意味着其余的 mipmap 链不需要由 GPU 本地内存(或任何类型的内存)支持。

第二个 mipmap级别包含当前亮度,其值是通过使用以下 HLSL 对颜色缓冲区进行下采样计算得出的:

float3 rgb = LoadInputColor(tex);
float3 rgb2y = float3(0.2126, 0.7152, 0.0722);
float logLuma = log(max(FSR2_EPSILON, dot(rgb2y, rgb)));

最后一个 mipmap级别使用以下 HLSL 计算:

float ComputeAutoExposureFromAverageLog(float averageLogLuminance)
{
const float averageLuminance = exp(averageLogLuminance);
const float S = 100.0f; // ISO arithmetic speed
const float K = 12.5f;
const float exposureIso100 = log2((averageLuminance * S) / K);
const float q = 0.65f;
const float luminanceMax = (78.0f / (q * S)) * pow(2.0f, exposureIso100);
return 1 / luminanceMax;
}

重构并膨胀

重构与膨胀阶段消耗应用程序的深度缓冲区和运动矢量,并生成上一帧的重构和膨胀的深度缓冲区,以及 UV 空间中的一组膨胀的运动矢量。该阶段在渲染分辨率下运行。

invert

资源输入

下表包含重构与膨胀阶段所需的所有资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
颜色缓冲区当前帧渲染应用程序指定纹理应用程序提供的当前帧的渲染分辨率颜色缓冲区。如果颜色缓冲区的内容是高动态范围 (HDR),则应在创建 FfxFsr2ContextDescription 结构体的 flags 字段中设置 FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE 标志。
曝光当前帧1x1R32_FLOAT纹理包含当前帧计算出的曝光值的 1x1 纹理。此资源可以由应用程序提供,或者由 FSR2 的 计算亮度金字塔 阶段计算,前提是在创建 FfxFsr2Context 时在 FfxFsr2ContextDescription 结构的 flags 字段中设置了 FFX_FSR2_ENABLE_AUTO_EXPOSURE 标志。
深度缓冲区当前帧渲染应用程序指定 (1x FLOAT)纹理由应用程序提供的当前帧的渲染分辨率深度缓冲区。数据应以单个浮点值形式提供,其精度由应用程序控制。应通过创建 FfxFsr2ContextFfxFsr2ContextDescription 结构的 flags 字段将深度配置告知 FSR2。如果您的深度缓冲区是反转的(即 [1..0] 范围),则应设置 FFX_FSR2_ENABLE_DEPTH_INVERTED 标志,如果您的深度缓冲区具有无限远平面,也应设置该标志。如果应用程序以 D32S8 格式提供深度缓冲区,则 FSR2 将忽略缓冲区的模板组件,并创建一个 R32_FLOAT 资源来处理深度缓冲区。在 GCN 和 RDNA 硬件上,深度缓冲区与模板缓冲区分开存储。
运动矢量当前帧渲染或呈现应用程序指定 (2x FLOAT)纹理由应用程序提供的当前帧的 2D 运动矢量,范围为 [(<-width, -height>..<width, height>]。如果您的应用程序以不同的范围渲染运动矢量,您可以使用 FfxFsr2DispatchDescription 结构的 motionVectorScale 字段来调整它们以匹配 FSR2 的预期范围。在内部,FSR2 在许多情况下使用 16 位量来表示运动矢量,这意味着虽然可以提供更高精度的运动矢量,但 FSR2 将无法从中受益。运动矢量缓冲区的分辨率应等于渲染分辨率,除非在创建 FfxFsr2Context 时在 FfxFsr2ContextDescription 结构的 flags 字段中设置了 FFX_FSR2_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS 标志,在这种情况下,它应等于显示分辨率。

资源输出

下表包含重构与膨胀阶段产生的所有资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
估计上一帧深度缓冲区当前帧渲染R32_UNORM纹理包含重构的上一帧深度值的纹理。此表面应首先被清除,有关详细信息,请参阅调整输入颜色阶段。请注意:在捕获工具(如 RenderDoc)中查看此纹理时,它可能无法正确显示。这是因为此纹理的格式为 R32_UNORM,并且包含 IEEE754 浮点值,这些值是在使用 asuint 内置函数进行位转换后写入的。有关此工作方式的具体细节,请参阅重新投影与累积中的注释。
膨胀深度当前帧渲染R16_UINT纹理包含从应用程序深度缓冲区计算出的膨胀深度值的纹理。
膨胀运动矢量当前帧渲染R16G16_FLOAT纹理包含从应用程序的 2D 运动矢量缓冲区计算出的膨胀 2D 运动矢量的纹理。红色和绿色通道包含 NDC 空间中的二维运动矢量。
上一帧深度缓冲区当前帧渲染R32_UNORM纹理包含重构和膨胀的深度值的纹理。此表面由调整输入颜色阶段清除。请注意:在捕获工具(如 RenderDoc)中查看此纹理时,它可能无法正确显示。这是因为此纹理的格式为 R32_UNORM,并且包含 IEEE754 浮点值,这些值是在使用 asuint 内置函数进行位转换后写入的。有关此工作方式的具体细节,请参阅调整输入颜色中的注释。
锁定输入亮度当前帧渲染R16_FLOAT纹理包含供锁定阶段消耗的亮度数据的纹理。

描述

重构与膨胀阶段的第一步是从当前帧的应用程序深度值和运动矢量计算膨胀的深度值和运动矢量。膨胀的深度值和运动矢量会强调已渲染到深度缓冲区中的几何体的边缘。这是因为几何体的边缘通常会在连续的深度值序列中引入不连续性,这意味着随着深度值和运动矢量的膨胀,它们会自然地遵循深度缓冲区中存在的几何体边缘的轮廓。为了计算膨胀的深度值和运动矢量,FSR2 会查看每个像素的 3x3 邻域的深度值,然后选择该邻域中深度值最接近相机的深度值和运动矢量。在下面的图中,您可以看到 3x3 内核的中心像素如何被右侧中间具有最大深度值的像素的深度值和运动矢量更新。

由于这是 FSR2 首次消耗运动矢量的阶段,因此如果使用 FSR2 主机 API,将在此处应用运动矢量缩放。通过 FfxFsr2DispatchDescription 结构体的 motionVectorScale 字段提供的运动矢量缩放因子允许您将非屏幕空间运动矢量转换为 FSR2 所期望的屏幕空间运动矢量。

// An example of how to manipulate motion vector scaling factors using the FSR2 host API.
FfxFsr2DispatchParameters dispatchParams = { 0 };
dispatchParams.motionVectorScale.x = renderWidth;
dispatchParams.motionVectorScale.y = renderHeight;

有了膨胀的运动矢量,我们现在可以进入重构与膨胀阶段的第二部分,即估计当前帧深度缓冲区中每个像素在上一帧中的位置。这是通过将像素的膨胀运动矢量应用于其深度缓冲区值来完成的。由于可能有很多像素重新投影到上一帧深度缓冲区中的同一个像素,因此使用原子操作来解析每个像素的最近深度值。这是通过使用InterlockedMaxInterlockedMin操作(选择取决于应用程序的深度缓冲区是否反转)来完成的。使用累积操作来解析上一深度缓冲区的内容意味着重构的深度缓冲区资源必须始终被清除为已知值,这在重新投影与累积阶段执行。这是对第 N 帧执行的,用于第 N + 1 帧。

invert

使用 FSR2 API 时,应用程序的深度缓冲区和应用程序的运动矢量缓冲区必须作为单独的资源指定,如上资源输入表所示。但是,如果您在应用程序中进行自定义集成,此限制可能会放宽。请注意,如果移动到更稀疏的运动矢量纹理格式(例如:在延迟渲染器中作为打包的 g-buffer 的一部分),此传递的性能特征不会改变。

深度剪辑

深度裁剪阶段的目标是生成一个掩码,指示当前帧的未遮挡区域。

此阶段在渲染分辨率下运行。

资源输入

下表包含 深度裁剪 阶段所需的所有资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
估计上一帧深度缓冲区当前帧渲染R32_UNORM纹理包含重构的上一帧深度值的纹理。此表面应首先被清除,有关详细信息,请参阅重新投影与累积阶段。请注意:在捕获工具(如 RenderDoc)中查看此纹理时,它可能无法正确显示。这是因为此纹理的格式为 R32_UINT,并且包含 IEEE754 浮点值,这些值是在使用 asuint 内置函数进行位转换后写入的。有关此工作方式的具体细节,请参阅重新投影与累积中的注释。
膨胀深度当前帧渲染R32_FLOAT纹理包含从应用程序深度缓冲区计算出的膨胀深度值的纹理。
膨胀运动矢量当前帧和上一帧渲染R16G16_FLOAT纹理包含从应用程序的运动矢量缓冲区计算出的膨胀 2D 运动矢量的纹理。红色和绿色通道包含 NDC 空间中的二维运动矢量,Alpha 通道包含 深度裁剪 阶段使用的深度值。
重叠掩码当前帧渲染R8_UNORM纹理由于渲染图像的某些区域在深度缓冲区中不留下足迹或不包含运动矢量,FSR2 支持反应性蒙版纹理,可用于向 FSR2 指示这些区域的位置。这些区域的好例子是粒子或未写入深度或运动矢量的 alpha 混合对象。如果未设置此资源,则 FSR2 的着色变化检测逻辑将尽力处理这些情况,但为了获得最佳结果,应设置此资源。有关反应性蒙版的更多信息,请参阅 反应性蒙版 部分。
颜色缓冲区当前帧渲染应用程序指定纹理应用程序提供的当前帧的渲染分辨率颜色缓冲区。如果颜色缓冲区的内容是高动态范围 (HDR),则应在创建 FfxFsr2ContextDescription 结构体的 flags 字段中设置 FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE 标志。
曝光当前帧1x1R32_FLOAT纹理包含当前帧计算出的曝光值的 1x1 纹理。此资源可以由应用程序提供,或者由 FSR2 的 计算亮度金字塔 阶段计算,前提是在创建 FfxFsr2Context 时在 FfxFsr2ContextDescription 结构的 flags 字段中设置了 FFX_FSR2_ENABLE_AUTO_EXPOSURE 标志。
深度缓冲区当前帧渲染应用程序指定 (1x FLOAT)纹理由应用程序提供的当前帧的渲染分辨率深度缓冲区。数据应以单个浮点值形式提供,其精度由应用程序控制。应通过创建 FfxFsr2ContextFfxFsr2ContextDescription 结构的 flags 字段将深度配置告知 FSR2。如果您的深度缓冲区是反转的(即 [1..0] 范围),则应设置 FFX_FSR2_ENABLE_DEPTH_INVERTED 标志,如果您的深度缓冲区具有无限远平面,也应设置该标志。如果应用程序以 D32S8 格式提供深度缓冲区,则 FSR2 将忽略缓冲区的模板组件,并创建一个 R32_FLOAT 资源来处理深度缓冲区。在 GCN 和 RDNA 硬件上,深度缓冲区与模板缓冲区分开存储。
运动矢量当前帧渲染或呈现应用程序指定 (2x FLOAT)纹理由应用程序提供的当前帧的 2D 运动矢量,范围为 [(<-width, -height>..<width, height>]。如果您的应用程序以不同的范围渲染运动矢量,您可以使用 FfxFsr2DispatchDescription 结构的 motionVectorScale 字段来调整它们以匹配 FSR2 的预期范围。在内部,FSR2 在许多情况下使用 16 位量来表示运动矢量,这意味着虽然可以提供更高精度的运动矢量,但 FSR2 将无法从中受益。运动矢量缓冲区的分辨率应等于渲染分辨率,除非在创建 FfxFsr2Context 时在 FfxFsr2ContextDescription 结构的 flags 字段中设置了 FFX_FSR2_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS 标志,在这种情况下,它应等于显示分辨率。

资源输出

下表包含 深度裁剪 阶段产生的所有资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
调整后的颜色缓冲区当前帧渲染R16G16B16A16_FLOAT纹理包含应用程序颜色缓冲区的调整后版本的纹理。色调映射运算符可能与应用程序中包含的任何色调映射运算符不同,而是 FSR2 中使用的局部、可逆运算符。此缓冲区以 YCoCg 格式存储。Alpha 通道包含非遮挡掩码。
膨胀重叠掩码当前帧渲染R8G8_UNORM纹理膨胀的重叠掩码。

描述

要生成非遮挡掩码,必须为每个像素计算上一相机位置和新相机位置的深度值。在下面的图中,您可以看到相机从初始位置(标记为 P0)移动到新位置(标记为 P1)。在此过程中,球体后面的着色区域变得非遮挡——也就是说,从 P1 相机可以看到它,而从 P0 的视角来看它之前是遮挡的。

invert

有了这两个深度值,我们就可以将它们之间的差值与 Akeley 分离值 [Akeley-06] 进行比较。直观地说,Akeley 分离常数提供两个在浮点深度缓冲区中表示的对象之间的最小距离,允许您——高度确定地——说这些对象最初是彼此独立的。在下面的图中,您可以看到中灰色和深灰色对象之间的差值大于为应用程序深度缓冲区配置计算出的 kSep 值。但是,浅灰色对象到中灰色对象的距离并未超过计算出的 kSep 值,因此我们无法确定此对象是否独立。

invert

存储在非遮挡掩码中的值范围为 [0..1],其中 1 映射到大于或等于 Akeley 分离值的值。

创建锁

此阶段负责在将要被重新投影与累积阶段使用的像素上创建新的锁定。此阶段在渲染分辨率下运行。

资源输入

下表包含 创建锁定 阶段所消耗的所有资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
锁定输入亮度当前帧渲染R16_FLOAT纹理包含供锁定阶段消耗的亮度数据的纹理。

资源输出

下表包含 创建锁定 阶段产生或修改的所有资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
新锁定掩码当前帧演示R8_UNORM纹理一个掩码,指示是否对像素执行颜色校正,可视为对像素的锁定,以阻止校正去除细节。请注意:此纹理是纹理数组的一部分,该数组包含两个纹理,与用于此阶段输入的锁定状态纹理一起。每帧都会交换使用数组中的哪个纹理作为输入和输出。红色通道包含像素锁定剩余的时间,Y 通道包含创建锁定时的像素亮度。创建锁定阶段仅更新此资源的一部分。
估计上一帧深度缓冲区下一帧渲染R32_UNORM纹理此仅用于清除。

描述

直观地说,像素锁定是一种停止对像素应用颜色校正的机制。此锁定的净效应是,在计算重新投影与累积阶段最终的超分辨率像素颜色时,会使用更多上一帧的颜色数据。锁定状态纹理包含两个值,它们共同构成一个像素锁定。锁定状态纹理的红色通道包含像素锁定剩余的生命周期。此值通过初始锁定长度除以抖动序列的总长度来递减。当锁定达到零时,它被视为已过期。锁定状态纹理的绿色通道包含创建锁定时的像素亮度,但仅在重新投影与累积阶段的重新投影阶段填充。亮度值最终在重新投影与累积阶段用作着色变化检测的一部分,这允许 FSR2 在像素外观出现不连续变化时(例如:像素着色突然变化)解锁像素。

创建锁定(lock)时,将 3x3 邻域的亮度值与阈值进行比较。比较结果决定是否应创建新锁定。使用邻域允许我们检测输入图像中的细微特征,这些特征应被锁定以在最终的超分辨率图像中保留细节;例如电线或链式栅栏。

此外,此阶段还负责将重新投影的深度缓冲区清除为已知值,为应用程序下一帧的重构与膨胀阶段做好准备。必须清除缓冲区,因为重构与膨胀将使用原子操作对其进行填充。根据深度缓冲区的配置,会选择适当的清除值。

上一帧深度缓冲区的格式为 R32_UINT,它允许从 FSR2 的重构与膨胀阶段执行 InterlockedMaxInterlockedMin 操作。这是通过将深度值通过asint函数转换后返回的整数值来完成的。这样做是因为深度值总是大于 0,这意味着 IEEE754 浮点值作为整数解释时的一致性是保证的。

重投影与累积

此阶段执行以下步骤:

  1. 使用 Lanczos 滤波对当前帧的颜色缓冲区进行上采样。
  2. 对上一帧的输出颜色和锁定状态缓冲区进行重新投影,就像从当前相机视角查看一样。
  3. 对历史颜色数据进行各种清理步骤。
  4. 计算亮度不稳定性。
  5. 累积历史颜色数据和当前帧的上采样颜色数据。

此阶段在显示分辨率下运行。

资源输入

下表包含 重新投影与累积 阶段所需的所有资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。如果提供显示分辨率运动矢量,则重新投影步骤将使用矢量的全精度,因为我们直接读取资源。

名称时域层分辨率格式类型说明
曝光当前帧1x1R32_FLOAT纹理包含当前帧计算出的曝光值的 1x1 纹理。此资源是可选的,除非在创建 FfxFsr2Context 时在 FfxFsr2ContextDescription 结构的 flags 字段中设置了 FFX_FSR2_ENABLE_AUTO_EXPOSURE 标志,否则可以省略。
膨胀运动矢量当前帧渲染R16G16_FLOAT纹理包含从应用程序的运动矢量缓冲区计算出的膨胀运动矢量的纹理。红色和绿色通道包含 UV 空间中的二维运动矢量。
膨胀重叠掩码当前帧渲染R8G8_UNORM纹理膨胀的重叠掩码。
上采样缓冲区上一帧演示R16G16B16A16_FLOAT纹理FSR2 在上一帧运行时产生的输出缓冲区。请注意:此缓冲区由 FSR2 内部使用,并且与从输出缓冲区派生的显示缓冲区不同,并且应用了RCAS。请注意:此纹理是纹理数组的一部分,该数组包含两个纹理,与重新投影与累积阶段产生的输出缓冲区纹理一起。每帧都会交换使用数组中的哪个纹理作为输入和输出。
当前亮度当前帧渲染 * 0.5R16_FLOAT纹理一个分辨率为渲染分辨率 50% 的纹理,其中包含当前帧的亮度。
亮度历史多帧演示R8G8B8A8_UNORM纹理包含三帧亮度历史的纹理,以及编码在 Alpha 通道中的稳定性因子。
调整后的颜色缓冲区当前帧渲染R16G16B16A16_FLOAT纹理包含应用程序颜色缓冲区的调整后版本的纹理。色调映射运算符可能与应用程序中包含的任何色调映射运算符不同,而是 FSR2 中使用的局部、可逆运算符。此缓冲区以 YCoCg 格式存储。Alpha 通道包含非遮挡掩码。
锁定状态上一帧演示R16G16_FLOAT纹理一个掩码,指示不应对像素执行颜色裁剪,可视为对像素的锁定,以阻止裁剪去除细节。有关像素锁定机制的更详细说明,请参阅创建锁定阶段。请注意:此纹理是纹理数组的一部分,该数组包含两个纹理,与作为此阶段输出的锁定状态纹理一起。每帧都会交换使用数组中的哪个纹理作为输入和输出。
新锁定掩码当前帧演示R8_UNORM纹理一个掩码,指示是否对像素执行颜色校正,可视为对像素的锁定,以阻止校正去除细节。请注意:此纹理是纹理数组的一部分,该数组包含两个纹理,与用于此阶段输入的锁定状态纹理一起。每帧都会交换使用数组中的哪个纹理作为输入和输出。红色通道包含像素锁定剩余的时间,Y 通道包含创建锁定时的像素亮度。创建锁定阶段仅更新此资源的一部分。

资源输出

此表包含 重新投影与累积 阶段产生的资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
上采样缓冲区当前帧演示R16G16B16A16_FLOAT纹理当前帧的 重新投影与累积 阶段产生的输出缓冲区。请注意:此缓冲区由 FSR2 内部使用,并且与此阶段应用 RCAS 后产生的显示缓冲区不同。请注意:此纹理是纹理数组的一部分,该数组包含两个纹理,与重新投影与累积阶段消耗的输出缓冲区纹理一起。每帧都会交换使用数组中的哪个纹理作为输入和输出。
重新投影的锁定当前帧演示R16G16_FLOAT纹理重新投影的锁定状态纹理。
亮度历史多帧演示R8G8B8A8_UNORM纹理包含三帧亮度历史的纹理,以及编码在 Alpha 通道中的稳定性因子。
新锁定掩码下一帧演示R8_UNORM纹理为下一帧清除。

描述

FSR2 的重新投影与累积阶段是最复杂也是最昂贵的阶段。它汇集了先前许多算法步骤的结果,并将上一帧的重新投影颜色数据与当前帧的上采样颜色数据累积起来。请注意,本文档中的描述旨在让您直观地了解此阶段涉及的步骤,并不一定与实际实现精确匹配。

重新投影与累积阶段的第一步是评估每个像素的着色变化。如果我们处于锁定区域,则将创建锁定时的亮度与 FSR2 的着色变化阈值进行比较。在非锁定区域,将使用当前帧和历史亮度值来做出此决定。着色变化确定是 FSR2 重新投影与累积阶段的关键部分,并为该阶段的许多其他部分提供输入。

invert

接下来,我们必须对调整后的颜色进行上采样。为了执行上采样,调整后的颜色的像素位置作为 5x5 Lanczos 重采样核的中心 [Lanczos]。在上面的图中,您可以看到 Lanczos 函数以显示分辨率样本 S 为中心。每个像素中的点——标记为 P——表示我们计算 Lanczos 权重的渲染分辨率抖动样本位置。查看 5x5 像素邻域的上方和右侧,您可以看到 Lanczos(x, 2) 重采样内核应用于围绕像素位置的 5x5 像素网格中的渲染分辨率样本。值得注意的是,虽然概念上邻域是 5x5,但在实现中,由于最外围像素的零权重贡献,实际上只采样了 4x4。Lanczos 内核的实现可能因 GPU 产品而异。在基于 RDNA2 的产品上,我们使用查找表 (LUT) 来编码 sinc(x) 函数。这有助于在重新投影与累积阶段产生 ALU 和内存之间的更和谐的平衡。由于上采样步骤可以访问 5x5 像素邻域,因此从效率角度来看,在此处计算 YCoCg 边界框(在颜色校正期间使用)是有意义的。下图显示了从当前像素周围的 3x3 邻域构建的 2D YCo 边界框,实际上边界框还有一个用于 Cg 的第三个维度。

invert

重新投影是重新投影与累积阶段的另一个关键部分。为了执行重新投影,将采样由重构与膨胀阶段产生的膨胀运动矢量,然后将其应用于 FSR2 上一帧执行的输出缓冲区。下图的左侧显示了二维运动矢量 M 被应用于当前像素位置。右侧,您可以看到 Lanczos(x, 2) 重采样内核应用于平移像素位置周围的 5x5 像素网格。与上采样步骤一样,Lanczos 内核的实现可能因 GPU 产品而异。重新投影的结果是显示分辨率图像,其中包含所有可以映射到当前帧的上一帧数据。但是,重新投影的不仅仅是上一帧的输出颜色。由于 FSR2 依赖于一种机制,即每个像素都可以被锁定以增强其时域稳定性,因此锁定也必须从上一帧重新投影到当前帧。这与颜色数据的重新投影非常相似,但还结合了我们对各种当前和历史亮度值进行的着色变化检测步骤的结果。

invert

现在是时候更新我们的锁定(lock)了。更新锁定的第一个任务是查找在此帧的创建锁定阶段创建但未重新投影的锁定,并将当前帧的亮度值写入重新投影锁定纹理的绿色通道。剩下要做的就是确定哪些锁定对于当前帧是可信的,并将它们传递给颜色校正步骤。可信度确定是通过比较当前亮度纹理中像素邻域内的亮度值来完成的。如果这些值之间的亮度差异很大,那么我们就不应该信任锁定。

在应用了我们的锁定更新并确定了其可信度后,我们可以进入颜色校正,这是 FSR2 重新投影与累积阶段的下一个关键步骤。在此阶段,将从像素的历史数据中确定一个最终颜色,然后将其与当前帧的上采样颜色混合,以形成最终累积的超分辨率颜色。最终历史颜色及其贡献的确定主要由两件事控制:

  1. 减少非遮挡区域的历史样本的影响。这是通过将颜色值与非遮挡掩码进行调制来完成的。
  2. 减少历史样本(在下图中标为ShS_h)的影响,这些样本距离当前帧颜色的边界框(在重新投影与累积阶段的上采样阶段计算)很远。

invert

重新投影与累积阶段的最后一步是累积当前帧的上采样颜色与校正后的历史颜色数据。默认情况下,FSR2 通常会以相对较低的线性插值因子混合当前帧——也就是说,最终输出中包含的当前帧相对较少。但是,这可以根据应用程序提供的响应性掩码的内容进行更改。有关更多详细信息,请参阅响应性掩码部分。

鲁棒对比度自适应锐化 (RCAS)

鲁棒对比度自适应锐化 (RCAS) 最初在 FidelityFX Super Resolution 1.0 中引入,作为额外的锐化通道,以帮助生成更清晰的最终放大图像。RCAS 是流行的对比度自适应锐化 (CAS) 算法的衍生,但有一些关键区别使其更适合放大。CAS 使用简化的机制将局部对比度转换为可变量的锐度,而 RCAS 则使用更精确的机制,在裁剪之前求解最大局部锐度。此外,RCAS 还具有内置过程来限制它检测到的可能噪声的锐化。CAS 中包含的一些缩放功能(在 CAS 中包含)不包含在 RCAS 中,因此它应该在显示分辨率下运行。

资源输入

此表包含 鲁棒对比度自适应锐化 (RCAS) 阶段消耗的资源。

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
上采样缓冲区当前帧演示R16G16B16A16_FLOAT纹理当前帧的 重新投影与累积 阶段的输出缓冲区。请注意:此缓冲区由 FSR2 内部使用,并且与此阶段应用 RCAS 后产生的显示缓冲区不同。请注意:此纹理是纹理数组的一部分,该数组包含两个纹理,与重新投影与累积阶段消耗的输出缓冲区纹理一起。每帧都会交换使用数组中的哪个纹理作为输入和输出。

资源输出

时域层指示应从哪个帧源数据。“当前帧”表示数据应从为下一个要显示的帧创建的资源中获取。“上一帧”表示数据应从为刚刚显示的帧创建的资源中获取。分辨率列指示数据是应为“渲染”分辨率还是“显示”分辨率。“渲染”分辨率表示资源应与应用程序正在执行的渲染分辨率匹配。相反,“显示”表示目标的分辨率应与将显示给用户的分辨率匹配。

名称时域层分辨率格式类型说明
显示缓冲区当前帧演示应用程序特定纹理当前帧完成的 FSR2 算法产生的显示缓冲区。

描述

RCAS 操作在通过横向模式配置的 5 点滤波器采样的数据上进行。请参阅下图。

invert

检索到样本后,RCAS 会选择导致无裁剪的“w”,限制“w”,然后乘以“sharp”量。上述解决方案在 MSAA 输入方面存在问题,因为沿着梯度的步骤会导致边缘检测问题。为了稳定 RCAS 的结果,它使用 4 倍的最大值和 4 倍的最小值(取决于方程)来代替各个抽样点,并从“m”切换到最小值或最大值(取决于侧面),以帮助能量守恒。

构建示例

要构建 FSR2 示例,请遵循以下说明:

  1. 安装以下工具
  1. 生成 Visual Studio 解决方案

    终端窗口
    > <installation path>\BuildSamplesSolution.bat

    批处理文件将询问是否应将 SDK 构建为 DLL(如果未提供‘n’,则构建为静态链接库),以及应包含哪些示例。请使用‘1’来构建包含所有示例的解决方案,或提供要包含的示例列表(使用示例对应的编号,数字之间用空格隔开)。

    这将生成一个 build\ 目录,您将在其中找到 SDK 示例的解决方案(FidelityFX SDK Samples.sln)。

  2. 打开解决方案,编译并运行。

局限性

FSR2 需要具有类型化 UAV 加载和 R16G16B16A16_UNORM 支持的 GPU。

版本历史

版本日期
2.2.12023-05-12
2.2.02023-02-16
2.1.22022-10-19
2.1.12022-09-15
2.1.02022-09-08
2.0.12022-06-22

有关版本的更多详细信息,请参阅变更日志。

参考文献

[Akeley-06] Kurt Akeley 和 Jonathan Su,“Minimum Triangle Separation for Correct Z-Buffer Occlusion”http://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/readings/akeley06_triseparation.pdf

[Lanczos] Lanczos 重采样,“Lanczos resampling”https://en.wikipedia.org/wiki/Lanczos_resampling

[Halton] Halton序列,“Halton序列”https://en.wikipedia.org/wiki/Halton_sequence

[YCoCg] YCoCg 色彩空间,https://en.wikipedia.org/wiki/YCoCg

另请参阅

© . This site is unofficial and not affiliated with AMD.