Files
XCEngine/docs/RHI抽象层设计与实现.md
ssdfasd be72e2f4a7 Enhance OpenGL RTV and DSV with comprehensive framebuffer support
OpenGLRenderTargetView:
- Add RenderTargetType enum for different texture types
- Add RenderTargetViewDesc struct with mip level, array slice, layer info
- Add Initialize() with desc parameter for 2D/2DArray/3D/Cube
- Add InitializeCubemap() for cubemap faces
- Add Bind(count) overload for multiple framebuffers
- Add Clear() methods for color and depth-stencil
- Add static BindFramebuffer/UnbindFramebuffer methods

OpenGLDepthStencilView:
- Add DepthStencilType enum for different texture types
- Add DepthStencilViewDesc struct with mip level, array slice, layer info
- Add Initialize() with desc parameter for 2D/2DArray/Cube
- Add InitializeCubemap() for cubemap faces
- Add ClearDepth, ClearStencil, ClearDepthStencil methods
- Add static BindFramebuffer/UnbindFramebuffer methods
2026-03-17 02:20:56 +08:00

404 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 跨平台 RHI 渲染架构设计文档
## 1. 项目背景
本项目旨在参考 Unity 渲染架构,为已有的 **OpenGL****Direct3D 12** 图形 API 后端设计统一的**渲染硬件抽象层RHI**,屏蔽 API 差异,实现引擎上层逻辑与底层图形 API 的解耦。
### 现有项目结构
```
engine/
├── include/XCEngine/RHI/
│ ├── Enums.h # 通用枚举定义
│ ├── Types.h # 通用结构体定义
│ ├── D3D12/ # D3D12 后端实现
│ └── OpenGL/ # OpenGL 后端实现
└── src/RHI/
├── D3D12/ # D3D12 源码
└── OpenGL/ # OpenGL 源码
```
## 2. 核心设计理念
### 2.1 总体原则
**求同存异,分层抽象,特性降级,底层逃逸**
- **求同存异**:优先提取 API 共性作为核心抽象,差异部分通过模拟/降级处理
- **分层抽象**:通过清晰的层级结构隔离 API 差异
- **特性降级**:对高级特性提供能力检测和替代方案
- **底层逃逸**:允许直接访问原生 API 以满足极端需求
### 2.2 差异分类与处理策略
| 差异类型 | 典型示例 | 处理方案 |
|----------|----------|----------|
| 概念命名不同但本质相似 | D3D12 `CommandList` ≈ OpenGL 状态机绘制 | 直接统一抽象 |
| 显式控制 vs 隐式管理 | D3D12 `DescriptorHeap` vs OpenGL 纹理单元 | 提供"自动模式"+"显式模式" |
| API 独有高级特性 | D3D12 光线追踪、网格着色器 | 特性检测 + 降级方案 + 底层逃逸 |
## 3. RHI 分层架构
### 3.1 通用分层模型
```
┌─────────────────────────────────┐
│ 引擎功能层(场景/材质/光照) │
├─────────────────────────────────┤
│ 渲染管线层SRP/Render Graph
├─────────────────────────────────┤
│ RHI 抽象层(统一接口) │ ← 核心设计重点
├─────────────────────────────────┤
│ API 后端层D3D12/OpenGL
├─────────────────────────────────┤
│ 驱动/硬件层 │
└─────────────────────────────────┘
```
### 3.2 层级职责说明
1. **引擎功能层**:提供场景管理、材质系统、光照等高级功能接口
2. **渲染管线层**:定义渲染流程(前向/延迟渲染)
3. **RHI 抽象层**:统一图形 API 接口,屏蔽差异
4. **API 后端层**:针对具体 API 的实现
5. **驱动/硬件层**:最终执行渲染指令
## 4. RHI 抽象基类设计
### 4.1 目录结构调整建议
```
include/XCEngine/RHI/
├── RHIEnums.h # 通用枚举
├── RHITypes.h # 通用结构体
├── RHICapabilities.h # 硬件能力检测
├── RHIDevice.h # 设备抽象(核心入口)
├── RHICommandQueue.h # 命令队列抽象
├── RHICommandList.h # 命令列表抽象
├── RHIBuffer.h # 缓冲区抽象
├── RHITexture.h # 纹理抽象
├── RHIShader.h # 着色器抽象
├── RHIPipelineLayout.h # 管线布局抽象(替代 RootSignature
├── RHIPipelineState.h # 管线状态抽象
├── RHISwapChain.h # 交换链抽象
├── RHIFence.h # 同步栅栏抽象
├── RHIDescriptorPool.h # 描述符池抽象
└── RHIFactory.h # RHI 工厂类
```
### 4.2 核心抽象基类定义
#### 4.2.1 通用类型定义Types.h
```cpp
#pragma once
#include <cstdint>
// 通用资源格式
enum class RHIFormat {
R8G8B8A8_UNORM,
D32_FLOAT,
// ... 其他格式
};
// 缓冲区用途
enum class RHIBufferUsage {
VertexBuffer,
IndexBuffer,
ConstantBuffer,
// ... 其他用途
};
// 通用缓冲区描述
struct RHIBufferDesc {
uint64_t size;
RHIBufferUsage usage;
// ... 其他参数
};
// 通用纹理描述
struct RHITextureDesc {
uint32_t width;
uint32_t height;
RHIFormat format;
// ... 其他参数
};
// 通用渲染通道描述
struct RHIRenderPassDesc {
struct Attachment {
RHITexture* texture;
float clearColor[4];
// ... 其他参数
} colorAttachments[8];
uint32_t colorAttachmentCount;
Attachment depthStencilAttachment;
// ... 其他参数
};
```
#### 4.2.2 硬件能力检测RHICapabilities.h
```cpp
#pragma once
struct RHICapabilities {
bool bSupportsRayTracing = false;
bool bSupportsMeshShaders = false;
bool bSupportsExplicitMultiThreading = false;
// ... 其他特性
};
```
#### 4.2.3 设备抽象RHIDevice.h
```cpp
#pragma once
#include "Types.h"
#include "RHICapabilities.h"
class RHISwapChain;
class RHICommandQueue;
class RHIBuffer;
class RHITexture;
class RHIDevice {
public:
virtual ~RHIDevice() = default;
// 初始化设备
virtual bool Initialize(const RHIDeviceDesc& desc) = 0;
// 资源创建接口
virtual RHIBuffer* CreateBuffer(const RHIBufferDesc& desc) = 0;
virtual RHITexture* CreateTexture(const RHITextureDesc& desc) = 0;
virtual RHICommandQueue* CreateCommandQueue(const RHICommandQueueDesc& desc) = 0;
virtual RHISwapChain* CreateSwapChain(const RHISwapChainDesc& desc) = 0;
// 硬件能力查询
virtual const RHICapabilities& GetCapabilities() const = 0;
// 底层逃逸口(谨慎使用)
virtual void* GetNativeDevice() = 0;
// 清理
virtual void Shutdown() = 0;
};
```
#### 4.2.4 命令列表抽象RHICommandList.h
```cpp
#pragma once
#include "Types.h"
class RHIBuffer;
class RHITexture;
class RHIPipelineState;
class RHICommandList {
public:
virtual ~RHICommandList() = default;
// 命令录制
virtual void Begin() = 0;
virtual void End() = 0;
// 渲染通道
virtual void BeginRenderPass(const RHIRenderPassDesc& desc) = 0;
virtual void EndRenderPass() = 0;
// 状态设置
virtual void SetPipelineState(RHIPipelineState* pso) = 0;
virtual void SetVertexBuffers(uint32_t slot, RHIBuffer* const* buffers, uint32_t count) = 0;
virtual void SetIndexBuffer(RHIBuffer* buffer, RHIFormat format, uint32_t offset) = 0;
// 绘制命令
virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount,
uint32_t startIndex, int32_t baseVertex,
uint32_t startInstance) = 0;
// 资源拷贝
virtual void CopyBuffer(RHIBuffer* dst, RHIBuffer* src, uint64_t size) = 0;
};
```
#### 4.2.5 管线布局抽象RHIPipelineLayout.h
```cpp
#pragma once
#include "Types.h"
// 管线布局描述(统一描述资源绑定规则)
struct RHIPipelineLayoutDesc {
uint32_t constantBufferCount;
uint32_t textureCount;
uint32_t samplerCount;
// ... 其他参数
};
class RHIPipelineLayout {
public:
virtual ~RHIPipelineLayout() = default;
// 具体实现由后端处理
};
```
#### 4.2.6 RHI 工厂类RHIFactory.h
```cpp
#pragma once
#include "RHIDevice.h"
#include <string>
enum class RHIType {
D3D12,
OpenGL,
// 未来扩展 Vulkan/Metal
};
class RHIFactory {
public:
// 根据类型创建 RHI 设备
static RHIDevice* CreateRHIDevice(RHIType type);
// 根据字符串选择(从配置文件读取)
static RHIDevice* CreateRHIDevice(const std::string& typeName);
};
```
## 5. 核心差异处理方案
### 5.1 根签名 vs OpenGL 资源绑定
- **D3D12**:显式 `RootSignature` 定义资源绑定规则
- **OpenGL**:隐式通过 `glUniformLocation``glBindTextureUnit` 绑定
- **解决方案**
-`RHIPipelineLayout` 统一抽象
- D3D12 后端:内部创建 `ID3D12RootSignature`
- OpenGL 后端:存储绑定点数量,绘制时自动调用 `glBind*`
### 5.2 描述符堆 vs OpenGL 纹理单元
- **D3D12**:显式 `DescriptorHeap` 管理资源视图
- **OpenGL**:隐式通过 `glActiveTexture` 绑定
- **解决方案**
-`RHIDescriptorPool` 统一抽象
- 提供"自动模式"(默认)和"显式模式"(可选)
- D3D12 后端:从堆分配槽位,更新描述符
- OpenGL 后端:维护绑定点计数器,绘制时自动绑定
### 5.3 多线程命令录制
- **D3D12**:原生支持多线程录制不同 `CommandList`
- **OpenGL**:状态机模型,单线程上下文
- **解决方案**
- 抽象层统一提供多线程接口
- D3D12 后端:真·并行提交
- OpenGL 后端:命令缓冲队列,单线程回放
### 5.4 高级特性(光线追踪等)
- **解决方案**
1. **特性检测**:通过 `RHICapabilities` 查询支持情况
2. **降级方案**:不支持时用传统路径替代
3. **底层逃逸**:通过 `GetNativeDevice()` 直接访问原生 API
## 6. 后端实现示例
### 6.1 D3D12 设备实现D3D12Device.h
```cpp
#pragma once
#include "../RHIDevice.h"
#include "D3D12Common.h"
class D3D12Device : public RHIDevice {
public:
virtual bool Initialize(const RHIDeviceDesc& desc) override;
virtual RHIBuffer* CreateBuffer(const RHIBufferDesc& desc) override;
virtual RHITexture* CreateTexture(const RHITextureDesc& desc) override;
virtual RHICommandQueue* CreateCommandQueue(const RHICommandQueueDesc& desc) override;
virtual RHISwapChain* CreateSwapChain(const RHISwapChainDesc& desc) override;
virtual const RHICapabilities& GetCapabilities() const override;
virtual void* GetNativeDevice() override { return m_pd3d12Device; }
virtual void Shutdown() override;
// D3D12 特有接口
ID3D12Device* GetD3D12Device() const { return m_pd3d12Device; }
private:
ID3D12Device* m_pd3d12Device = nullptr;
ID3D12CommandQueue* m_pd3d12CommandQueue = nullptr;
RHICapabilities m_capabilities;
};
```
### 6.2 OpenGL 设备实现OpenGLDevice.h
```cpp
#pragma once
#include "../RHIDevice.h"
#include "OpenGLCommon.h"
class OpenGLDevice : public RHIDevice {
public:
virtual bool Initialize(const RHIDeviceDesc& desc) override;
virtual RHIBuffer* CreateBuffer(const RHIBufferDesc& desc) override;
virtual RHITexture* CreateTexture(const RHITextureDesc& desc) override;
virtual RHICommandQueue* CreateCommandQueue(const RHICommandQueueDesc& desc) override;
virtual RHISwapChain* CreateSwapChain(const RHISwapChainDesc& desc) override;
virtual const RHICapabilities& GetCapabilities() const override;
virtual void* GetNativeDevice() override { return m_context; }
virtual void Shutdown() override;
// OpenGL 特有接口
HGLRC GetContext() const { return m_context; }
private:
HGLRC m_context = nullptr;
RHICapabilities m_capabilities;
};
```
## 7. 测试用例示例
### 7.1 最小渲染循环测试
```cpp
#include "XCEngine/RHI/RHIFactory.h"
#include "XCEngine/RHI/RHIDevice.h"
#include "XCEngine/RHI/RHISwapChain.h"
#include "XCEngine/RHI/RHICommandList.h"
int main() {
// 1. 创建 RHI 设备(可切换 D3D12/OpenGL
RHIDevice* pDevice = RHIFactory::CreateRHIDevice(RHIType::D3D12);
pDevice->Initialize(RHIDeviceDesc{...});
// 2. 创建交换链和命令队列
RHISwapChain* pSwapChain = pDevice->CreateSwapChain(RHISwapChainDesc{...});
RHICommandQueue* pCommandQueue = pDevice->CreateCommandQueue(RHICommandQueueDesc{...});
RHICommandList* pCommandList = pDevice->CreateCommandList(RHICommandListDesc{...});
// 3. 渲染循环
while (!ShouldQuit()) {
// 录制命令
pCommandList->Begin();
// 清屏
RHIRenderPassDesc renderPassDesc = {};
renderPassDesc.colorAttachments[0].texture = pSwapChain->GetCurrentBackBuffer();
renderPassDesc.colorAttachments[0].loadOp = RHIRenderPassLoadOp::Clear;
renderPassDesc.colorAttachments[0].clearColor = {0.2f, 0.4f, 0.8f, 1.0f};
pCommandList->BeginRenderPass(renderPassDesc);
pCommandList->EndRenderPass();
// 提交命令
pCommandList->End();
pCommandQueue->SubmitCommandList(pCommandList);
// 呈现
pSwapChain->Present();
}
// 4. 清理
pDevice->Shutdown();
delete pDevice;
return 0;
}
```
## 8. 下一步行动指南
1. **补全抽象基类**:重点实现 `RHIDevice``RHICommandList``RHIPipelineLayout`
2. **改造现有后端**:让 `D3D12Device``OpenGLDevice` 继承抽象基类并实现接口
3. **实现工厂类**:完成 `RHIFactory` 以支持动态切换后端
4. **测试验证**:用最小渲染循环测试 D3D12 和 OpenGL 后端
5. **扩展功能**:逐步添加资源管理、着色器跨平台、多线程渲染等功能
## 9. 关键注意事项
- **上层只调用抽象接口**:绝不直接访问 D3D12/OpenGL 特有类
- **合理使用底层逃逸**:仅在必要时使用 `GetNativeDevice()`,并注明破坏跨平台性
- **优先保证核心功能**:先实现 90% 常用功能的统一抽象,再处理高级特性
- **保持设计可扩展**:为未来支持 Vulkan/Metal 预留空间
需要我帮你细化某个具体模块的实现代码吗?