RHI: Internalize OpenGL-specific methods in OpenGLDevice

- Remove GetTextureUnitAllocator/GetUniformBufferManager from public interface
- Remove SwapBuffers from public interface (friend OpenGLSwapChain can still access)
- Add MakeContextCurrent() and GetNativeContext() public methods
- Update integration tests to use MakeContextCurrent() instead of wglMakeCurrent
- Update RenderDoc calls to use GetNativeContext() instead of GetGLContext()
- Remove Device_SwapBuffers_NoErrors test (SwapBuffers no longer public)
- Mark Priority 7 as completed in RHI_Design_Issues.md
This commit is contained in:
2026-03-25 01:20:38 +08:00
parent 6328ac8d37
commit dc970d215b
8 changed files with 56 additions and 27 deletions

View File

@@ -402,9 +402,40 @@ virtual void ResourceBarrier(uint32_t count, const ResourceBarrier* barriers) =
详见第一版文档,此处不再赘述。
### 4.3 OpenGL 特有方法暴露
### 4.3 OpenGL 特有方法暴露 ✅ 已完成
详见第一版文档,此处不再赘述。
**实现状态**2026-03-25 已完成
**问题**OpenGLDevice 和 OpenGLCommandList 暴露了 OpenGL 特有方法,违反"上层只调用抽象接口"原则。
**修复内容**
1. **OpenGLDevice 内部化方法**
- 移除 `GetTextureUnitAllocator()``GetUniformBufferManager()` 公开访问(移到 private
- 移除 `SwapBuffers()` 公开方法OpenGLSwapChain 作为 friend 仍可访问)
- `GetPresentationDC()``GetGLContext()` 保留在 private通过 friend 访问
2. **新增抽象接口**
- `MakeContextCurrent()` - 封装 `wglMakeCurrent` 操作
- `GetNativeContext()` - 返回 GL Context 供 RenderDoc 使用
3. **保留的逃生舱方法**
- OpenGLCommandList 中的 `PrimitiveType` 相关方法是显式的 OpenGL 逃生舱
- 这些方法使用 OpenGL 特有类型,文档化为"backend-specific escape hatch"
- 抽象层正确使用 `PrimitiveTopology` 枚举
**修改的文件**
- `engine/include/XCEngine/RHI/OpenGL/OpenGLDevice.h` - 内部化特有方法,新增 MakeContextCurrent/GetNativeContext
- `engine/src/RHI/OpenGL/OpenGLDevice.cpp` - 实现 MakeContextCurrent
- `tests/RHI/OpenGL/unit/test_device.cpp` - 移除 SwapBuffers 测试
- `tests/RHI/OpenGL/integration/minimal/main.cpp` - 使用 MakeContextCurrent
- `tests/RHI/OpenGL/integration/triangle/main.cpp` - 使用 MakeContextCurrent
- `tests/RHI/OpenGL/integration/quad/main.cpp` - 使用 MakeContextCurrent
- `tests/RHI/OpenGL/integration/sphere/main.cpp` - 使用 MakeContextCurrent
**说明**
- `PrimitiveType` 枚举在 OpenGL 专用逃生舱方法中使用是可接受的,因为这些是显式的后端特定接口
- 抽象层正确使用 `PrimitiveTopology`,不存在类型泄漏问题
### 4.4 缺少 Compute Pipeline 抽象
@@ -562,7 +593,7 @@ class RHITexture : public RHIResource { ... };
| 4 | ResourceView 类型不明确 | 🟡 中 | 中 | ✅ 基本完成 |
| 5 | TransitionBarrier 针对 View 而非 Resource | 🟡 中 | 中 | ✅ 已完成 |
| 6 | SetGlobal* 空操作 | 🟡 中 | 低 | ✅ 已完成 |
| 7 | OpenGL 特有方法暴露 | 🟡 中 | 高 | ❌ 未完成 |
| 7 | OpenGL 特有方法暴露 | 🟡 中 | 高 | ✅ 已完成 |
| 8 | 缺少 Compute Pipeline 抽象 | 🟡 中 | 中 | ✅ 已完成 |
---

View File

