4.4 KiB
4.4 KiB
D3D12Screenshot::Capture
bool Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) override;
static bool Capture(ID3D12Device* device,
ID3D12CommandQueue* commandQueue,
ID3D12Resource* renderTarget,
const char* filename,
uint32_t width,
uint32_t height);
static bool Capture(D3D12Device& device,
D3D12CommandQueue& commandQueue,
D3D12Texture& texture,
const char* filename);
作用
从 D3D12 渲染目标抓取一帧图像,并把结果保存为 PPM 文件。
这三个公开重载只是适配不同调用层级,最终都会进入同一套 copy-to-readback 再写盘的实现。
核心流程
底层实现 CopyToReadbackAndSave(...) 的关键步骤如下:
- 校验原生
device、commandQueue、renderTarget - 查询资源描述和 copy footprint
- 创建一次性 command allocator、command list、readback buffer
- 插入
RENDER_TARGET -> COPY_SOURCE -> RENDER_TARGET状态切换 - 执行
CopyTextureRegion(...) - 提交队列并通过 fence 阻塞等待
Map()读回数据,按P6PPM 写出 RGB 像素
重载 1: RHI 入口
bool Capture(RHIDevice* device, RHISwapChain* swapChain, const char* filename) override;
当前实现行为
- 直接把
device转成D3D12Device* - 直接把
swapChain转成D3D12SwapChain* - 通过
swapChain->GetCurrentBackBuffer()取得当前 back buffer - 通过
d3d12SwapChain->GetNativeCommandQueue()取得原生命令队列 - 再转发到内部 copy 逻辑
注意事项
- 没有运行时类型检查,所以它只能在 D3D12 后端上下文中正确工作
- 也没有对
device/swapChain做空指针保护 - 如果 D3D12SwapChain 当前没有缓存原生命令队列,底层会在空队列检查时报错并返回
false
重载 2: 原生 D3D12 入口
static bool Capture(ID3D12Device* device,
ID3D12CommandQueue* commandQueue,
ID3D12Resource* renderTarget,
const char* filename,
uint32_t width,
uint32_t height);
当前实现行为
- 这是最直接的后端入口
- 只做一层转发,真正逻辑全部在
CopyToReadbackAndSave(...) - 会记录
device、commandQueue、renderTarget为空的错误日志
关键前提
renderTarget当前状态被假定为D3D12_RESOURCE_STATE_RENDER_TARGET- 目标资源需要能被
CopyTextureRegion(...)读取 - 当前实现默认按“每像素 4 字节,取前 3 字节写 RGB”处理输出
宽高参数说明
这里的 width / height 不是通过 renderTarget->GetDesc() 自动推导出来的输出尺寸,而是调用者显式传入的写盘尺寸。
当前实现里:
- copy 区域使用的是资源描述中的
Width/Height - 文件写出循环使用的是函数参数里的
width/height
因此如果两者不一致,输出内容可能越界、截断或产生错误图像。常规做法是传入与资源真实尺寸一致的值。
重载 3: D3D12 包装对象入口
static bool Capture(D3D12Device& device,
D3D12CommandQueue& commandQueue,
D3D12Texture& texture,
const char* filename);
当前实现行为
- 从
D3D12Device取GetDevice() - 从
D3D12CommandQueue取GetCommandQueue() - 从
D3D12Texture取GetResource()、GetWidth()、GetHeight() - 再调用原生 D3D12 重载
适用场景
这通常是测试和集成样例里最方便的入口,因为调用方已经处在 D3D12 封装层,不需要再自己拆出所有原生句柄。
输出格式
- 文件格式固定为
P6PPM - 只写 RGB,不写 alpha
- 不做压缩
- 不做色彩空间转换或 HDR 编码
实践建议
- 优先用于测试截图、调试抓帧和最小验证程序
- 如果未来要支持商业级截图能力,通常应把这条同步路径升级成“异步 readback + 后台编码”体系
- 如果 render target 不是标准 4 字节颜色格式,应先评估当前实现是否适配,而不是直接假设结果正确