Fix RenderDoc OpenGL capture - pass HGLRC instead of HDC

Critical fix: For OpenGL, RenderDoc requires HGLRC (OpenGL context) as
the device pointer, not HDC. Previously OpenGL test incorrectly passed
HDC which caused capture to silently fail (NumCaptures=0).

Changes:
- OpenGLDevice: Add wglCreateContextAttribsARB support for debug context
- OpenGLDevice: Create OpenGL 4.6 core profile with debug flag
- RenderDocCapture: Pass correct window to SetActiveWindow/StartFrameCapture
- OpenGL test: Pass HGLRC via SetDevice(), use BeginCapture/EndCapture

Fix root cause identified via RenderDoc docs analysis:
  'For OpenGL it must be the HGLRC, GLXContext, or EGLContext'
This commit is contained in:
2026-03-23 18:35:49 +08:00
parent e9f4f2dc49
commit 36683b4bb3
3 changed files with 112 additions and 5 deletions

View File

@@ -122,14 +122,19 @@ void RenderDocCapture::BeginCapture(const char* title) {
if (title) {
m_api->SetCaptureTitle(title);
}
m_api->StartFrameCapture(m_device, nullptr);
SetForegroundWindow((HWND)m_window);
SetFocus((HWND)m_window);
m_api->SetActiveWindow(m_device, m_window);
m_api->StartFrameCapture(m_device, m_window);
}
void RenderDocCapture::EndCapture() {
if (!m_isLoaded || !m_api) {
return;
}
m_api->EndFrameCapture(m_device, nullptr);
m_api->EndFrameCapture(m_device, m_window);
}
void RenderDocCapture::TriggerCapture() {

View File

@@ -14,10 +14,26 @@
#include "XCEngine/RHI/OpenGL/OpenGLCommandList.h"
#include "XCEngine/RHI/OpenGL/OpenGLCommandQueue.h"
#include "XCEngine/RHI/OpenGL/OpenGLSwapChain.h"
#include "XCEngine/Debug/Logger.h"
static bool s_windowClassRegistered = false;
static const wchar_t kWindowClassName[] = L"XCEngine_OpenGL_WindowClass";
typedef const char* (WINAPI* PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC hdc);
typedef BOOL (WINAPI* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats);
typedef HGLRC (WINAPI* PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hdc, HGLRC hShareContext, const int* attribList);
static PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = nullptr;
static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = nullptr;
static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr;
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_FLAGS_ARB 0x2094
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x0001
namespace XCEngine {
namespace RHI {
@@ -135,13 +151,60 @@ bool OpenGLDevice::InitializeWithExistingWindow(HWND hwnd) {
return false;
}
m_hglrc = wglCreateContext(m_hdc);
if (!m_hglrc) {
HGLRC tempRC = wglCreateContext(m_hdc);
if (!tempRC) {
ReleaseDC(m_hwnd, m_hdc);
m_hdc = nullptr;
return false;
}
if (!wglMakeCurrent(m_hdc, tempRC)) {
wglDeleteContext(tempRC);
ReleaseDC(m_hwnd, m_hdc);
m_hdc = nullptr;
return false;
}
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB) {
const char* extensions = wglGetExtensionsStringARB(m_hdc);
if (extensions && strstr(extensions, "WGL_ARB_pixel_format")) {
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
}
if (extensions && strstr(extensions, "WGL_ARB_create_context")) {
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
}
}
wglMakeCurrent(nullptr, nullptr);
wglDeleteContext(tempRC);
if (wglCreateContextAttribsARB) {
int debugAttribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, 6,
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0, 0
};
m_hglrc = wglCreateContextAttribsARB(m_hdc, nullptr, debugAttribs);
if (m_hglrc) {
XCEngine::Debug::Logger::Get().Info(XCEngine::Debug::LogCategory::General, "Created OpenGL debug context with WGL_ARB_create_context");
}
}
if (!m_hglrc) {
m_hglrc = wglCreateContext(m_hdc);
if (m_hglrc) {
XCEngine::Debug::Logger::Get().Warning(XCEngine::Debug::LogCategory::General, "Created OpenGL context without debug bit (wglCreateContextAttribsARB failed)");
} else {
ReleaseDC(m_hwnd, m_hdc);
m_hdc = nullptr;
return false;
}
}
if (!wglMakeCurrent(m_hdc, m_hglrc)) {
wglDeleteContext(m_hglrc);
ReleaseDC(m_hwnd, m_hdc);
@@ -159,6 +222,14 @@ bool OpenGLDevice::InitializeWithExistingWindow(HWND hwnd) {
return false;
}
GLint contextFlags = 0;
glGetIntegerv(GL_CONTEXT_FLAGS, &contextFlags);
if (contextFlags & GL_CONTEXT_FLAG_DEBUG_BIT) {
XCEngine::Debug::Logger::Get().Info(XCEngine::Debug::LogCategory::General, "OpenGL debug context is active");
} else {
XCEngine::Debug::Logger::Get().Warning(XCEngine::Debug::LogCategory::General, "OpenGL debug context is NOT active");
}
const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
const char* renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
const char* version = reinterpret_cast<const char*>(glGetString(GL_VERSION));