在 DirectX 11 中高效捕获帧
Efficiently Capture Frames in DirectX 11
我正在尝试捕捉我正在玩的游戏的每一帧。市面上有很多优秀的屏幕捕捉软件,Windows 10.
中内置了其中一款
但是,出于不同的原因,我需要一种自定义方法。我目前正在使用 DirectX 工具包 SaveWICTextureToFile()
方法来保存由 Present() 生成的每一帧。
https://github.com/microsoft/DirectXTK
对于捕获的每一帧,我想用它的适用编号标记文件名的末尾。 ScreenShot_0
至 ScreenShot_n.
方法SaveWICTextureToFile()
为您保存截图:
DirectX::SaveWICTextureToFile(context, backbufferTex, GUID_ContainerFormatJpeg, L"C:/Users/User Name/Desktop/Images/ScreenShot.JPG");
这不允许您按顺序捕获帧。它只是为每一帧覆盖同一个文件。但是,性能非常流畅。在游戏过程中没有任何滞后。
为了尝试为每一帧编写一个文件,我执行了以下操作:
#include <sstream>
int Frame_Number;
//For each Call to Present() do the following:
//Get Device
ID3D11Device* device;
HRESULT gd = pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&device);
assert(gd == S_OK);
//Get context
ID3D11DeviceContext* context;
device->GetImmediateContext(&context);
//get back buffer
ID3D11Texture2D* backbufferTex;
HRESULT gb = pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2d), (LPVOID*)&backbufferTex);
assert(gb == S_OK);
//Set-up Directory
std::wstringstream Image_Directory;
Image_Directory << L"C:/Users/User Name/Desktop/Images/ScreenShot_" << Frame_Number << L".JPG";
//Capture Frame
REFGUID GUID_ContainerFormatJpeg{ 0x19e4a5aa, 0x5662, 0x4fc5, 0xa0, 0xc0, 0x17, 0x58, 0x2, 0x8e, 0x10, 0x57 };
HRESULT hr = DirectX::SaveWICTextureToFile(context, backbufferTex, GUID_ContainerFormatJpeg, Image_Directory.str().c_str());
assert(hr == S_OK);
Frame_Number = Frame_Number + 1;
这有效,但性能不稳定。与以前的方法相比,我不再获得流畅的游戏体验。有人能推荐一种更有效的方法吗?
如果这是在调试版本中完成的,我怀疑字符串流有导致问题的逻辑,我建议改用字符数组和 swprintf。更好的是,如果你跟踪目录的结束位置,那么只需要写出文件名部分(你可以更进一步,这样你只需要格式化数字和扩展名)。
It simply writes over the same file for each frame. The performance however is very smooth.
如果其他条件相同,则减速有几种可能性:
该文件仅写入内存,从未提交到磁盘,因为它一直被覆盖。
每秒打开很多文件从来都不是一个好主意,特别是在 Windows 上,与例如相比,这在这方面特别慢。 Linux.
将许多文件写入同一个文件夹是另一个坏主意,因为许多文件系统不能很好地处理这种情况。
找出这三个中的哪一个是罪魁祸首,然后从那里迭代。
并让我们知道!听到现在不同用例的 IO 有多快总是很有趣:-)
我正在尝试捕捉我正在玩的游戏的每一帧。市面上有很多优秀的屏幕捕捉软件,Windows 10.
中内置了其中一款但是,出于不同的原因,我需要一种自定义方法。我目前正在使用 DirectX 工具包 SaveWICTextureToFile()
方法来保存由 Present() 生成的每一帧。
https://github.com/microsoft/DirectXTK
对于捕获的每一帧,我想用它的适用编号标记文件名的末尾。 ScreenShot_0
至 ScreenShot_n.
方法SaveWICTextureToFile()
为您保存截图:
DirectX::SaveWICTextureToFile(context, backbufferTex, GUID_ContainerFormatJpeg, L"C:/Users/User Name/Desktop/Images/ScreenShot.JPG");
这不允许您按顺序捕获帧。它只是为每一帧覆盖同一个文件。但是,性能非常流畅。在游戏过程中没有任何滞后。
为了尝试为每一帧编写一个文件,我执行了以下操作:
#include <sstream>
int Frame_Number;
//For each Call to Present() do the following:
//Get Device
ID3D11Device* device;
HRESULT gd = pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&device);
assert(gd == S_OK);
//Get context
ID3D11DeviceContext* context;
device->GetImmediateContext(&context);
//get back buffer
ID3D11Texture2D* backbufferTex;
HRESULT gb = pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2d), (LPVOID*)&backbufferTex);
assert(gb == S_OK);
//Set-up Directory
std::wstringstream Image_Directory;
Image_Directory << L"C:/Users/User Name/Desktop/Images/ScreenShot_" << Frame_Number << L".JPG";
//Capture Frame
REFGUID GUID_ContainerFormatJpeg{ 0x19e4a5aa, 0x5662, 0x4fc5, 0xa0, 0xc0, 0x17, 0x58, 0x2, 0x8e, 0x10, 0x57 };
HRESULT hr = DirectX::SaveWICTextureToFile(context, backbufferTex, GUID_ContainerFormatJpeg, Image_Directory.str().c_str());
assert(hr == S_OK);
Frame_Number = Frame_Number + 1;
这有效,但性能不稳定。与以前的方法相比,我不再获得流畅的游戏体验。有人能推荐一种更有效的方法吗?
如果这是在调试版本中完成的,我怀疑字符串流有导致问题的逻辑,我建议改用字符数组和 swprintf。更好的是,如果你跟踪目录的结束位置,那么只需要写出文件名部分(你可以更进一步,这样你只需要格式化数字和扩展名)。
It simply writes over the same file for each frame. The performance however is very smooth.
如果其他条件相同,则减速有几种可能性:
该文件仅写入内存,从未提交到磁盘,因为它一直被覆盖。
每秒打开很多文件从来都不是一个好主意,特别是在 Windows 上,与例如相比,这在这方面特别慢。 Linux.
将许多文件写入同一个文件夹是另一个坏主意,因为许多文件系统不能很好地处理这种情况。
找出这三个中的哪一个是罪魁祸首,然后从那里迭代。
并让我们知道!听到现在不同用例的 IO 有多快总是很有趣:-)