跳至内容

从 FSR 3.0 迁移到 FSR 3.1

FSR 3.1 的新 API 在几个方面改变了应用程序与 FSR 的交互方式

  • 上采样和帧生成已分离。
  • 不再支持自定义后端。
  • 后端与效果上下文一起创建,其生命周期绑定在一起。
  • 所有调用都使用 ABI 稳定的结构,支持未来的扩展。

有关新 API 的更详细信息,请参阅 FidelityFX API 简介

API 设置

将您的构建系统设置为包含 ffx-api/include 中的头文件,并链接到 amd_fidelityfx_dx12 或 amd_fidelityfx_vk 库之一。

在源文件中,包含 C API 的 ffx_api/ffx_api.h 或 C++ 便利工具的 ffx_api/ffx_api.hpp

对于上采样,包含 ffx_api/ffx_fsr_upscale.h(或 .hpp),对于帧生成,包含 ffx_api/ffx_fg.h(或 .hpp)。

对于后端创建和帧生成交换链,您还需要 ffx_api/dx12/ffx_api_dx12.hffx_api/vk/ffx_api_vk.h(或 .hpp)之一。

创建上下文

不要调用 ffxFsr3ContextCreate,而是调用 ffxCreateContext

ffxCreateContextDescFsrUpscale 接受 FfxFsr3ContextDescription 的一部分参数,不同之处在于标志现在以 FFX_FSR_ 开头,而不是 FFX_FSR3_

必须在 ffxCreateContextDescFsrUpscaleheaderpNext 字段中传递后端创建描述。这可以是 ffxCreateBackendDX12DescffxCreateBackendVKDesc

每个结构体的 header 上的 type 字段必须设置为关联的类型 ID。在 C 头文件中,这些与其关联的类型相邻。在使用 C++ 命名空间类型时,结构体类型由构造函数初始化。

对于帧生成,必须单独创建一个上下文,以及一个用于帧生成交换链(特定于后端)的上下文。

对于内存分配,可以传递一组回调。如果设置为 NULL,则使用系统 mallocfree

查询 FSR 信息

ffxFsr3GetUpscaleRatioFromQualityModeffxFsr3GetRenderResolutionFromQualityModeffxFsr3GetJitterPhaseCountffxFsr3GetJitterOffset 函数被替换为传递给 ffxQuery 函数的结构体。这些查询函数中的指针参数在新 API 中是结构体成员。

配置 FSR

ffxFsr3ConfigureFrameGenerationffxConfigure 函数替换,并使用帧生成上下文。配置结构体几乎相同。添加了一个新的可选回调上下文。有关详细信息,请参阅比较表。

调度 FSR

所有调度都使用 ffxDispatch 函数完成。

资源通过新的 FfxApiResource 结构体传递,该结构体与 FfxResource 非常相似,但具有更好的平台稳定性。对于 DirectX,可以使用辅助函数 ffxApiGetResourceDX12 来填充资源描述。

使用帧生成时,每帧都必须调用新的准备调度。这可以放在与上采样调度相同的位置,并接受上采样资源的子集。

对比

以下部分显示了 FSR 3.0 代码模式及其 FSR 3.1 等效项。

上下文名称

FSR 3.0

FfxFsr3Context fsr3Context;

FSR 3.1 / FFX API C

ffxContext upscalingContext, framegenContext;

FFX API C++

ffx::Context upscalingContext, framegenContext;

上下文创建(仅限上采样)

FSR 3.0

FfxFsr3ContextDescription fsr3ContextDesc = {0};
// create backend interface ...
// fill fsr3ContextDesc ...
fsr3ContextDesc.flags |= FFX_FSR3_ENABLE_UPSCALING_ONLY;
ffxFsr3ContextCreate(&fsr3Context, &fsr3ContextDesc);

FSR 3.1 / FFX API C

ffxCreateContextDescFsrUpscale fsrContextDesc = {0};
fsrContextDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_FSR_UPSCALE;
// fill fsrContextDesc ...
// backend interface desc ...
fsrContextDesc.header.pNext = &backendDesc.header;
ffxCreateContext(&upscalingContext, &fsrContextDesc.header, NULL);

FFX API C++

ffx::CreateContextDescFsrUpscale fsrContextDesc{};
// fill fsrContextDesc ...
// backend interface desc ...
ffx::CreateContext(&upscalingContext, nullptr, fsrContextDesc, backendDesc);

DX12 后端创建

FSR 3.0

