Эффективный захват кадров в DirectX 11 - PullRequest
0 голосов
/ 05 августа 2020

Я пытаюсь запечатлеть каждый кадр игры, в которую играю. Существует множество хороших программ для захвата экрана, одно из которых встроено прямо в Windows 10.

Однако мне нужен индивидуальный подход по разным причинам. В настоящее время я использую метод DirectX Tool Kits 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;

Это сработало, однако производительность нестабильна. По сравнению с предыдущим методом у меня больше не получается плавного игрового процесса. Может ли кто-нибудь порекомендовать более эффективный способ сделать это?

Ответы [ 2 ]

1 голос
/ 05 августа 2020

Он просто записывает один и тот же файл для каждого кадра. Однако производительность очень плавная.

Если все остальное равно, есть несколько возможностей для замедления:

  • Файл записывается только в память и никогда не сохраняется на диск, так как он продолжает перезаписываться.

  • Открытие большого количества файлов в секунду никогда не является хорошей идеей, особенно для Windows, который при этом работает особенно медленно по сравнению, например, с. Linux.

  • Запись большого количества файлов в одну папку - еще одна плохая идея, поскольку многие файловые системы плохо справляются с этим случаем.

Выясните, кто из этих трех является виновником, и повторите оттуда.

И дайте нам знать! Всегда интересно услышать, насколько быстро выполняется ввод-вывод в различных случаях использования: -)

1 голос
/ 05 августа 2020

Если это делается в отладочной сборке, я подозреваю, что в строковом потоке есть logi c, вызывающий проблемы, я предлагаю вместо этого использовать массивы символов и swprintf. Еще лучше, если вы отслеживаете, где заканчивается каталог и вам нужно записать только часть имени файла (вы можете go еще больше и сделать так, чтобы вам нужно было только отформатировать номер и расширение).

...