ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

dlssg-to-fsr3 中的 FidelityFX API 详解:五个核心函数、描述符链与内存分配机制

dlssg-to-fsr3 中的 FidelityFX API 详解:五个核心函数、描述符链与内存分配机制 图形学游戏开发【免费下载链接】dlssg-to-fsr3Adds AMD FSR 3 Frame Generation to games by replacing Nvidia DLSS Frame Generation (nvngx_dlssg).项目地址https://gitcode.com/gh_mirrors/dl/dlssg-to-fsr3点击查看免费下载FidelityFX API 是 AMD FidelityFX SDK 对外暴露的轻量级调用接口整个 SDK 的功能最终都收敛为ffxCreateContext、ffxDestroyContext、ffxDispatch、ffxQuery、ffxConfigure这五个导出函数。本篇以 FidelityFX-SDK 官方入门文档 为骨架结合本仓库内 ffx-api 目录下的头文件与源码实现系统讲解这五个函数的签名、描述符链表Descriptor Chain约定、C/C 两套封装的使用差异、版本覆盖机制与自定义内存分配器帮助读者在集成 FSR 3 帧生成等效果时正确调用该 API。FidelityFX API 在 dlssg-to-fsr3 项目中的角色本项目 dlssg-to-fsr3 的核心思路是在不支持 DLSS 帧生成的 RTX 显卡上用 AMD FSR 3 帧生成替换 Nvidia DLSS-G 帧生成。整个替换链路以动态链接库形式交付source/maindll生成替换用的nvngx.dll其底层调用的正是 FidelityFX SDK 提供的amd_fidelityfx_dx12.dll/amd_fidelityfx_vk.dll见 dependencies/FidelityFX-SDK/PrebuiltSignedDLL。而所有对 FSR 3 帧生成、超分辨率等效果的调用都必须经由本片文档所讲解的 FidelityFX API 五个导出函数完成。因此理解这套 API 的约定是理解项目如何驱动 FSR 3 的前提。API 总体设计极小 ABI 面与向前兼容FidelityFX API 被设计为极小 ABI 面small ABI surface以动态链接库形式交付对外只暴露 5 个函数全部声明在 ffx_api.h 中ffxCreateContext—— 创建效果上下文ffxDestroyContext—— 销毁效果上下文ffxDispatch—— 派发渲染或计算任务ffxQuery—— 查询效果信息与资源ffxConfigure—— 配置效果选项所有参数都以结构体链表方式传入每个结构体首部都包含一个ffxApiHeader头头内保存结构体类型type和指向下一个结构体的指针pNext。这种设计让 API 无需每次增加参数就破坏 ABI新参数通过新增结构体类型即可向前兼容地扩展。DLL 加载方式使用该 API 的应用必须加载官方签名 DLL。文档推荐两种方式运行时动态加载推荐使用LoadLibraryGetProcAddress按函数名解析地址启动时静态链接通过.lib文件交给动态链接器在应用启动时完成绑定。仓库中 ffx_api_loader.h 提供了现成的运行时加载辅助它定义ffxFunctions结构体其中的ffxLoadFunctions函数会通过GetProcAddress一次性把五个函数指针装入该结构体应用只需持有这份函数表即可调用无需逐个手写GetProcAddress。需要特别注意的是后端互斥DirectX 12 后端与 Vulkan 后端功能只由各自对应的 DLL 支持同一应用内不能同时链接两个后端因为符号名解析会发生冲突。选择 DX12 后端时用amd_fidelityfx_dx12.dllVulkan 后端时用amd_fidelityfx_vk.dll。C 封装的便利与限制为方便 C 应用SDK 同时提供.hpp版本的每个头文件如 ffx_api.hpp其中把ffx前缀替换为ffx::命名空间并提供结构体自动初始化辅助InitHelper、LinkHeaders等。但必须注意C 辅助函数仅在通过.lib静态链接时有效如果使用运行时加载LoadLibrary/GetProcAddress调用这些辅助函数会产生链接错误。描述符结构体Descriptor structs效果的创建、配置、查询、派发都通过描述符结构体完成。每个结构体的头部统一为typedef struct ffxApiHeader { ffxStructType_t type; /// 结构体类型。必须始终设置为与该结构体对应的枚举值。 struct ffxApiHeader* pNext; /// 指向下一个结构体的指针用于可选参数与扩展。可以为 null。 } ffxApiHeader;在 ffx_api.h 中可以看到ffxCreateContextDescHeader、ffxConfigureDescHeader、ffxQueryDescHeader、ffxDispatchDescHeader全部是ffxApiHeader的类型别名——这意味着四种调用共享同一种链式传参机制。关键约定每个描述符结构体都有对应的结构体类型枚举值通常紧邻结构体声明定义在头文件中例如FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE、FFX_API_CONFIGURE_DESC_TYPE_GLOBALDEBUG1等type字段必须设置为该结构体对应的类型设置错误属于未定义行为很可能直接导致崩溃C 的.hpp头通过InitHelper模板在构造函数中自动填充header.type与header.pNext因此推荐 C 应用直接使用.hpp提供的辅助类型pNext用于以链表chain形式追加可选参数和扩展结构体某些调用强制要求链入特定结构体例如创建效果上下文时必须链入后端描述符。在 ffx_api.hpp 中可以看到LinkHeaders的实现它以变参模板递归地把各描述符的header.pNext依次指向下一个描述符的header最后一个描述符的pNext置为nullptr返回链表头指针。这也是文档中使用 C 封装时链会自动连接的实现基础。上下文创建ffxCreateContext上下文创建是使用任何效果的第一步声明如下ffxReturnCode_t ffxCreateContext(ffxContext* context, ffxCreateContextDescHeader* desc, const ffxAllocationCallbacks* memCb);调用前context应初始化为null。注意第二个参数是指向结构体头header的指针而非结构体本身。第三个参数用于自定义分配器可为nullnull 时使用系统malloc/free详见后文内存分配一节。典型调用C 风格struct ffxCreateBackendDX12Desc createBackend /*...*/; struct ffxCreateContextDescUpscale createUpscale { 0 }; createUpscale.header.type FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE; // 填充 createUpscale 其余字段 ... createUpscale.header.pNext createBackend.header; ffxContext upscaleContext NULL; ffxReturnCode_t retCode ffxContextCreate(upscaleContext, createUpscale.header, NULL); // 处理错误从 ffx_api_dx12.h 可以印证后端的描述符结构ffxCreateBackendDX12Desc携带ID3D12Device* device指定后端运行设备而帧生成交换链相关描述符ffxCreateContextDescFrameGenerationSwapChainWrapDX12、ffxCreateContextDescFrameGenerationSwapChainNewDX12、ffxCreateContextDescFrameGenerationSwapChainForHwndDX12分别对应包装已有交换链新建交换链为 HWND 创建交换链三种接入方式字段中都有swapchain、gameQueue等关键参数。这正是 dlssg-to-fsr3 这类帧生成替换方案需要深入使用的部分。C 封装的调用差异使用 C 封装时第三个参数memCb会移到第二位以便支持可变参数描述符// 等价于上面的 C 调用createUpscale 与 createBackend 的链会自动连接。 ffxReturnCode_t retCode ffx::ContextCreate(upscaleContext, nullptr, createUpscale, createBackend);对照 ffx_api.hpp 的实现ffx::ContextCreate内部先调用LinkHeaders自动串链再转发给ffxCreateContext返回码经ConvertReturnCode转换为ffx::ReturnCode枚举。上下文销毁ffxDestroyContext销毁上下文调用ffxReturnCode_t ffxDestroyContext(ffxContext* context, const ffxAllocationCallbacks* memCb);调用后context会被置为null。memCb必须与创建时使用的分配回调兼容——即创建期间用该回调与用户数据分配的任何指针销毁时都必须能用传入销毁函数的回调与用户数据释放。查询ffxQuery查询效果的信息或资源使用ffxReturnCode_t ffxQuery(ffxContext* context, ffxQueryDescHeader* desc);context必须是ffxCreateContext创建的有效上下文除非特定查询的文档另有说明。输出值通过查询描述符中传入的指针写出。典型例子是版本枚举查询ffxQueryDescGetVersions其定义在 ffx_api.h通过createDescType指定要枚举版本的效果deviceDX12 应用需传入ID3D12Device指针outputCount/versionIds/versionNames分别接收数量、版本 ID 数组与版本名字符串数组。在 DX12 后端中ffxQuery还用于取帧生成交换链的插值命令列表与插值纹理ffx_api_dx12.h以及查询 GPU 内存占用ffxQueryFrameGenerationSwapChainGetGPUMemoryUsageDX12。配置ffxConfigure配置效果选项使用ffxReturnCode_t ffxConfigure(ffxContext* context, const ffxConfigureDescHeader* desc);context必须是有效上下文除非特定配置描述的文档另有说明。所有效果都提供键值对配置结构体用于简单选项例如struct ffxConfigureDescUpscaleKeyValue { ffxConfigureDescHeader header; uint64_t key; /// 配置键FfxApiConfigureUpscaleKey 枚举成员。 uint64_t u64; /// 要设置的整数值或枚举值。 void* ptr; /// 要设置的指针或指向要设置值的指针。 };可用的键与值约束由对应技术的文档说明。值得补充的是ffx_api.h 中定义了全局调试配置结构体ffxConfigureDescGlobalDebug1fpMessage传入回调函数指针接收错误/警告消息debugLevel可取值FFX_API_CONFIGURE_GLOBALDEBUG_LEVEL_SILENCE静默、ERRORS仅错误、WARNINGS错误警告或VERBOSE全量输出且ffxConfigure传入nullptr上下文时作用于全局状态。在 DX12 帧生成交换链后端ffx_api_dx12.h 定义了FfxApiConfigureFrameGenerationSwapChainKeyDX12枚举目前支持两个键FFX_API_CONFIGURE_FG_SWAPCHAIN_KEY_WAITCALLBACK—— 设置FfxWaitCallbackFuncFFX_API_CONFIGURE_FG_SWAPCHAIN_KEY_FRAMEPACINGTUNING—— 设置FfxApiSwapchainFramePacingTuning帧节奏调优参数。后者与 ffx_api_types.h 中的FfxApiSwapchainFramePacingTuning直接对应该结构体包含safetyMarginInMs默认 0.1ms、varianceFactor有效范围 [0.0,1.0]默认 0.1、allowHybridSpin、hybridSpinTime默认 2不建议低于 2与allowWaitForSingleObjectOnFence五个字段——这些字段正是 dlssg-to-fsr3 这类帧生成工具在调整帧节奏时可能用到的配置入口。派发ffxDispatch派发渲染命令或执行其他功能使用ffxReturnCode_t ffxDispatch(ffxContext* context, const ffxDispatchDescHeader* desc);context必须是有效上下文。两种派发行为的区别GPU 渲染派发将命令编码进传入的命令列表/命令缓冲command list / command buffer中由应用随后提交执行CPU 派发通常同步、立即执行。在 DX12 帧生成交换链后端ffx_api_dx12.h 定义了ffxDispatchDescFrameGenerationSwapChainWaitForPresentsDX12空描述符用于等待呈现完成配合ffxQuery取回的插值命令列表即可完成帧生成的实际提交流程。资源结构体FfxApiResource纹理、缓冲等资源通过FfxApiResource结构体传入 API。其定义位于 ffx_api_types.hstruct FfxApiResource { void* resource; struct FfxApiResourceDescription description; uint32_t state; };descriptionFfxApiResourceDescription描述了资源类型、表面格式、宽高/大小、mip 数量与使用标志state表示资源的当前状态如FFX_API_RESOURCE_STATE_UNORDERED_ACCESS、FFX_API_RESOURCE_STATE_PIXEL_COMPUTE_READ、FFX_API_RESOURCE_STATE_PRESENT等见 ffx_api_types.h。对 C 应用后端头文件提供从原生资源句柄构造该结构体的辅助函数。同文件还定义了FfxApiEffectMemoryUsagetotalUsageInBytes与aliasableUsageInBytes供查询效果 GPU 内存占用使用。版本选择Version selectionFidelityFX API 支持在创建上下文时覆盖每个效果的版本这是一个可选功能。一旦使用版本覆盖就必须保持一致只能使用ffxQuery的ffxQueryDescGetVersions查询返回的版本 ID并与对应的创建结构体类型配套使用不要硬编码版本 ID若在无上下文NULL参数情况下调用ffxQuery必须与ffxCreateContext使用相同的版本覆盖版本选择应交给默认行为不覆盖或用户在选项 UI 中展示而非写死在代码里。使用 C 辅助的版本查询示例ffx::QueryDescGetVersions versionQuery{}; versionQuery.createDescType FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE; versionQuery.device GetDX12Device(); // 仅 DirectX 12 应用需要 uint64_t versionCount 0; versionQuery.outputCount versionCount; // 先查询版本数量用于分配 ffxQuery(nullptr, versionQuery.header); std::vectorconst char* versionNames; std::vectoruint64_t versionIds; m_FsrVersionIds.resize(versionCount); versionNames.resize(versionCount); versionQuery.versionIds versionIds.data(); versionQuery.versionNames versionNames.data(); // 填充版本 ID 与名称数组 ffxQuery(nullptr, versionQuery.header);注意这里先以outputCount为 0 调用一次取得数量分配数组后再以填充好的versionIds/versionNames调用第二次是典型的两段式查询用法。版本覆盖本身通过ffxOverrideVersion结构体ffx_api.h链入创建描述符实现其versionId必须是ffxQueryDescGetVersions.versionIds数组返回的值。错误处理Error handling所有 API 调用都返回ffxReturnCode_tC 封装中为ffx::ReturnCode枚举。FFX_API_RETURN_OK值为 0表示成功其余均为错误码。从 ffx_api.h 可以看到完整的错误码定义返回码值含义FFX_API_RETURN_OK0操作成功FFX_API_RETURN_ERROR1发生未进一步指定的错误FFX_API_RETURN_ERROR_UNKNOWN_DESCTYPE2结构体类型无法被当前函数或上下文识别通常是编程错误FFX_API_RETURN_ERROR_RUNTIME_ERROR3底层运行时如 D3D12、Vulkan或效果返回了错误码FFX_API_RETURN_NO_PROVIDER4未找到给定结构体类型对应的 Provider通常是编程错误FFX_API_RETURN_ERROR_MEMORY5内存分配失败FFX_API_RETURN_ERROR_PARAMETER6参数无效如空指针、空资源或越界枚举值未来版本可能新增当前头文件中尚未出现的返回码因此应用应具备优雅处理错误的能力——即使错误不可恢复也不应因异常返回码而崩溃。内存分配Memory allocation要控制内存分配向ffxCreateContext与ffxDestroyContext传入ffxAllocationCallbacks指针传null时使用全局malloc/free。自定义分配器需要两个函数指针与一个用户数据指针// 内存分配函数。必须返回指向至少 size 字节、且对齐到可容纳任意类型地址的有效指针。 // 可返回 null 表示失败。标准库 malloc 满足此要求。 typedef void* (*ffxAlloc)(void* pUserData, uint64_t size); // 内存释放函数。第二个参数可能以 null 指针调用。 typedef void (*ffxDealloc)(void* pUserData, void* pMem); typedef struct ffxAllocationCallbacks { void* pUserData; ffxAlloc alloc; ffxDealloc dealloc; } ffxAllocationCallbacks;pUserData会原样透传给回调FidelityFX API 不会解引用、不会存储它。创建与销毁必须使用兼容的回调创建期间用某回调用户数据分配的任何指针都必须能由传给ffxDestroyContext的回调用户数据释放否则会造成内存管理不一致。总结FidelityFX API 用五个导出函数加统一的描述符链表机制把 FSR 3 帧生成、超分辨率等全部效果能力收敛为极简且向前兼容的调用面。对 dlssg-to-fsr3 而言正确理解ffxCreateContext含后端描述符链入与版本覆盖、ffxQuery取插值命令列表/纹理、枚举版本、ffxConfigure键值配置与帧节奏调优、ffxDispatch提交 GPU 派发以及内存分配回调的配套使用是在 DX12/Vulkan 两个后端中稳定驱动 FSR 3 帧生成的基础。想深入探索的读者可以继续阅读官方入门文档目录了解 SDK 结构、构建与迁移指南ffx-api 完整头文件目录逐一核对各效果的描述符定义帧生成技术文档 与 帧生成交换链技术文档理解交换链层面如何接入帧生成本仓库 source/maindll 下的实际工程代码观察真实应用中如何加载并驱动 FSR 3 帧生成。赞分享图形学游戏开发【免费下载链接】dlssg-to-fsr3Adds AMD FSR 3 Frame Generation to games by replacing Nvidia DLSS Frame Generation (nvngx_dlssg).项目地址https://gitcode.com/gh_mirrors/dl/dlssg-to-fsr3点击查看免费下载相关推荐TabDDPM 教程用扩散模型三步生成高保真表格合成数据TabDDPM 教程用扩散模型三步生成高保真表格合成数据 TabDDPM 是 ICML 2023 论文 Modelling Tabular Data wit人工智能深度学习机器学习dlssg-to-fsr3 仓库中的 FidelityFX CauldronDirectX-Headers 内嵌维护与 AgilitySDK 版本同步实战指南dlssg to fsr3 仓库中的 FidelityFX CauldronDirectX Headers 内嵌维护与 AgilitySDK 版本同步实战指南图形学游戏开发FidelityFX SDK 1.1.3 更新详解FSR 3.1.3 帧生成修复与 FSR API 演进dlssg-to-fsr3 视角FidelityFX SDK 1.1.3 更新详解FSR 3.1.3 帧生成修复与 FSR API 演进dlssg to fsr3 视角 本文基于本仓库随图形学游戏开发上一篇30-seconds-of-css SMACSS方法将代码片段按类别组织的实用策略下一篇listmonk容器健康检查依赖外部服务健康验证创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表