FfxFsr3ContextDescription fsr3ContextDesc = {0};
// create backend interface (DX12)
size_t scratchBufferSize = ffxGetScratchMemorySizeDX12(1);
void* scratchBuffer = malloc(scrathBufferSize);
memset(scratchBuffer, 0, scrathBufferSize);
errorCode = ffxGetInterfaceDX12(&fsr3ContextDesc.backendInterfaceUpscaling, ffxGetDeviceDX12(dx12Device), scratchBuffer, scratchBufferSize, 1);
assert(errorCode == FFX_OK);

FSR 3.1 / FFX API C

ffxCreateContextDescFsrUpscale fsrContextDesc = {0};
// fill fsrContextDesc ...
// backend interface desc (dx12)
ffxCreateBackendDX12Desc backendDesc = {0};
backendDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_BACKEND_DX12;
backendDesc.device = dx12Device;
fsrContextDesc.header.pNext = &backendDesc.header;
// create context and backend
ffxCreateContext(&upscalingContext, &fsrContextDesc.header, NULL);

FFX API C++

ffx::CreateContextDescFsrUpscale fsrContextDesc{};
// fill fsrContextDesc ...
// backend interface desc (dx12)
ffx::CreateBackendDX12Desc backendDesc{};
backendDesc.device = dx12Device;
ffx::CreateContext(&upscalingContext, nullptr, fsrContextDesc, backendDesc);

上下文创建(上采样 + 帧生成)

FSR 3.0

FfxFsr3ContextDescription fsr3ContextDesc = {0};
// create backend interface (x3) ...
// fill fsr3ContextDesc ...
ffxFsr3ContextCreate(&fsr3Context, &fsr3ContextDesc);

FSR 3.1 / FFX API C

ffxCreateContextDescFsrUpscale fsrContextDesc = {0};
fsrContextDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_FSR_UPSCALE;
// fill fsrContextDesc ...
// backend interface desc ...
fsrContextDesc.header.pNext = &backendDesc.header;
ffxCreateContext(&upscalingContext, &fsrContextDesc.header, NULL);
ffxCreateContextDescFsrFrameGeneneration fgContextDesc = {0};
// fill fgContextDesc ...
// backend interface desc ...
fgContextDesc.header.pNext = &backendDesc.header;
ffxCreateContext(&frameGenContext, &fgContextDesc.header, NULL);

FFX API C++

ffx::CreateContextDescFsrUpscale fsrContextDesc{};
// fill fsrContextDesc ...
// backend interface desc ...
ffx::CreateContext(&upscalingContext, nullptr, fsrContextDesc, backendDesc);
ffx::CreateContextDescFsrFrameGen fgContextDesc{};
// fill fgContextDesc ...
// backend interface desc ...
ffx::CreateContext(&frameGenContext, nullptr, fgContextDesc, backendDesc);

查询上采样比例 / 渲染分辨率

FSR 3.0

float upscaleRatio = ffxFsr3GetUpscaleRatioFromQualityMode(FFX_FSR3_QUALITY_MODE_BALANCED);
<!-- -->
uint32_t renderWidth, renderHeight;
ffxFsr3GetRenderResolutionFromQualityMode(&renderWidth, &renderHeight, displayWidth, displayHeight, FFX_FSR3_QUALITY_MODE_BALANCED);

FSR 3.1 / FFX API C

float upscaleRatio;
struct ffxQueryDescFsrGetUpscaleRatioFromQualityMode queryDesc1 = {0};
queryDesc1.header.type = FFX_API_QUERY_DESC_TYPE_FSR_GETUPSCALERATIOFROMQUALITYMODE;
queryDesc1.qualityMode = FFX_FSR_QUALITY_MODE_BALANCED;
queryDesc1.pOutUpscaleRatio = &upscaleRatio;
ffxQuery(&fsrContext, &queryDesc1.header);
<!-- -->
uint32_t renderWidth, renderHeight;
struct ffxQueryDescFsrGetRenderResolutionFromQualityMode queryDesc2 = {0};
queryDesc2.header.type = FFX_API_QUERY_DESC_TYPE_FSR_GETRENDERRESOLUTIONFROMQUALITYMODE;
queryDesc2.displayWidth = displayWidth;
queryDesc2.displayHeight = displayHeight;
queryDesc2.qualityMode = FFX_FSR_QUALITY_MODE_BALANCED;
queryDesc2.pOutRenderWidth = &renderWidth;
queryDesc2.pOutRenderHeight = &renderHeight;
ffxQuery(&fsrContext, &queryDesc2.header);

FFX API C++

