跳至内容

从 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 库之一。

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

对于放大,包含 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.