FidelityFX 帧插值 1.1.3
目录
引言
FidelityFX 帧插值技术需要 2 个后缓冲区,以及与 FSR3Upscaler 和 FfxOpticalFlow 共享的几个资源,以计算 2 个后缓冲区之间的插值图像。与上采样器共享的资源也可以在准备传递中进行计算。
该技术旨在与 FfxOpticalFlow(通过使用该技术生成的纹理)和 FfxFsr3Upscaler(通过使用该技术的内部表面)配合使用。尽管 FfxFrameInterpolation 不直接使用这些技术的接口,但它在调度时需要一些表面的引用,因此必须将 FfxOpticalFlow 与 FfxFrameInterpolation 一起使用来计算这些表面。
FfxFrameInterpolation> 效果仅计算插值图像。完成此操作后,仍然需要使用插值后的和实际的后缓冲区,即通常发送到交换链。关于如何处理后缓冲区的演示和节奏,请参阅帧插值交换链文档。
着色语言要求
HLSLCS_6_2CS_6_6†
† 在某些支持 64 位宽波前的硬件上使用 CS_6_6。
- Vulkan 1.x
GLSL 4.50,并支持以下扩展GL_EXT_samplerless_texture_functionsGL_EXT_shader_image_load_formatted
请注意,GLSL 编译器还必须支持 GL_GOOGLE_include_directive 以处理 GLSL 着色器系统中使用的 #include。
集成
FidelityFX 帧插值应按照 FidelityFX API 的说明进行集成,如组合 FSR 集成文档中所述。
本节介绍如何直接使用 FidelityFX 帧插值 API,并有助于理解该组件的内部工作原理。
创建
可以通过调用 ffxFrameInterpolationContextCreate 函数来创建该效果,并将指向 FfxFrameInterpolationContext 容器的指针和指向 FfxFrameInterpolationContextDescription 结构的指针传递进去,该结构填充了与帧插值上下文相关的数据。
FfxFrameInterpolationContextDescription 结构包含配置数据
- 一个要使用的 FidelityFX 后端接口
- 一组初始化标志
- 渲染将执行的最大分辨率
- 将进行插值的资源的分辨率
- 将进行插值的资源格式
初始化标志通过 FfxFrameInterpolationInitializationFlagBits 枚举提供
| 标志 | 说明 |
|---|---|
FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED | 一个位,指示提供的输入深度缓冲区数据是反转的 [1..0]。一个位,指示深度缓冲区已反转。 |
FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INFINITE | 一个位,指示提供的输入深度缓冲区数据使用的是无限远平面。 |
FFX_FRAMEINTERPOLATION_ENABLE_TEXTURE1D_USAGE | 一个位,指示后端应使用一维纹理。 |
FFX_FRAMEINTERPOLATION_ENABLE_HDR_COLOR_INPUT | 一个位,指示提供的输入颜色数据是否使用高动态范围。 |
调度
为了调度该效果并获得相关结果,请调用 ffxFrameInterpolationContextDispatch 函数,并将 FfxFrameInterpolationDispatchDescription 结构填充如下:
FfxFrameInterpolationDispatchDescription 成员 | 说明 |
|---|---|
flags | FfxFrameInterpolationDispatchFlags 的组合。 |
commandList | 用于将帧插值命令记录到其中的 FfxCommandList。 |
displaySize | 目标输出尺寸。 |
renderSize | 用于渲染游戏内容的分辨率。dilatedDepth 和 dilatedMotionVectors 预计为此尺寸。 |
currentBackBuffer | 当前的演示颜色缓冲区。如果未使用 currentBackBuffer_HUDLess,则此缓冲区将用作插值源数据。 |
currentBackBuffer_HUDLess | 不带 HUD 内容的当前演示颜色缓冲区。使用时,它将用作插值源数据。 |
output | 用于存储插值结果的输出资源。 |
dilatedDepth | 已放大(dilated)的深度缓冲区数据。 |
dilatedMotionVectors | 已放大(dilated)的运动矢量数据。 |
reconstructPrevNearDepth | 估计的上一帧的深度缓冲区。 |
interpolationRect | 在仅使用屏幕的一部分时(例如由于电影条纹),应使用此后缓冲区区域进行插值。 |
opticalFlowVector | 光流运动矢量。 |
opticalFlowSceneChangeDetection | 光流场景变化检测数据。 |
opticalFlowBufferSize | 光流运动矢量资源尺寸。 |
opticalFlowScale | 光流运动矢量缩放因子,用于将资源值缩放到 [0.0,1.0] 范围。 |
opticalFlowBlockSize | 光流块尺寸。 |
cameraNear | 相机近裁剪面的距离。 |
cameraFar | 相机远裁剪面的距离。仅在非无限深度情况下使用。 |
cameraFovAngleVertical | 相机垂直视场角(以弧度表示)。 |
viewSpaceToMetersFactor | 用于将视图空间坐标缩放到米的单位。 |
frameTimeDelta | 自上一帧以来经过的时间(以毫秒为单位)。 |
reset | 一个布尔值,如果为 true,则表示相机发生了不连续的移动。 |
backBufferTransferFunction | 用于将插值源颜色数据转换为线性 RGB 的传递函数。 |
minMaxLuminance[2] | 最小和最大亮度值,用于将 HDR 颜色转换为线性 RGB。 |
FfxFrameInterpolationDispatchDescription> 的 flags 属性可以是以下内容的组合:
FfxFrameInterpolationDispatchFlags | 说明 |
|---|---|
FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES | 一个标志,指示是否应启用调试输出的撕裂线可视化。 |
FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW | 一个标志,指示是否应启用调试输出的内部表面可视化。 |
传递给 output 的资源必须具有带 Alpha 通道的格式,该 Alpha 通道用于存储一些中间数据。
销毁
可以使用 ffxFrameInterpolationContextDestroy 函数销毁上下文,并将指向相关上下文容器的指针传递进去。
技术
算法结构
FfxFrameInterpolation> 算法实现为一系列阶段,如下所示:
准备输入
如果使用 FSR3 上采样器,则上采样期间生成的某些资源会被帧插值使用。如果未使用上采样器,则必须通过调用 ffxFrameInterpolationPrepare 来生成它们。此过程与上采样器的准备输入传递类似,但它仅生成帧插值所需的资源子集。
设置传递
设置传递会清除内部 Counter、GameMotionVectorFieldXY、OpticalFlowVectorFieldXY 和 DisocclusionMask 表面,因为它们将通过原子操作使用。
估算插值帧深度
此传递(使用 ReconstructPreviousDepthPass 管道)计算插值帧的估计的扩张深度缓冲区。它基于时间上采样器中使用的ReconstructAndDilate 传递的深度重建逻辑。
为了计算插值帧的深度缓冲区,此传递会消耗来自 Fsr3Upscaler 的扩张深度和运动矢量表面,并通过运动矢量长度的一半进行重投影和扩张。
计算游戏运动矢量场
GameMotionVectorField> 传递构建了插值帧位置的参考帧。这意味着,当使用游戏运动矢量采样上一帧和当前帧数据时,会生成一个插值帧。
为此,该传递将 DilatedMotionVectors 打包到一对 32 位 UINT 值中的低 16 位中。高 16 位包含一个优先级,由最高 1 位指示矢量是主矢量还是次矢量,10 位指示基于与相机距离的优先级,低 5 位优先级基于上一帧和当前后缓冲区的颜色相似性。
值通过原子操作写入,并不保证所有位置都在此传递中写入,因此字段中可能存在一些空隙。
计算游戏运动矢量场内插金字塔
上一传递未写入的位置将通过相邻矢量信息填充。为了实现这一点,此传递使用SPD 生成游戏运动矢量场的完整 mip 链。
在此 mip 链中,游戏运动矢量将存储在 .xy 通道中,基于深度的优先级因子将存储在 .z 通道中,基于颜色相似性的优先级因子将存储在 .w 通道中。
在计算 mip 链时,将选择二维中最接近的矢量和深度中最远的矢量。
计算光流矢量场
此传递类似于 GameMotionVectorField 传递,但使用 FfxOpticalFlow 矢量生成的运动矢量作为输入。
高优先级值基于矢量幅度计算,低优先级值基于使用光流运动矢量重投影颜色的颜色相似性计算。
计算遮挡去除掩码
此传递基于时间上采样器的遮挡去除逻辑,但会产生两个遮挡去除掩码:
- 一个掩码表示插值帧和上一帧之间的遮挡区域
- 一个掩码表示插值帧和当前帧之间的遮挡区域
使用此掩码,计算插值传递将确定是否应丢弃任何重投影方向。
计算插值
此传递使用遮挡去除掩码和运动矢量场计算插值图像。
为此,它首先读取计数器并检查这是重置后的第一张图像,如果是,它将简单地复制最新的后缓冲区。
在此之后,算法分两个阶段进行操作:
- 首先,它通过根据遮挡去除掩码值混合两个颜色值来计算每个像素的插值颜色。
- 接下来,它基于光流运动矢量计算插值颜色,并将其与基于游戏运动矢量结果进行混合。
- 此操作的混合因子基于每种情况下的上一帧和当前帧颜色的相似性,简而言之,如果光流运动矢量产生更好的匹配,算法会优先选择它们而非游戏运动矢量。
生成的图像可能包含一些孔洞,这些孔洞将在算法的最后一步由内插传递填充。
计算内插金字塔
此传递使用SPD 来生成插值颜色的完整 mip 链。插值颜色中的孔洞将被忽略,因此从 mip 链采样将导致颜色平均自二维空间中最接近的颜色值。
内插
此传递通过使用内插金字塔查找最接近的可用颜色来填充计算插值传递中留下的任何孔洞。
之后,该传递会清理 UI,以防使用无 HUD UI 模式,然后可选地将调试信息添加到插值图像中。
调试输出
帧插值 API 支持两种类型的调试视图:
当 FfxFrameGenerationConfig 的 flags 属性中设置了 FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES 时,内插传递将在插值图像的左右边界添加彩色条。这将有助于可视化插值帧是否已呈现以及帧是否以启用撕裂的方式呈现。
当 FfxFrameGenerationConfig 的 flags 属性中设置了 FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW 时,FrameInterpolationSwapChain 将仅呈现插值帧,并执行额外的传递以将内部表面的调试数据渲染到插值帧上,以便您进行调试。