float upscaleRatio;
ffx::QueryDescFsrGetUpscaleRatioFromQualityMode queryDesc1{};
queryDesc1.qualityMode = FFX_FSR_QUALITY_MODE_BALANCED;
queryDesc1.pOutUpscaleRatio = &upscaleRatio;
ffx::Query(fsrContext, queryDesc1);
<!-- -->
uint32_t renderWidth, renderHeight;
ffx::QueryDescFsrGetRenderResolutionFromQualityMode queryDesc2{};
queryDesc2.displayWidth = displayWidth;
queryDesc2.displayHeight = displayHeight;
queryDesc2.qualityMode = FFX_FSR_QUALITY_MODE_BALANCED;
queryDesc2.pOutRenderWidth = &renderWidth;
queryDesc2.pOutRenderHeight = &renderHeight;
ffx::Query(fsrContext, queryDesc2);

查询抖动计数 / 偏移量

FSR 3.0

int32_t jitterCount = ffxFsr3GetJitterPhaseCount(renderWidth, displayWidth);
<!-- -->
float jitterX, jitterY;
ffxFsr3GetJitterOffset(&jitterX, &jitterY, jitterIndex, jitterCount);

FSR 3.1 / FFX API C

int32_t jitterCount;
struct ffxQueryDescFsrGetJitterPhaseCount queryDesc1 = {0};
queryDesc1.header.type = FFX_API_QUERY_DESC_TYPE_FSR_GETJITTERPHASECOUNT;
queryDesc1.renderWidth = renderWidth;
queryDesc1.displayWidth = displayWidth;
queryDesc1.pOutPhaseCount = &jitterCount;
ffxQuery(&fsrContext, &queryDesc1.header);
<!-- -->
float jitterX, jitterY;
struct ffxQueryDescFsrGetJitterOffset queryDesc2 = {0};
queryDesc2.header.type = FFX_API_QUERY_DESC_TYPE_FSR_GETJITTEROFFSET;
queryDesc2.index = jitterIndex;
queryDesc2.phaseCount = jitterCount;
queryDesc2.pOutX = &jitterX;
queryDesc2.pOutY = &jitterY;
ffxQuery(&fsrContext, &queryDesc2.header);

FFX API C++

int32_t jitterCount;
ffx::QueryDescFsrGetJitterPhaseCount queryDesc1{};
queryDesc1.renderWidth = renderWidth;
queryDesc1.displayWidth = displayWidth;
queryDesc1.pOutPhaseCount = &jitterCount;
ffx::Query(fsrContext, queryDesc1);
<!-- -->
float jitterX, jitterY;
ffxQueryDescFsrGetJitterOffset queryDesc2{};
queryDesc2.index = jitterIndex;
queryDesc2.phaseCount = jitterCount;
queryDesc2.pOutX = &jitterX;
queryDesc2.pOutY = &jitterY;
ffx::Query(fsrContext, queryDesc2);

配置帧生成

FSR 3.0

FfxFrameGenerationConfig config = {0};
// fill config ...
ffxFsr3ConfigureFrameGeneration(&fsr3Context, &config);

FSR 3.1 / FFX API C

struct ffxConfigureDescFrameGeneration config = {0};
config.header.type = FFX_API_CONFIGURE_DESC_TYPE_FRAMEGENERATION;
// fill config ...
ffxConfigure(&fsrContext, &config);

FFX API C++

ffx::ConfigureDescFrameGeneration config{};
// fill config ...
ffxConfigure(fsrContext, config);

呈现回调

FSR 3.0

FfxErrorCode myPresentCallback(const FfxPresentCallbackDescription* params, void* userCtx) // note: pre-3.1 does not have user context pointer
{
// pre-presentation work, e.g. UI
return FFX_OK;
}
<!-- -->
// ...
FfxFrameGenerationConfig config;
config.presentCallback = myPresentCallback;
config.presentCallbackContext = &myEngineContext;

FSR 3.1 / FFX API C

ffxReturnCode_t myPresentCallback(struct ffxCallbackDescFrameGenerationPresent* params, void* pUserCtx)
{
// pre-presentation work, e.g. UI
return FFX_API_RETURN_OK;
}
<!-- -->
// ...
struct ffxConfigureDescFrameGeneration config;
config.presentCallback = myPresentCallback;
config.presentCallbackUserContext = &myEngineContext;

FFX API C++

extern "C" ffxReturnCode_t myPresentCallback(ffxCallbackDescFrameGenerationPresent* params, void* pUserCtx)
{
// pre-presentation work, e.g. UI
return FFX_API_RETURN_OK;
}
<!-- -->
// ...
ffx::ConfigureDescFrameGeneration config;
config.presentCallback = myPresentCallback;
config.presentCallbackUserContext = &myEngineContext;

