Microsoft® DirectSR 与 AMD FidelityFX™ 超分辨率技术

最初发布时间:
最后更新时间:
Jarrett Wendt's avatar
Jarrett Wendt

开发者概述

在过去的几年里,超分辨率技术已成为大多数游戏的一项必备功能。AMD FidelityFX Super Resolution 1 的第一个版本于 2021 年发布,随后几年推出了 FSR 2 和 FSR 3。每一次迭代都改进了该技术,为全球玩家提供了更多、更高质量的像素。当然,现代游戏开发意味着要考虑游戏所处的生态系统并与之协同工作。对于 PC 游戏来说,现实情况是包含多种超分辨率技术。对开发人员而言,这意味着要在游戏引擎中集成多种 API,并进行相关的验证工作。

随着 Microsoft 的 DirectSR 的推出(参见 Microsoft 的博客),集成多种超分辨率 API 的需求已大大降低。相反,开发人员只需集成一个 API——Microsoft DirectSR——即可枚举 DirectSR 本身以及特定适配器(及其驱动程序堆栈)支持的所有超分辨率技术,从而轻松地将这些选项提供给最终用户。

要使用 DirectSR,应用程序会通过 DirectSR API 枚举可用的超分辨率变体,这有点像应用程序使用 DXGI 枚举显示器或显示适配器一样。通过超分辨率变体列表,应用程序可以通过提供所需的变体来创建一个超分辨率引擎。通过 DirectSR 公开的一些技术——例如 AMD FidelityFX Super Resolution 2.2——可能只公开一个变体。有了引擎,应用程序就可以创建一个 upscaler,调用每帧 API 入口点,将超分辨率工作负载分派到所需的应用程序队列。

值得详细讨论一下应用程序队列,因为它标志着与标准 AMD FidelityFX SDK 超分辨率入口点的不同,后者直接记录到 DirectX®12 命令列表。选择队列而不是命令列表,允许更广泛的设备为 DirectSR 和应用程序提供超分辨率引擎,包括非 GPU 设备。这种额外的灵活性意味着,对于其设计中渲染工作和同步图元提交到 GPU 的地方单一的游戏引擎来说,集成 DirectSR 可能会更具挑战性。有了 DirectSR,游戏引擎中的那个位置将需要进行修改,以包含对 DirectSR 每帧入口点的调用,并与引擎对 GPU 的正常工作提交视图同步。

DirectSR driver stack

AMD 的 DirectSR 实现是通过直接集成到运行时中完成的。这与其他超分辨率引擎使用的基于驱动程序的元命令实现略有不同。通过在运行时级别实现,AMD 能够将其行业领先的广泛支持(由 FSR 2 提供)带给几乎所有 DirectSR 用户。这意味着更多的玩家可以从尖端的超分辨率技术中受益。

// Create an IDSRDevice to allow us to enumerate available SR variants.
ID3D12DSRDeviceFactory* dsrDeviceFactory;
D3D12GetInterface(CLSID_D3D12DSRDeviceFactory, IID_PPV_ARGS(&dsrDeviceFactory));
IDSRDevice* dsrDevice;
dsrDeviceFactory->CreateDSRDevice(d3d12Device, 1, IID_PPV_ARGS(&dsrDevice));

在对 DirectSR 有了高层概述后,现在让我们将重点转向 DirectSR API 的一些具体细节,看看如何将 DirectSR 集成到您的应用程序中。让我们从创建 DirectSR 设备开始,正如您在上面的代码片段中所见。这是使 DirectSR upscaler 运行的第一步。有了设备,我们就可以枚举目标机器上可用的 DirectSR 变体。

// Enumerate all super resolution variants available on the device.
const UINT dsrVariantCount = dsrDevice->GetNumSuperResVariants();
for (UINT currentVariantIndex = 0; currentVariantIndex < dsrVariantCount; currentVariantIndex++)
{
DSR_SUPERRES_VARIANT_DESC variantDesc;
dsrDevice->GetSuperResVariantDesc(currentVariantIndex, &variantDesc);
// Use the variant desc as we see fit...
}

上面的循环正在从设备中检索包含每个变体描述的结构。在 DirectSR 的术语中,变体是指一种特定的超分辨率技术,例如:AMD FidelityFX Super Resolution 2.2 在这种命名法中就是一个变体。下一步是为我们想要使用的变体创建一个 DirectSR 引擎。接下来我们将这样做。

