2023年12月13日发(作者:)

【DirectX12笔记】内置RenderDoc抓帧和启动

  一般我们用RenderDoc调试DirectX12时,是在Launch Application中填入启动的EXE和工作目录,然后Launch:

  不过有时也想像Unity一样,通过App内置代码来启动RenderDoc,所以我参考了文档In Application API ,改造现有的程序。

  首先上RenderDoc安装目录,找到,和renderdoc_app.h,注意,如果程序是32位的,要到RenderDoc的X86子目录中找

dll。

  暂时不考虑其他平台,Windows下,动态加载dll用下面的方法:

//别忘了#include "renderdoc_app.h"

RENDERDOC_API_1_1_2 *rdoc_api = nullptr;//API接口

if (HMODULE mod = LoadLibraryA(""))

{

pRENDERDOC_GetAPI RENDERDOC_GetAPI = (pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");

int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void**)&rdoc_api);

assert(ret == 1);

}

else

{

std::cout << "RenderDoc Lode Error: " << GetLastError() << std::endl;

}

  Renderdoc安装时会在注册表

计算机HKEY_LOCAL_MACHINESOFTWAREClassesCLSID{5D6BF029-A6BA-417A-8523-

120492B1DCE3}InprocServer32

中,记录dll路径,Unity和UE都是通过这种方法找到的。

  这个代码具体放置位置有要求,要在所有图形API调用之前,所以根据DX12龙书,我找到定义的Initialize方法中,正好开头就

是下面这种代码:

if(!InitMainWindow())

return false;

//Init renderdoc api

//...

if(!InitDirect3D())

return false;

  初始化后定义暂存截帧文件的位置模版,我是这么定义的:

rdoc_api->SetCaptureFilePathTemplate("RenderDocCapture/Capture");

  这样会在工作路径/RenderDocCapture下,不断存取Capture_这样的文件,后面的数字是App运行到当前时间的帧数。

  如果不自定义,会存在C盘的某个Temp目录中,这个目录可以通过

const char *GetCaptureFilePathTemplate()

得到。

  然后用下面的方法截帧:

if (GetKeyDown(Key::C))

{

rdoc_api->TriggerCapture();

if(!rdoc_api->IsTargetControlConnected())

rdoc_api->LaunchReplayUI(1, nullptr);

}

  GetKeyDown是我自己定义的按键模块,这个根据自己的项目修改,TriggerCapture触发下一帧截取,IsTargetControlConnected判断

是否打开了UI,如果没打开,则调用LaunchReplayUI打开RenderDoc,参数1是指立刻打开UI,参数2的nullptr是命令行参数。

  抓到的帧会存在刚刚定义的文件中,当RenderDoc退出时会询问是否保存抓到的帧,如果否,则文件会被删除。

  功能大致这样,也可以根据需要简单封装。