调度上采样(无 FG)

FSR 3.0

// (context created with UPSCALING_ONLY flag)
FfxFsr3DispatchUpscaleDescription params = {0};
// fill params ...
ffxFsr3ContextDispatchUpscale(&fsr3Context, &params);

FSR 3.1 / FFX API C

struct ffxDispatchDescFsrUpscale params = {0};
params.header.type = FFX_API_DISPATCH_DESC_TYPE_FSR_UPSCALE;
// fill params ...
ffxDispatch(&fsrContext, &params);

FFX API C++

ffx::DispatchDescFsrUpscale params{};
// fill params ...
ffx::Dispatch(fsrContext, params);

调度上采样和 FG 准备

FSR 3.0

// dispatch upscaling and prepare resources for frame generation
FfxFsr3DispatchUpscaleDescription params = {0};
// fill params ...
ffxFsr3ContextDispatchUpscale(&fsr3Context, &params);

FSR 3.1 / FFX API C

struct ffxDispatchDescFsrUpscale upscaleParams = {0};
upscaleParams.header.type = FFX_API_DISPATCH_DESC_TYPE_FSR_UPSCALE;
struct ffxDispatchDescFrameGenerationPrepare frameGenParams = {0};
frameGenParams.header.type = FFX_API_DISPATCH_DESC_TYPE_FRAMEGENERATION_PREPARE;
// fill both structs with params ...
ffxDispatch(&fsrContext, &upscaleParams);
ffxDispatch(&fgContext, &frameGenParams);

FFX API C++

ffx::DispatchDescFsrUpscale upscaleParams{};
ffx::DispatchDescFrameGenerationPrepare frameGenParams{};
// fill both structs with params ...
ffx::Dispatch(fsrContext, upscaleParams);
ffx::Dispatch(fgContext, frameGenParams);

调度帧生成(无回调模式)

FSR 3.0

FfxFrameGenerationDispatchDescription fgDesc = {0};
ffxGetFrameinterpolationCommandlistDX12(ffxSwapChain, fgDesc.commandList);
fgDesc.outputs[0] = ffxGetFrameinterpolationTextureDX12(ffxSwapChain);
// other parameters ...
ffxFsr3DispatchFrameGeneration(&fgDesc);

FSR 3.1 / FFX API C

struct ffxDispatchDescFrameGeneration dispatchFg = {0};
dispatchFg.header.type = FFX_API_DISPATCH_DESC_TYPE_FRAMEGENERATION;
<!-- -->
struct ffxQueryDescFrameGenerationSwapChainInterpolationCommandListDX12 queryCmdList = {0};
queryCmdList.header.type = FFX_API_QUERY_DESC_TYPE_FRAMEGENERATIONSWAPCHAIN_INTERPOLATIONCOMMANDLIST_DX12;
queryCmdList.pOutCommandList = &dispatchFg.commandList;
ffxQuery(&swapChainContext, &queryCmdList);
<!-- -->
struct ffxQueryDescFrameGenerationSwapChainInterpolationTextureDX12 queryFiTexture{};
queryFiTexture.header.type = FFX_API_QUERY_DESC_TYPE_FRAMEGENERATIONSWAPCHAIN_INTERPOLATIONTEXTURE_DX12;
queryFiTexture.pOutTexture = &dispatchFg.outputs[0];
ffxQuery(&swapChainContext, &queryFiTexture);
<!-- -->
// other parameters ...
ffxDispatch(&fgContext, &dispatchFg);

FFX API C++

ffx::DispatchDescFrameGeneration dispatchFg{};
<!-- -->
ffx::QueryDescFrameGenerationSwapChainInterpolationCommandListDX12 queryCmdList{};
queryCmdList.pOutCommandList = &dispatchFg.commandList;
ffx::Query(swapChainContext, queryCmdList);
<!-- -->
ffx::QueryDescFrameGenerationSwapChainInterpolationTextureDX12 queryFiTexture{};
queryFiTexture.pOutTexture = &dispatchFg.outputs[0];
ffx::Query(swapChainContext, queryFiTexture);
<!-- -->
// other parameters ...
ffx::Dispatch(fgContext, dispatchFg);

销毁上下文和后端

FSR 3.0

ffxFsr3ContextDestroy(&fsr3Context);
// for each backend interface:
free(backendInterface.scratchBuffer);

FSR 3.1 / FFX API C

ffxDestroyContext(&fsrContext, NULL);

FFX API C++

ffx::DestroyContext(fsrContext, nullptr);
© . This site is unofficial and not affiliated with AMD.