FidelityFX API 简介
FidelityFX API 是一个简单的 API,专为小的 ABI 接口和向前兼容性而设计。它以动态链接库 (DLL) 的形式提供,包含 5 个函数,声明在 ffx_api.h 中。
ffxCreateContextffxDestroyContextffxDispatchffxQueryffxConfigure
参数通过一个结构体链表提供,每个结构体都有一个包含结构体类型和指向下一个结构体指针的头。
使用 FidelityFX API 的应用程序必须使用提供的已签名 DLL 之一。可以通过 `LoadLibrary` 和 `GetProcAddress` 在运行时加载(推荐),或者通过 `.lib` 文件在应用程序启动时使用动态链接器加载。
特定于后端的功能(用于 DirectX 12 或 Vulkan)仅支持相应的 DLL。由于名称解析冲突,无法在同一个应用程序中同时链接两者。
为方便 C++ 应用程序使用,提供了用于正确初始化结构体类型和链接头文件的辅助函数。只需使用每个头的 `.hpp` 版本,并将 `ffx` 前缀替换为 `ffx::` 命名空间。请注意,包装 API 函数的辅助函数仅在链接使用 `.lib` 文件时有效。将它们与运行时加载一起使用将导致链接器错误。
描述符结构
效果功能通过描述符结构体暴露。每个结构体都有一个头
typedef struct ffxApiHeader{ ffxStructType_t type; ///< The structure type. Must always be set to the corresponding value for any structure (found nearby with a similar name). struct ffxApiHeader* pNext; ///< Pointer to next structure, used for optional parameters and extensions. Can be null.} ffxApiHeader;每个描述符都有一个关联的结构体类型,通常直接在其头文件中声明。头中的 `type` 字段必须设置为该结构体类型。否则将导致未定义的行为,并可能导致崩溃。C++ 头文件(扩展名为 `.hpp`)提供了用于自动初始化的辅助函数。
`pNext` 字段用于在链表(或“链”)中指定附加参数和扩展。某些调用需要链接特定的其他结构体。
创建上下文
通过调用 `ffxCreateContext` 来创建上下文,其声明如下:
ffxReturnCode_t ffxCreateContext(ffxContext* context, ffxCreateContextDescHeader* desc, const ffxAllocationCallbacks* memCb);在调用之前,`context` 应初始化为 `null`。请注意,第二个参数是指向结构体头的指针,而不是结构体本身。第三个参数用于自定义分配器,可以为 `null`,请参阅 内存分配 部分。
示例调用
struct ffxCreateBackendDX12Desc createBackend = /*...*/;
struct ffxCreateContextDescUpscale createUpscale = { 0 };createUpscale.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE;
// fill struct ...
createUpscale.header.pNext = &createBackend.header;
ffxContext upscaleContext = NULL;ffxReturnCode_t retCode = ffxContextCreate(&upscaleContext, &createUpscale.header, NULL);// handle errors请注意,在使用 C++ 包装器时,第三个参数的位置会提前,以支持可变数量的描述符参数。
// equivalent of above, chain of createUpscale and createBackend will be linked automatically.ffxReturnCode_t retCode = ffx::ContextCreate(upscaleContext, nullptr, createUpscale, createBackend);上下文销毁
要销毁上下文,请调用 `ffxDestroyContext`。
ffxReturnCode_t ffxDestroyContext(ffxContext* context, const ffxAllocationCallbacks* memCb);调用后,上下文将为 `null`。内存回调必须与创建上下文期间使用的分配回调兼容,请参阅 内存分配 部分。
查询
要从效果中查询信息或资源,请使用 `ffxQuery`。
ffxReturnCode_t ffxQuery(ffxContext* context, ffxQueryDescHeader* desc);除非特定查询的文档另有说明,否则上下文必须是 `ffxCreateContext` 创建的有效上下文。
输出值将通过写入查询描述符中传递的指针来返回。
配置
要配置效果,请使用 `ffxConfigure`。
ffxReturnCode_t ffxConfigure(ffxContext* context, const ffxConfigureDescHeader* desc);除非特定配置描述符的文档另有说明,否则上下文必须是 `ffxCreateContext` 创建的有效上下文。
所有效果都有一个键值配置结构体,用于简单的选项,例如:
struct ffxConfigureDescUpscaleKeyValue{ ffxConfigureDescHeader header; uint64_t key; ///< Configuration key, member of the FfxApiConfigureUpscaleKey enumeration. uint64_t u64; ///< Integer value or enum value to set. void* ptr; ///< Pointer to set or pointer to value to set.};可用的键和要传递的值的约束在相关技术的文档中指定。
调度
要分派渲染命令或其他功能,请使用 `ffxDispatch`。
ffxReturnCode_t ffxDispatch(ffxContext* context, const ffxDispatchDescHeader* desc);上下文必须是 `ffxCreateContext` 创建的有效上下文。
GPU 渲染分派会将命令编码到作为输入的命令列表/缓冲区中。
CPU 分派通常会同步并立即执行其函数。
资源结构
纹理和缓冲区等资源使用 `FfxApiResource` 结构体传递给 FidelityFX API。
对于 C++ 应用程序,后端头文件定义了用于从原生资源句柄构建它的辅助函数。
版本选择
FidelityFX API 支持在上下文创建时覆盖每个效果的版本。这是一个可选功能。如果使用版本覆盖,则 **必须** 保持一致。
- 仅使用 `ffxQuery` 在 `ffxQueryDescGetVersions` 中返回的、适用于创建结构体类型的版本 ID。
- 不要硬编码版本 ID。
- 如果调用 `ffxQuery` 时不带上下文(`NULL` 参数),请使用与 `ffxCreateContext` 相同的版本覆盖。
- 版本选择应保持默认行为(无覆盖)或由用户选择(在选项 UI 中显示)。
使用 C++ 辅助函数的版本查询示例
ffx::QueryDescGetVersions versionQuery{};versionQuery.createDescType = FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE;versionQuery.device = GetDX12Device(); // only for DirectX 12 applicationsuint64_t versionCount = 0;versionQuery.outputCount = &versionCount;// get number of versions for allocationffxQuery(nullptr, &versionQuery.header);
std::vector<const char*> versionNames;std::vector<uint64_t> versionIds;m_FsrVersionIds.resize(versionCount);versionNames.resize(versionCount);versionQuery.versionIds = versionIds.data();versionQuery.versionNames = versionNames.data();// fill version ids and names arrays.ffxQuery(nullptr, &versionQuery.header);错误处理
对 FidelityFX API 的所有调用都返回 `ffxReturnCode_t` 类型的值。如果使用 C++ 包装器,则会替换为 `ffx::ReturnCode`。
成功的操作将返回 `FFX_API_RETURN_OK`。所有其他返回码均为错误。未来版本可能会添加当前不在头文件中的新返回码。
应用程序应能够优雅地处理错误,即使是无法恢复的错误。
内存分配
要控制内存分配,请将 `ffxAllocationCallbacks` 的指针传递给 `ffxCreateContext` 和 `ffxDestroyContext`。
如果传递空指针,则将使用全局 `malloc` 和 `free`。
对于自定义分配器,需要两个函数:
// Memory allocation function. Must return a valid pointer to at least size bytes of memory aligned to hold any type.// May return null to indicate failure. Standard library malloc fulfills this requirement.typedef void* (*ffxAlloc)(void* pUserData, uint64_t size);
// Memory deallocation function. May be called with null pointer as second argument.typedef void (*ffxDealloc)(void* pUserData, void* pMem);
typedef struct ffxAllocationCallbacks{ void* pUserData; ffxAlloc alloc; ffxDealloc dealloc;} ffxAllocationCallbacks;`pUserData` 将被无修改或验证地传递给回调。FidelityFX API 代码不会尝试解引用它,也不会存储它。
如果为上下文创建使用了自定义分配器,则必须为销毁使用兼容的结构体。这意味着在创建上下文期间使用回调和用户数据分配的任何指针,都必须能够使用传递给 `ffxDestroyContext` 的回调和用户数据进行释放。