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:
@@ -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 抽象
|
### 4.4 缺少 Compute Pipeline 抽象
|
||||||
|
|
||||||
@@ -562,7 +593,7 @@ class RHITexture : public RHIResource { ... };
|
|||||||
| 4 | ResourceView 类型不明确 | 🟡 中 | 中 | ✅ 基本完成 |
|
| 4 | ResourceView 类型不明确 | 🟡 中 | 中 | ✅ 基本完成 |
|
||||||
| 5 | TransitionBarrier 针对 View 而非 Resource | 🟡 中 | 中 | ✅ 已完成 |
|
| 5 | TransitionBarrier 针对 View 而非 Resource | 🟡 中 | 中 | ✅ 已完成 |
|
||||||
| 6 | SetGlobal* 空操作 | 🟡 中 | 低 | ✅ 已完成 |
|
| 6 | SetGlobal* 空操作 | 🟡 中 | 低 | ✅ 已完成 |
|
||||||
| 7 | OpenGL 特有方法暴露 | 🟡 中 | 高 | ❌ 未完成 |
|
| 7 | OpenGL 特有方法暴露 | 🟡 中 | 高 | ✅ 已完成 |
|
||||||
| 8 | 缺少 Compute Pipeline 抽象 | 🟡 中 | 中 | ✅ 已完成 |
|
| 8 | 缺少 Compute Pipeline 抽象 | 🟡 中 | 中 | ✅ 已完成 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -29,14 +29,10 @@ public:
|
|||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
||||||
bool InitializeWithExistingWindow(HWND hwnd);
|
bool InitializeWithExistingWindow(HWND hwnd);
|
||||||
HDC GetPresentationDC() const { return m_hdc; }
|
|
||||||
HGLRC GetGLContext() const { return m_hglrc; }
|
|
||||||
const RHIDeviceInfo& GetDeviceInfoImpl() const { return m_deviceInfo; }
|
const RHIDeviceInfo& GetDeviceInfoImpl() const { return m_deviceInfo; }
|
||||||
|
|
||||||
OpenGLTextureUnitAllocator* GetTextureUnitAllocator() { return m_textureUnitAllocator.get(); }
|
bool MakeContextCurrent();
|
||||||
OpenGLUniformBufferManager* GetUniformBufferManager() { return m_uniformBufferManager.get(); }
|
void* GetNativeContext() const { return m_hglrc; }
|
||||||
|
|
||||||
void SwapBuffers();
|
|
||||||
|
|
||||||
RHIBuffer* CreateBuffer(const BufferDesc& desc) override;
|
RHIBuffer* CreateBuffer(const BufferDesc& desc) override;
|
||||||
RHITexture* CreateTexture(const TextureDesc& desc) override;
|
RHITexture* CreateTexture(const TextureDesc& desc) override;
|
||||||
@@ -66,6 +62,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
friend class OpenGLSwapChain;
|
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;
|
HWND m_hwnd = nullptr;
|
||||||
HDC m_hdc = nullptr;
|
HDC m_hdc = nullptr;
|
||||||
HGLRC m_hglrc = nullptr;
|
HGLRC m_hglrc = nullptr;
|
||||||
|
|||||||
@@ -259,6 +259,13 @@ void OpenGLDevice::Shutdown() {
|
|||||||
m_initialized = false;
|
m_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenGLDevice::MakeContextCurrent() {
|
||||||
|
if (m_hdc && m_hglrc) {
|
||||||
|
return ::wglMakeCurrent(m_hdc, m_hglrc) == TRUE;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLDevice::SwapBuffers() {
|
void OpenGLDevice::SwapBuffers() {
|
||||||
if (m_hdc) {
|
if (m_hdc) {
|
||||||
::SwapBuffers(m_hdc);
|
::SwapBuffers(m_hdc);
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderDocCapture::Get().SetDevice(device.GetGLContext());
|
RenderDocCapture::Get().SetDevice(device.GetNativeContext());
|
||||||
|
|
||||||
ShowWindow(hwnd, nShowCmd);
|
ShowWindow(hwnd, nShowCmd);
|
||||||
UpdateWindow(hwnd);
|
UpdateWindow(hwnd);
|
||||||
@@ -117,7 +117,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessageW(&msg);
|
DispatchMessageW(&msg);
|
||||||
} else {
|
} else {
|
||||||
wglMakeCurrent(device.GetPresentationDC(), device.GetGLContext());
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
commandList.SetViewport(0, 0, gWidth, gHeight);
|
commandList.SetViewport(0, 0, gWidth, gHeight);
|
||||||
commandList.Clear(1.0f, 0.0f, 0.0f, 1.0f, 1 | 2);
|
commandList.Clear(1.0f, 0.0f, 0.0f, 1.0f, 1 | 2);
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderDocCapture::Get().SetDevice(device.GetGLContext());
|
RenderDocCapture::Get().SetDevice(device.GetNativeContext());
|
||||||
|
|
||||||
ShowWindow(hwnd, nShowCmd);
|
ShowWindow(hwnd, nShowCmd);
|
||||||
UpdateWindow(hwnd);
|
UpdateWindow(hwnd);
|
||||||
@@ -202,7 +202,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessageW(&msg);
|
DispatchMessageW(&msg);
|
||||||
} else {
|
} else {
|
||||||
wglMakeCurrent(device.GetPresentationDC(), device.GetGLContext());
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
commandList.SetViewport(0, 0, gWidth, gHeight);
|
commandList.SetViewport(0, 0, gWidth, gHeight);
|
||||||
commandList.Clear(0.0f, 0.0f, 1.0f, 1.0f, 1);
|
commandList.Clear(0.0f, 0.0f, 1.0f, 1.0f, 1);
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderDocCapture::Get().SetDevice(device.GetGLContext());
|
RenderDocCapture::Get().SetDevice(device.GetNativeContext());
|
||||||
|
|
||||||
ShowWindow(hwnd, nShowCmd);
|
ShowWindow(hwnd, nShowCmd);
|
||||||
UpdateWindow(hwnd);
|
UpdateWindow(hwnd);
|
||||||
@@ -312,7 +312,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessageW(&msg);
|
DispatchMessageW(&msg);
|
||||||
} else {
|
} else {
|
||||||
wglMakeCurrent(device.GetPresentationDC(), device.GetGLContext());
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
renderCount++;
|
renderCount++;
|
||||||
GLenum err = glGetError();
|
GLenum err = glGetError();
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderDocCapture::Get().SetDevice(device.GetGLContext());
|
RenderDocCapture::Get().SetDevice(device.GetNativeContext());
|
||||||
|
|
||||||
ShowWindow(hwnd, nShowCmd);
|
ShowWindow(hwnd, nShowCmd);
|
||||||
UpdateWindow(hwnd);
|
UpdateWindow(hwnd);
|
||||||
@@ -179,7 +179,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessageW(&msg);
|
DispatchMessageW(&msg);
|
||||||
} else {
|
} else {
|
||||||
wglMakeCurrent(device.GetPresentationDC(), device.GetGLContext());
|
device.MakeContextCurrent();
|
||||||
|
|
||||||
commandList.SetViewport(0, 0, gWidth, gHeight);
|
commandList.SetViewport(0, 0, gWidth, gHeight);
|
||||||
commandList.Clear(0.0f, 0.0f, 1.0f, 1.0f, 1);
|
commandList.Clear(0.0f, 0.0f, 1.0f, 1.0f, 1);
|
||||||
|
|||||||
@@ -23,13 +23,3 @@ TEST_F(OpenGLTestFixture, Device_GetDeviceInfo_ReturnsValid) {
|
|||||||
EXPECT_GE(info.majorVersion, 3);
|
EXPECT_GE(info.majorVersion, 3);
|
||||||
EXPECT_GE(info.minorVersion, 0);
|
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);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user