// Create a DirectSR engine for the desired variant.
DSR_SUPERRES_CREATE_ENGINE_PARAMETERS createParams
{
.VariantId = ChosenVariantId,
.TargetFormat = DXGI_FORMAT_R10G10B10A2_UNORM,
.SourceColorFormat = DXGI_FORMAT_R10G10B10A2_UNORM,
.SourceDepthFormat = DXGI_FORMAT_R32_FLOAT,
.Flags = DSR_SUPERRES_CREATE_ENGINE_FLAG_ALLOW_DRS,
.MaxSourceSize = CreateParams.TargetSize,
.TargetSize = DSR_SIZE{ targetResX, targetResY },
};
IDSRSuperResEngine* dsrEngine;
dsrDevice->CreateSuperResEngine(&createParams, IID_PPV_ARGS(&dsrEngine));
// Create super resolution upscaler object to use each frame.
IDSRSuperResUpscaler* dsrUpscaler;
dsrEngine->CreateUpscaler(commandQueue, IID_PPV_ARGS(&dsrUpscaler));

`CreateUpscaler()` 方法的一个重要方面是它接受一个 `commandQueue` 参数。这意味着 DirectSR 引擎与特定的队列绑定。API 的其余部分不与 DirectX®12 的其他命令相关结构或对象交互,这意味着当 DirectSR 执行 upscaling 时,DirectSR 运行时将直接向您在引擎创建期间指定的命令队列提交工作。现在,我们可以继续看如何使用我们从 DirectSR 引擎创建的 DirectSR upscaler 对象,以及我们将如何从帧到帧地与之交互。

DSR_SUPERRES_UPSCALER_EXECUTE_PARAMETERS params{ /* see the next code snippet */ };
DSR_SUPERRES_UPSCALER_EXECUTE_FLAGS executeFlags =
jumpCutOccurred ? DSR_SUPERRES_UPSCALER_EXECUTE_FLAG_RESET_HISTORY
: DSR_SUPERRES_UPSCALER_EXECUTE_FLAG_NONE;
dsrUpscaler->Execute(&params, frameDeltaInSeconds, executeFlags);

与 DirectSR upscaler 交互非常直接,只需要三件事。第一是执行参数,我们将在下一节中更详细地探讨。第二是帧差,这告诉 DirectSR upscalers 自上次 upscaling 以来经过的时间。最后,我们有执行标志,它们会告诉 DirectSR upscalers 重要事件,例如相机执行了跳跃剪切,这完全使所有之前的历史信息失效。我们在上面的代码片段中略过了执行参数,现在让我们更深入地研究一下这个结构,看看我们需要从应用程序中将哪些数据流输入到 DirectSR upscaler 中。

DSR_SUPERRES_UPSCALER_EXECUTE_PARAMETERS params
{
.pTargetTexture = target,
.TargetRegion = D3D12_RECT{ 0, 0, targetResX, targetResY },
.pSourceColorTexture = pSourceColor,
.SourceColorRegion = D3D12_RECT{ 0, 0, sourceResX, sourceResY },
.pSourceDepthTexture = sourceDepth,
.SourceDepthRegion = D3D12_RECT{ 0, 0, sourceResX, sourceResY },
.pMotionVectorsTexture = motionVectors,
.MotionVectorsRegion = D3D12_RECT{ 0, 0, sourceResX, sourceResY },
.MotionVectorScale = DSR_FLOAT2{ 1.f, 1.f },
.CameraJitter = DSR_FLOAT2{ cameraJitterX, cameraJitterY },
.ExposureScale = 1.f,
.PreExposure = 1.f,
.Sharpness = 1.f,
.CameraNear = 0.f,
.CameraFar = INFINITY,
.CameraFovAngleVert = 1.f,
.pExposureScaleTexture = nullptr,
.pIgnoreHistoryMaskTexture = nullptr,
.IgnoreHistoryMaskRegion = D3D12_RECT{ 0, 0, sourceResX, sourceResY },
.pReactiveMaskTexture = reactiveMask,
.ReactiveMaskRegion = D3D12_RECT{ 0, 0, sourceResX, sourceResY },
};

在我们向 DirectSR 传递这些数据之前,我们——作为应用程序开发人员——需要确保所有这些输入都可用。这意味着生成它们的 GPU 工作负载已经提交给 GPU,然后才能调用超分辨率引擎上的 `Execute()` 方法。这最重要的是包括应用程序在其源分辨率下生成的颜色纹理、深度纹理和运动矢量。这些通常由应用程序在其主要的渲染和着色阶段生成。

