#include "XCEngine/Debug/RenderDocCapture.h" #include "XCEngine/Debug/Logger.h" #include #include #include namespace XCEngine { namespace Debug { static const char* RENDERDOC_DLL_PATH = "renderdoc.dll"; RenderDocCapture& RenderDocCapture::Get() { static RenderDocCapture instance; return instance; } bool RenderDocCapture::Initialize(void* device, void* window) { if (m_initialized) { return true; } m_device = device; m_window = window; if (!LoadRenderDoc()) { return false; } m_api->SetCaptureOptionU32(2, 1); m_api->SetCaptureOptionU32(8, 1); m_api->SetCaptureOptionU32(9, 1); m_api->SetCaptureFilePathTemplate(".\\captures"); m_initialized = true; Logger::Get().Info(LogCategory::General, "RenderDocCapture initialized successfully"); return true; } void RenderDocCapture::Shutdown() { if (m_initialized) { if (IsCapturing()) { EndCapture(); } UnloadRenderDoc(); m_initialized = false; } } void RenderDocCapture::SetDevice(void* device) { m_device = device; } void RenderDocCapture::SetWindow(void* window) { m_window = window; } bool RenderDocCapture::LoadRenderDoc() { char exePath[MAX_PATH]; GetModuleFileNameA(NULL, exePath, MAX_PATH); char* end = strrchr(exePath, '\\'); if (end) *end = '\0'; strcat_s(exePath, "\\renderdoc.dll"); HMODULE module = LoadLibraryA(exePath); if (!module) { DWORD error = GetLastError(); char buf[512]; sprintf(buf, "Failed to load renderdoc.dll from %s, error=%lu", exePath, error); Logger::Get().Warning(LogCategory::General, buf); return false; } using PFN_RENDERDOC_GetAPI = int (RENDERDOC_CC*)(int version, void** apiOut); PFN_RENDERDOC_GetAPI GetAPI = (PFN_RENDERDOC_GetAPI)GetProcAddress(module, "RENDERDOC_GetAPI"); if (!GetAPI) { Logger::Get().Error(LogCategory::General, "Failed to get RENDERDOC_GetAPI"); FreeLibrary(module); return false; } int apiVersion = 10700; void* apiPtr = nullptr; int ret = GetAPI(apiVersion, &apiPtr); if (ret != 1 || !apiPtr) { char buf[256]; sprintf(buf, "Failed to get RenderDoc API: ret=%d, ptr=%p", ret, apiPtr); Logger::Get().Error(LogCategory::General, buf); FreeLibrary(module); return false; } m_renderDocModule = module; m_api = (RENDERDOC_API_1_7_0*)apiPtr; m_isLoaded = true; return true; } void RenderDocCapture::UnloadRenderDoc() { if (m_renderDocModule) { FreeLibrary(m_renderDocModule); m_renderDocModule = nullptr; } m_api = nullptr; m_isLoaded = false; } bool RenderDocCapture::IsCapturing() const { if (!m_isLoaded || !m_api) { return false; } return m_api->IsFrameCapturing() != 0; } uint32_t RenderDocCapture::GetNumCaptures() const { if (!m_isLoaded || !m_api) { return 0; } return m_api->GetNumCaptures(); } bool RenderDocCapture::GetCapture(uint32_t index, RenderDocCaptureInfo* info) const { if (!m_isLoaded || !m_api || !info) { return false; } uint32_t length = 0; uint64_t timestamp = 0; uint32_t result = m_api->GetCapture(index, info->filename, &length, ×tamp); info->length = length; info->timestamp = timestamp; return result == 1; } bool RenderDocCapture::BeginCapture(const char* title) { if (!m_isLoaded || !m_api) { Logger::Get().Warning(LogCategory::General, "BeginCapture called but RenderDoc not loaded"); return false; } if (IsCapturing()) { Logger::Get().Warning(LogCategory::General, "BeginCapture called while already capturing"); return false; } if (!m_device || !m_window) { Logger::Get().Warning(LogCategory::General, "BeginCapture called with null device or window"); return false; } if (title) { m_api->SetCaptureTitle(title); } SetForegroundWindow((HWND)m_window); SetFocus((HWND)m_window); m_api->SetActiveWindow(m_device, m_window); m_api->StartFrameCapture(m_device, m_window); return true; } bool RenderDocCapture::EndCapture() { if (!m_isLoaded || !m_api) { Logger::Get().Warning(LogCategory::General, "EndCapture called but RenderDoc not loaded"); return false; } if (!IsCapturing()) { Logger::Get().Warning(LogCategory::General, "EndCapture called but not currently capturing"); return false; } m_api->EndFrameCapture(m_device, m_window); return true; } void RenderDocCapture::TriggerCapture() { if (!m_isLoaded || !m_api) { return; } m_api->TriggerCapture(); } void RenderDocCapture::SetCaptureFilePath(const char* path) { if (!m_isLoaded || !m_api) { return; } m_api->SetCaptureFilePathTemplate(path); } void RenderDocCapture::SetCaptureComments(const char* comments) { if (!m_isLoaded || !m_api) { return; } m_api->SetCaptureFileComments(nullptr, comments); } void RenderDocCapture::SetCaptureOptionU32(uint32_t option, uint32_t value) { if (!m_isLoaded || !m_api) { return; } m_api->SetCaptureOptionU32(option, value); } bool RenderDocCapture::LaunchReplayUI(uint32_t connect, const char* cmdline) { if (!m_isLoaded || !m_api) { Logger::Get().Warning(LogCategory::General, "LaunchReplayUI called but RenderDoc not loaded"); return false; } m_api->LaunchReplayUI(connect, cmdline); return true; } } // namespace Debug } // namespace XCEngine