feat: add RenderDocCapture to Debug module for frame capture debugging

- Add RenderDocCapture class for dynamic loading of renderdoc.dll
- Support BeginCapture/EndCapture/TriggerCapture APIs
- Add RenderDoc log category
- Add unit tests for RenderDocCapture in tests/debug
This commit is contained in:
2026-03-23 17:11:01 +08:00
parent d58d98cb68
commit 81dc337262
8 changed files with 285 additions and 0 deletions

View File

@@ -8,5 +8,6 @@
#include "FileLogSink.h"
#include "Logger.h"
#include "Profiler.h"
#include "RenderDocCapture.h"
#include "../Core/FileWriter.h"

View File

@@ -13,6 +13,7 @@ enum class LogCategory {
Memory,
Threading,
FileSystem,
RenderDoc,
Custom
};

View File

@@ -0,0 +1,76 @@
#pragma once
#include <cstdint>
#include <windows.h>
namespace XCEngine {
namespace Debug {
#define RENDERDOC_CC __cdecl
class RenderDocCapture {
public:
static RenderDocCapture& Get();
bool Initialize(void* device, void* window = nullptr);
void Shutdown();
bool IsLoaded() const { return m_isLoaded; }
bool IsCapturing() const;
void BeginCapture(const char* title = nullptr);
void EndCapture();
void TriggerCapture();
void SetCaptureFilePath(const char* path);
void SetCaptureComments(const char* comments);
private:
RenderDocCapture() = default;
~RenderDocCapture() = default;
bool LoadRenderDoc();
void UnloadRenderDoc();
struct RENDERDOC_API_1_7_0 {
void (RENDERDOC_CC* GetAPIVersion)(int* major, int* minor, int* patch);
void (RENDERDOC_CC* SetCaptureOptionU32)(uint32_t opt, uint32_t val);
void (RENDERDOC_CC* SetCaptureOptionF32)(uint32_t opt, float val);
uint32_t (RENDERDOC_CC* GetCaptureOptionU32)(uint32_t opt);
float (RENDERDOC_CC* GetCaptureOptionF32)(uint32_t opt);
void (RENDERDOC_CC* SetFocusToggleKeys)(const char* const* keys, int num);
void (RENDERDOC_CC* SetCaptureKeys)(const char* const* keys, int num);
uint32_t (RENDERDOC_CC* GetOverlayBits)();
void (RENDERDOC_CC* MaskOverlayBits)(uint32_t And, uint32_t Or);
void (RENDERDOC_CC* RemoveHooks)();
void (RENDERDOC_CC* UnloadCrashHandler)();
void (RENDERDOC_CC* SetCaptureFilePathTemplate)(const char* path);
const char* (RENDERDOC_CC* GetCaptureFilePathTemplate)();
uint32_t (RENDERDOC_CC* GetNumCaptures)();
uint32_t (RENDERDOC_CC* GetCapture)(uint32_t idx, char* filename, uint32_t* length, uint64_t* timestamp);
void (RENDERDOC_CC* TriggerCapture)();
uint32_t (RENDERDOC_CC* IsTargetControlConnected)();
void (RENDERDOC_CC* LaunchReplayUI)(uint32_t connect, const char* cmdline);
void (RENDERDOC_CC* SetActiveWindow)(void* device, void* window);
void (RENDERDOC_CC* StartFrameCapture)(void* device, void* window);
uint32_t (RENDERDOC_CC* IsFrameCapturing)();
void (RENDERDOC_CC* EndFrameCapture)(void* device, void* window);
void (RENDERDOC_CC* TriggerMultiFrameCapture)(uint32_t numFrames);
void (RENDERDOC_CC* SetCaptureFileComments)(const char* filePath, const char* comments);
uint32_t (RENDERDOC_CC* DiscardFrameCapture)(void* device, void* window);
uint32_t (RENDERDOC_CC* ShowReplayUI)();
void (RENDERDOC_CC* SetCaptureTitle)(const char* title);
void (RENDERDOC_CC* SetObjectAnnotation)(void* device, void* object, const char* key, int valueType, uint32_t valueVectorWidth, const void* value);
void (RENDERDOC_CC* SetCommandAnnotation)(void* device, void* queueOrCommandBuffer, const char* key, int valueType, uint32_t valueVectorWidth, const void* value);
};
HMODULE m_renderDocModule = nullptr;
RENDERDOC_API_1_7_0* m_api = nullptr;
void* m_device = nullptr;
void* m_window = nullptr;
bool m_isLoaded = false;
bool m_initialized = false;
};
} // namespace Debug
} // namespace XCEngine