目标纹理参数应包含一个大小适当的资源,以包含运行 DirectSR upscaler 的 upscaled 结果。其他数值参数应该相对不言自明,包括相机抖动、曝光比例和 HDR 输入信号的预曝光、相机近景、远景和垂直视场角,以及一个锐度因子,包括 upscaling 引擎应对 upscaled 结果执行的额外锐化量。最后两个纹理输入——忽略历史掩码和响应掩码——被标记为可选,但对于那些寻求实现最高 upscaling 质量的开发人员来说非常重要,因此需要稍作解释。

与 AMD FidelityFX Super Resolution 2.2 一样,我们强烈建议应用程序开发人员为 DirectSR 实现提供可选的元数据。在 DirectSR 的术语中,这意味着应用程序需要填充并提供“忽略历史掩码”和“响应掩码”,以及颜色、深度和运动矢量表面。这些额外的元数据表面分别对应于 FidelityFX Super Resolution 2.2 的“透明度和合成掩码”和“响应掩码”。

DirectSR inputs and outputs

为了填充这些掩码,了解它们应该包含什么很有帮助。让我们先从响应掩码开始。术语“响应性”是指当前帧渲染的样本对最终 upscaled 图像的生成有多大的影响。通常,当前帧渲染的样本对 FSR 2 计算结果的贡献相对适中;但是,也有例外。为了对快速移动的、alpha 混合的物体产生最佳结果,FSR 2 需要其算法的某个阶段对这些像素更加响应。由于无法从颜色、深度或运动矢量中确定哪些像素是使用 alpha 混合渲染的,因此当应用程序显式标记这些区域时,FSR 2 的效果最好。因此,强烈建议应用程序为 FSR 2 提供响应掩码。

响应掩码指导 FSR 2 在合成当前像素时应减少对历史信息的依赖程度,而是让当前帧的样本对结果贡献更多。响应掩码允许应用程序提供一个介于 [0..1] 之间的值,其中 0 表示像素完全不响应(并应使用默认的 FSR 2 合成策略),而 1.0 表示像素应完全响应。这是一个浮点范围,可以根据不同的情况进行调整。

虽然响应掩码还有其他用途,但其主要用途是为包含 alpha 混合对象的 upscaling 图像产生更好的结果。响应性的一个很好的代理是 alpha 混合对象合成到场景中时使用的 alpha 值,因此,应用程序应该将 alpha 值写入响应掩码。将响应性设置为 alpha 值只是开始,为了获得最佳结果,您的实现可能需要进一步定制该值。有关填充响应掩码的更多详细信息,请参阅 FSR 2 文档。接近 1 的响应值不太可能产生好的结果。因此,我们建议将最大响应值限制在 0.9 左右。

除了响应掩码之外,FSR 2 还允许应用程序标示在 upscaling 过程中需要考虑的其他专业渲染区域。例如,这些专业渲染包括光线追踪反射区域或动画纹理。虽然响应掩码调整累积平衡,但忽略历史掩码调整像素历史保护机制。该掩码还消除了亮度不稳定因素的影响。忽略历史掩码中值为 0 的像素不会对该像素的锁定进行任何额外修改。反之,值为 1 表示该像素的锁定应完全移除。


我们希望这篇博文对您理解 DirectSR 以及 AMD FidelityFX Super Resolution 2.2 如何在其内部托管有所帮助且引人入胜。要成功地将 upscaler 集成到应用程序中,还有很多内容需要探索。AMD FidelityFX Super Resolution 2 提供了大量文档,解释了 upscaler API 核心之外的所有集成注意事项。这些主题包括 mipmap 偏差、相机抖动、upscaler 在帧中的位置、如何构建运动矢量纹理等等。您可以在此处找到 AMD FSR 2 文档。

AMD 的 DirectSR 实现使用 AMD FidelityFX SDK 中的 AMD FSR 2.2 API。如果您想了解 AMD FidelityFX SDK,可以在此处阅读更多内容。如果您也对帧生成技术和超分辨率 upscaling 感兴趣,您可以查阅AMD FidelityFX SDK,了解有关AMD FidelityFX Super Resolution 3.0 技术及其生成新帧的能力的更多详细信息。

Jarrett Wendt's avatar

Jarrett Wendt

Jarrett Wendt 是 AMD DirectSR 支持的首席开发人员,隶属于 Adrenalin 软件团队。他拥有佛罗里达互动娱乐学院的理学硕士学位。

相关新闻和技术文章

相关视频

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