@@ -29,14 +29,10 @@ public:
void Shutdown() override;
bool InitializeWithExistingWindow(HWND hwnd);
HDC GetPresentationDC() const { return m_hdc; }
HGLRC GetGLContext() const { return m_hglrc; }
const RHIDeviceInfo& GetDeviceInfoImpl() const { return m_deviceInfo; }
OpenGLTextureUnitAllocator* GetTextureUnitAllocator() { return m_textureUnitAllocator.get(); }
OpenGLUniformBufferManager* GetUniformBufferManager() { return m_uniformBufferManager.get(); }
void SwapBuffers();
bool MakeContextCurrent();
void* GetNativeContext() const { return m_hglrc; }
RHIBuffer* CreateBuffer(const BufferDesc& desc) override;
RHITexture* CreateTexture(const TextureDesc& desc) override;
@@ -66,6 +62,11 @@ public:
private:
friend class OpenGLSwapChain;
HDC GetPresentationDC() const { return m_hdc; }
OpenGLTextureUnitAllocator* GetTextureUnitAllocator() { return m_textureUnitAllocator.get(); }
OpenGLUniformBufferManager* GetUniformBufferManager() { return m_uniformBufferManager.get(); }
void SwapBuffers();
HWND m_hwnd = nullptr;
HDC m_hdc = nullptr;
HGLRC m_hglrc = nullptr;

View File

@@ -259,6 +259,13 @@ void OpenGLDevice::Shutdown() {
m_initialized = false;
}
bool OpenGLDevice::MakeContextCurrent() {
if (m_hdc && m_hglrc) {
return ::wglMakeCurrent(m_hdc, m_hglrc) == TRUE;
}
return false;
}
void OpenGLDevice::SwapBuffers() {
if (m_hdc) {
::SwapBuffers(m_hdc);

View File

@@ -91,7 +91,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
return -1;
}
RenderDocCapture::Get().SetDevice(device.GetGLContext());
RenderDocCapture::Get().SetDevice(device.GetNativeContext());
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
@@ -117,7 +117,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
TranslateMessage(&msg);
DispatchMessageW(&msg);
} else {
wglMakeCurrent(device.GetPresentationDC(), device.GetGLContext());
device.MakeContextCurrent();
commandList.SetViewport(0, 0, gWidth, gHeight);
commandList.Clear(1.0f, 0.0f, 0.0f, 1.0f, 1 | 2);

View File

@@ -95,7 +95,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
return -1;
}
RenderDocCapture::Get().SetDevice(device.GetGLContext());
RenderDocCapture::Get().SetDevice(device.GetNativeContext());
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
@@ -202,7 +202,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
TranslateMessage(&msg);
DispatchMessageW(&msg);
} else {
wglMakeCurrent(device.GetPresentationDC(), device.GetGLContext());
device.MakeContextCurrent();
commandList.SetViewport(0, 0, gWidth, gHeight);
commandList.Clear(0.0f, 0.0f, 1.0f, 1.0f, 1);

View File

@@ -174,7 +174,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
return -1;
}
RenderDocCapture::Get().SetDevice(device.GetGLContext());
RenderDocCapture::Get().SetDevice(device.GetNativeContext());
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
@@ -312,7 +312,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
TranslateMessage(&msg);
DispatchMessageW(&msg);
} else {
wglMakeCurrent(device.GetPresentationDC(), device.GetGLContext());
device.MakeContextCurrent();
renderCount++;
GLenum err = glGetError();

View File

@@ -91,7 +91,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
return -1;
}
RenderDocCapture::Get().SetDevice(device.GetGLContext());
RenderDocCapture::Get().SetDevice(device.GetNativeContext());
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
@@ -179,7 +179,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
TranslateMessage(&msg);
DispatchMessageW(&msg);
} else {
wglMakeCurrent(device.GetPresentationDC(), device.GetGLContext());
device.MakeContextCurrent();
commandList.SetViewport(0, 0, gWidth, gHeight);
commandList.Clear(0.0f, 0.0f, 1.0f, 1.0f, 1);

View File

@@ -22,14 +22,4 @@ TEST_F(OpenGLTestFixture, Device_GetDeviceInfo_ReturnsValid) {
EXPECT_FALSE(info.renderer.empty());
EXPECT_GE(info.majorVersion, 3);
EXPECT_GE(info.minorVersion, 0);
}
TEST_F(OpenGLTestFixture, Device_SwapBuffers_NoErrors) {
OpenGLDevice device;
device.InitializeWithExistingWindow(GetWindow());
device.SwapBuffers();
GLenum error = glGetError();
EXPECT_EQ(error, GL_NO_ERROR);
}