DirectX 12中如何捕获FSR3与DLSS3生成的所有帧?
捕获DX12应用中FSR3/DLSS3全帧(真实+插值)的实用方案
1. Hook关键DX12 API与SDK函数
既然插值帧不触发应用层的Present,但最终会通过资源拷贝或SDK内部提交完成输出,可通过轻量Hook实现精准捕获:
- 针对FSR3:你已经通过PIX识别出插值帧对应的资源名称,用MinHook这类库Hook
ID3D12CommandQueue::ExecuteCommandLists,在命令列表提交前检查是否包含目标资源的写入操作,待命令执行完成(通过Fence同步GPU)后触发转储;也可以直接HookFfxFsr3ContextDispatch,获取其输出的插值帧资源指针。 - 针对DLSS3:Hook NVIDIA DLSS SDK的
NvAPI_D3D12_DLSS3_Execute函数,拦截其输出的插值帧资源,同步GPU后转储。 - 无需修改交换链工厂,只需要针对性Hook SDK核心函数和DX12命令提交接口,复杂度远低于全局交换链修补。
2. 替换为离屏渲染目标(推荐)
既然不需要实时显示,直接接管所有帧的输出目标:
- 创建与原交换链同格式、同分辨率的离屏
ID3D12Resource作为统一输出目标。 - Hook
IDXGISwapChain::Present,将真实帧拷贝到你的离屏资源后转储,跳过原生Present流程。 - 对于FSR3/DLSS3,Hook其上下文初始化函数,强制将插值帧的输出定向到你创建的离屏资源,每次插值完成后直接转储该资源。
- 这种方式不需要跟踪复杂的命令流,所有帧都会输出到你可控的资源,转储逻辑统一且可靠。
3. 基于资源状态与Fence的监控
利用DX12的资源状态变化同步捕获:
- 启用DX12资源名称调试(创建资源时设置
D3D12_RESOURCE_DESC的Name),通过ID3D12Resource::GetDesc()匹配你已知的FSR3插值帧资源。 - 为目标资源创建
ID3D12Fence,在资源状态切换为D3D12_RESOURCE_STATE_COPY_SOURCE时触发Fence信号。 - 在CPU端等待Fence信号触发后,立即将资源数据转储到磁盘,确保获取的是GPU已经渲染完成的完整帧。
注意事项
- 转储前必须同步GPU:插值帧生成是异步操作,直接读取资源会得到未完成的帧数据,必须通过Fence等待命令执行完毕。
- DLSS3私有资源处理:DLSS3的插值帧资源是SDK内部创建的,无法通过枚举资源获取,必须通过Hook SDK输出函数拦截。
- 资源状态转换:转储前要确保资源处于
D3D12_RESOURCE_STATE_COPY_SOURCE状态,否则会触发GPU错误,可通过ID3D12GraphicsCommandList::ResourceBarrier转换状态。
内容的提问来源于stack exchange,提问作者Deniz da King
相关产品推荐
相关产品推荐

