Integrate RenderDoc frame capture into D3D12 minimal test
- Add SetDevice() and GetNumCaptures() methods to RenderDocCapture - Fix initialization order: RenderDoc before D3D12, then SetDevice after - Use nullptr for window param in StartFrameCapture/EndFrameCapture - Add BeginCapture at frame 29, EndCapture at frame 30 - Set capture file path template to .\minimal_frame30 - Copy renderdoc.dll (26MB redistributable) to test output - Engine/third_party/renderdoc/ now contains working renderdoc.dll
This commit is contained in:
@@ -14,9 +14,11 @@ public:
|
|||||||
|
|
||||||
bool Initialize(void* device, void* window = nullptr);
|
bool Initialize(void* device, void* window = nullptr);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
void SetDevice(void* device);
|
||||||
|
|
||||||
bool IsLoaded() const { return m_isLoaded; }
|
bool IsLoaded() const { return m_isLoaded; }
|
||||||
bool IsCapturing() const;
|
bool IsCapturing() const;
|
||||||
|
uint32_t GetNumCaptures() const;
|
||||||
|
|
||||||
void BeginCapture(const char* title = nullptr);
|
void BeginCapture(const char* title = nullptr);
|
||||||
void EndCapture();
|
void EndCapture();
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ void RenderDocCapture::Shutdown() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderDocCapture::SetDevice(void* device) {
|
||||||
|
m_device = device;
|
||||||
|
}
|
||||||
|
|
||||||
bool RenderDocCapture::LoadRenderDoc() {
|
bool RenderDocCapture::LoadRenderDoc() {
|
||||||
char exePath[MAX_PATH];
|
char exePath[MAX_PATH];
|
||||||
GetModuleFileNameA(NULL, exePath, MAX_PATH);
|
GetModuleFileNameA(NULL, exePath, MAX_PATH);
|
||||||
@@ -104,6 +108,13 @@ bool RenderDocCapture::IsCapturing() const {
|
|||||||
return m_api->IsFrameCapturing() != 0;
|
return m_api->IsFrameCapturing() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t RenderDocCapture::GetNumCaptures() const {
|
||||||
|
if (!m_isLoaded || !m_api) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return m_api->GetNumCaptures();
|
||||||
|
}
|
||||||
|
|
||||||
void RenderDocCapture::BeginCapture(const char* title) {
|
void RenderDocCapture::BeginCapture(const char* title) {
|
||||||
if (!m_isLoaded || !m_api) {
|
if (!m_isLoaded || !m_api) {
|
||||||
return;
|
return;
|
||||||
@@ -111,15 +122,14 @@ void RenderDocCapture::BeginCapture(const char* title) {
|
|||||||
if (title) {
|
if (title) {
|
||||||
m_api->SetCaptureTitle(title);
|
m_api->SetCaptureTitle(title);
|
||||||
}
|
}
|
||||||
m_api->SetActiveWindow(m_device, m_window);
|
m_api->StartFrameCapture(m_device, nullptr);
|
||||||
m_api->StartFrameCapture(m_device, m_window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderDocCapture::EndCapture() {
|
void RenderDocCapture::EndCapture() {
|
||||||
if (!m_isLoaded || !m_api) {
|
if (!m_isLoaded || !m_api) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_api->EndFrameCapture(m_device, m_window);
|
m_api->EndFrameCapture(m_device, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderDocCapture::TriggerCapture() {
|
void RenderDocCapture::TriggerCapture() {
|
||||||
|
|||||||
BIN
engine/third_party/renderdoc/renderdoc.dll
vendored
Normal file
BIN
engine/third_party/renderdoc/renderdoc.dll
vendored
Normal file
Binary file not shown.
BIN
engine/third_party/renderdoc/renderdoc.pyd
vendored
Normal file
BIN
engine/third_party/renderdoc/renderdoc.pyd
vendored
Normal file
Binary file not shown.
@@ -39,6 +39,9 @@ add_custom_command(TARGET D3D12_Minimal POST_BUILD
|
|||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm
|
${CMAKE_CURRENT_SOURCE_DIR}/GT.ppm
|
||||||
$<TARGET_FILE_DIR:D3D12_Minimal>/
|
$<TARGET_FILE_DIR:D3D12_Minimal>/
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
${ENGINE_ROOT_DIR}/third_party/renderdoc/renderdoc.dll
|
||||||
|
$<TARGET_FILE_DIR:D3D12_Minimal>/
|
||||||
)
|
)
|
||||||
|
|
||||||
add_test(NAME D3D12_Minimal_Integration
|
add_test(NAME D3D12_Minimal_Integration
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "XCEngine/Debug/Logger.h"
|
#include "XCEngine/Debug/Logger.h"
|
||||||
#include "XCEngine/Debug/ConsoleLogSink.h"
|
#include "XCEngine/Debug/ConsoleLogSink.h"
|
||||||
#include "XCEngine/Debug/FileLogSink.h"
|
#include "XCEngine/Debug/FileLogSink.h"
|
||||||
|
#include "XCEngine/Debug/RenderDocCapture.h"
|
||||||
#include "XCEngine/Containers/String.h"
|
#include "XCEngine/Containers/String.h"
|
||||||
|
|
||||||
using namespace XCEngine::RHI;
|
using namespace XCEngine::RHI;
|
||||||
@@ -228,12 +229,22 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize RenderDoc capture (MUST be before D3D12 init)
|
||||||
|
if (!RenderDocCapture::Get().Initialize(nullptr, gHWND)) {
|
||||||
|
Log("[WARNING] Failed to initialize RenderDoc, frame capture will not be available");
|
||||||
|
} else {
|
||||||
|
RenderDocCapture::Get().SetCaptureFilePath(".\\minimal_frame30");
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize D3D12
|
// Initialize D3D12
|
||||||
if (!InitD3D12()) {
|
if (!InitD3D12()) {
|
||||||
MessageBox(NULL, L"Failed to initialize D3D12", L"Error", MB_OK);
|
MessageBox(NULL, L"Failed to initialize D3D12", L"Error", MB_OK);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set device for RenderDoc (must be called after D3D12 init)
|
||||||
|
RenderDocCapture::Get().SetDevice(gDevice.GetDevice());
|
||||||
|
|
||||||
// Show window
|
// Show window
|
||||||
ShowWindow(gHWND, nShowCmd);
|
ShowWindow(gHWND, nShowCmd);
|
||||||
UpdateWindow(gHWND);
|
UpdateWindow(gHWND);
|
||||||
@@ -267,7 +278,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
frameCount++;
|
frameCount++;
|
||||||
|
|
||||||
if (frameCount >= targetFrameCount) {
|
if (frameCount >= targetFrameCount) {
|
||||||
Log("[INFO] Reached target frame count %d - taking screenshot before present!", targetFrameCount);
|
Log("[INFO] Reached target frame count %d - ending capture and taking screenshot!", targetFrameCount);
|
||||||
|
RenderDocCapture::Get().EndCapture();
|
||||||
ExecuteCommandList();
|
ExecuteCommandList();
|
||||||
WaitForGPU();
|
WaitForGPU();
|
||||||
Log("[INFO] GPU idle, taking screenshot...");
|
Log("[INFO] GPU idle, taking screenshot...");
|
||||||
@@ -282,9 +294,14 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
} else {
|
} else {
|
||||||
Log("[ERROR] Screenshot failed");
|
Log("[ERROR] Screenshot failed");
|
||||||
}
|
}
|
||||||
|
Log("[INFO] RenderDoc capture completed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frameCount == targetFrameCount - 1) {
|
||||||
|
RenderDocCapture::Get().BeginCapture("Minimal_Test_Frame30");
|
||||||
|
}
|
||||||
|
|
||||||
EndRender();
|
EndRender();
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
@@ -296,6 +313,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown
|
// Shutdown
|
||||||
|
RenderDocCapture::Get().Shutdown();
|
||||||
gCommandList.Shutdown();
|
gCommandList.Shutdown();
|
||||||
gCommandAllocator.Shutdown();
|
gCommandAllocator.Shutdown();
|
||||||
gSwapChain.Shutdown();
|
gSwapChain.Shutdown();
|
||||||
|
|||||||
Reference in New Issue
Block a user