2026-03-17 02:17:41 +08:00
|
|
|
|
# 跨平台 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/
|
2026-03-17 02:20:56 +08:00
|
|
|
|
├── RHIEnums.h # 通用枚举
|
|
|
|
|
|
├── RHITypes.h # 通用结构体
|
2026-03-17 02:17:41 +08:00
|
|
|
|
├── 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. 核心差异处理方案
|
2026-03-17 17:26:41 +08:00
|
|
|
|
|
|
|
|
|
|
### 5.1 缓冲区(RHIBuffer)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.1.1 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12Buffer | OpenGLBuffer | 处理方案 |
|
|
|
|
|
|
|------|-------------|--------------|----------|
|
|
|
|
|
|
| 初始化参数 | 需要 device + heapType | 不需要 | 后端各自实现初始化逻辑 |
|
|
|
|
|
|
| 句柄类型 | `ID3D12Resource*` | `GLuint` | 统一返回 `void*`,底层逃逸 |
|
|
|
|
|
|
| Map/Unmap | `Map()` / `Unmap()` | `glMapBuffer` | 后端各自实现 |
|
|
|
|
|
|
| 上传数据 | `UpdateData()` | `SetData()` | 统一为 `SetData()` |
|
|
|
|
|
|
| 获取大小 | `GetSize()` | `GetSize()` | 通用 |
|
|
|
|
|
|
| Vertex Stride | 显式存储 `m_stride` | VAO 管理 | 基类提供接口 |
|
|
|
|
|
|
| 资源状态 | `ResourceStates` 显式管理 | 无 | D3D12 维护,OpenGL 透明 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.1.2 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// engine/include/XCEngine/RHI/RHIBuffer.h
|
|
|
|
|
|
class RHIBuffer {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHIBuffer() = default;
|
|
|
|
|
|
|
|
|
|
|
|
// 数据操作
|
|
|
|
|
|
virtual void* Map() = 0;
|
|
|
|
|
|
virtual void Unmap() = 0;
|
|
|
|
|
|
virtual void SetData(const void* data, size_t size, size_t offset = 0) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 属性查询
|
|
|
|
|
|
virtual uint64_t GetSize() const = 0;
|
|
|
|
|
|
virtual BufferType GetBufferType() const = 0;
|
|
|
|
|
|
virtual void SetBufferType(BufferType type) = 0;
|
|
|
|
|
|
virtual uint32_t GetStride() const = 0;
|
|
|
|
|
|
virtual void SetStride(uint32_t stride) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 底层逃逸
|
|
|
|
|
|
virtual void* GetNativeHandle() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 调试
|
|
|
|
|
|
virtual const std::string& GetName() const = 0;
|
|
|
|
|
|
virtual void SetName(const std::string& name) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 生命周期
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.1.3 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **初始化参数差异**
|
|
|
|
|
|
- D3D12:在 `CreateBuffer()` 时由 Device 传入 device 参数,内部调用 `Initialize(device, size, ...)`
|
|
|
|
|
|
- OpenGL:直接调用 `Initialize(type, size, data, dynamic)`,不需要 device
|
|
|
|
|
|
|
|
|
|
|
|
2. **句柄类型差异**
|
|
|
|
|
|
- `GetNativeHandle()` 返回 `void*`
|
|
|
|
|
|
- D3D12 后端:`return m_resource.Get();`
|
|
|
|
|
|
- OpenGL 后端:`return (void*)(uintptr_t)m_buffer;`
|
|
|
|
|
|
|
|
|
|
|
|
3. **Vertex Stride**
|
|
|
|
|
|
- D3D12:显式存储在 `m_stride`
|
|
|
|
|
|
- OpenGL:在 VertexArray 中管理,可在基类中提供接口
|
|
|
|
|
|
|
|
|
|
|
|
4. **Device 创建接口**
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
// RHIDevice 中
|
|
|
|
|
|
virtual RHIBuffer* CreateBuffer(const BufferDesc& desc) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// D3D12Device 实现
|
|
|
|
|
|
RHIBuffer* CreateBuffer(const BufferDesc& desc) override {
|
|
|
|
|
|
auto* buffer = new D3D12Buffer();
|
|
|
|
|
|
buffer->Initialize(m_device.Get(), desc.size, ...);
|
|
|
|
|
|
return buffer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// OpenGLDevice 实现
|
|
|
|
|
|
RHIBuffer* CreateBuffer(const BufferDesc& desc) override {
|
|
|
|
|
|
auto* buffer = new OpenGLBuffer();
|
|
|
|
|
|
buffer->Initialize(glType, desc.size, ...);
|
|
|
|
|
|
return buffer;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5.2 纹理(RHITexture)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.2.1 设计理念对应
|
|
|
|
|
|
|
|
|
|
|
|
| 差异点 | 设计理念 | 处理方案 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| 初始化参数差异 | 求同存异 | 后端各自实现初始化,基类定义统一创建接口 |
|
|
|
|
|
|
| 句柄类型差异 | 底层逃逸 | 统一返回 void*,通过 GetNativeHandle() 获取原生类型 |
|
|
|
|
|
|
| 资源状态管理 | 特性降级 | D3D12 显式管理 ResourceStates,OpenGL 无需管理(透明) |
|
|
|
|
|
|
| 格式枚举差异 | 求同存异 | 基类统一 Format 枚举,后端映射到各自格式 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.2.2 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12Texture | OpenGLTexture | 处理方案 |
|
|
|
|
|
|
|------|--------------|---------------|----------|
|
|
|
|
|
|
| 初始化参数 | device + resource desc | type + dimensions + format | 后端各自实现 |
|
|
|
|
|
|
| 句柄类型 | `ID3D12Resource*` | `GLuint` | 统一返回 `void*` |
|
|
|
|
|
|
| 尺寸获取 | GetWidth/Height/Depth | 同上 | 统一接口 |
|
|
|
|
|
|
| Mip Levels | GetMipLevels() | GetMipLevels() | 通用 |
|
|
|
|
|
|
| 格式 | DXGI_FORMAT | OpenGLFormat | 基类统一 Format |
|
|
|
|
|
|
| 纹理类型 | TextureType enum | OpenGLTextureType enum | 基类统一 TextureType |
|
|
|
|
|
|
| 绑定 | 通过 DescriptorHeap | glBindTexture | 后端实现 Bind() |
|
|
|
|
|
|
| Mipmap 生成 | 需手动计算 | glGenerateMipmap | 后端实现 |
|
|
|
|
|
|
| 资源状态 | ResourceStates | 无 | D3D12 维护,OpenGL 透明 |
|
|
|
|
|
|
| 深度纹理 | InitializeDepthStencil() | 普通纹理 | 后端实现 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.2.3 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class RHITexture {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHITexture() = default;
|
|
|
|
|
|
|
|
|
|
|
|
// 属性(求同存异)
|
|
|
|
|
|
virtual uint32_t GetWidth() const = 0;
|
|
|
|
|
|
virtual uint32_t GetHeight() const = 0;
|
|
|
|
|
|
virtual uint32_t GetDepth() const = 0;
|
|
|
|
|
|
virtual uint32_t GetMipLevels() const = 0;
|
|
|
|
|
|
virtual Format GetFormat() const = 0;
|
|
|
|
|
|
virtual TextureType GetTextureType() const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 资源状态(特性降级)
|
|
|
|
|
|
virtual ResourceStates GetState() const = 0;
|
|
|
|
|
|
virtual void SetState(ResourceStates state) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 底层逃逸
|
|
|
|
|
|
virtual void* GetNativeHandle() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 调试
|
|
|
|
|
|
virtual const std::string& GetName() const = 0;
|
|
|
|
|
|
virtual void SetName(const std::string& name) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 生命周期
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.2.4 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **初始化参数差异(求同存异)**
|
|
|
|
|
|
- D3D12:需要 device + resource desc
|
|
|
|
|
|
- OpenGL:需要 type + dimensions + format
|
|
|
|
|
|
- 解决:Device 的 CreateTexture() 统一接收 TextureDesc,后端各自实现 Initialize()
|
|
|
|
|
|
|
|
|
|
|
|
2. **句柄类型差异(底层逃逸)**
|
|
|
|
|
|
- `GetNativeHandle()` 返回 `void*`
|
|
|
|
|
|
- D3D12:`return m_resource.Get();`
|
|
|
|
|
|
- OpenGL:`return reinterpret_cast<void*>(static_cast<uintptr_t>(m_texture));`
|
|
|
|
|
|
|
|
|
|
|
|
3. **资源状态管理(特性降级)**
|
|
|
|
|
|
- D3D12:显式 ResourceStates 管理,需要转换 barrier
|
|
|
|
|
|
- OpenGL:无资源状态概念
|
|
|
|
|
|
- 解决:基类提供 GetState/SetState,D3D12 实现具体逻辑,OpenGL 空实现
|
|
|
|
|
|
|
|
|
|
|
|
4. **格式枚举差异(求同存异)**
|
|
|
|
|
|
- D3D12:DXGI_FORMAT
|
|
|
|
|
|
- OpenGL:OpenGLFormat
|
|
|
|
|
|
- 解决:基类统一使用 Format 枚举,后端内部映射
|
|
|
|
|
|
|
|
|
|
|
|
### 5.7 着色器(RHIShader)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.7.1 设计理念对应
|
|
|
|
|
|
|
|
|
|
|
|
| 差异点 | 设计理念 | 处理方案 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| 编译方式差异 | 求同存异 | 统一 Compile 接口,后端各自实现 |
|
|
|
|
|
|
| 句柄类型差异 | 底层逃逸 | 统一返回 void* |
|
|
|
|
|
|
| Uniform 设置 | 特性降级 | OpenGL 实现,D3D12 空实现 |
|
|
|
|
|
|
| 绑定方式 | 求同存异 | 基类提供 Bind/Unbind,后端实现 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.7.2 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12Shader | OpenGLShader | 处理方案 |
|
|
|
|
|
|
|------|-------------|--------------|----------|
|
|
|
|
|
|
| 编译 | CompileFromFile/Compile | 同上 | 统一接口 |
|
|
|
|
|
|
| 字节码/Program | ID3DBlob | GLuint | 统一 void* |
|
|
|
|
|
|
| 类型 | ShaderType | 自有 enum | 基类统一 |
|
|
|
|
|
|
| Uniform 设置 | 无 | SetInt/SetFloat... | OpenGL 实现,D3D12 空 |
|
|
|
|
|
|
| 绑定 | 通过 CommandList | Use()/Bind() | 基类提供 Bind/Unbind |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.7.3 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class RHIShader {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHIShader() = default;
|
|
|
|
|
|
|
|
|
|
|
|
// 编译(求同存异)
|
|
|
|
|
|
virtual bool CompileFromFile(const wchar_t* filePath, const char* entryPoint, const char* target) = 0;
|
|
|
|
|
|
virtual bool Compile(const void* sourceData, size_t sourceSize, const char* entryPoint, const char* target) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 属性
|
|
|
|
|
|
virtual ShaderType GetType() const = 0;
|
|
|
|
|
|
virtual bool IsValid() const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 绑定(求同存异)
|
|
|
|
|
|
virtual void Bind() = 0;
|
|
|
|
|
|
virtual void Unbind() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 底层逃逸
|
|
|
|
|
|
virtual void* GetNativeHandle() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// Uniform 设置(特性降级)
|
|
|
|
|
|
virtual void SetInt(const char* name, int value) = 0;
|
|
|
|
|
|
virtual void SetFloat(const char* name, float value) = 0;
|
|
|
|
|
|
virtual void SetVec3(const char* name, float x, float y, float z) = 0;
|
|
|
|
|
|
virtual void SetVec4(const char* name, float x, float y, float z, float w) = 0;
|
|
|
|
|
|
virtual void SetMat4(const char* name, const float* value) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 生命周期
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.7.4 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **编译方式差异(求同存异)**
|
|
|
|
|
|
- D3D12:需要 entry point + target(如 "vs_6_0")
|
|
|
|
|
|
- OpenGL:根据 source 类型自动判断
|
|
|
|
|
|
- 解决:统一 Compile 接口,后端各自处理
|
|
|
|
|
|
|
|
|
|
|
|
2. **句柄类型差异(底层逃逸)**
|
|
|
|
|
|
- D3D12:ID3DBlob
|
|
|
|
|
|
- OpenGL:GLuint (program)
|
|
|
|
|
|
- 解决:GetNativeHandle() 返回 void*
|
|
|
|
|
|
|
|
|
|
|
|
3. **Uniform 设置(特性降级)**
|
|
|
|
|
|
- D3D12:通过 RootSignature/CBV 设置,不在 Shader 类
|
|
|
|
|
|
- OpenGL:通过 glUniform* 设置
|
|
|
|
|
|
- 解决:D3D12 实现为空,OpenGL 实现具体逻辑
|
|
|
|
|
|
|
|
|
|
|
|
4. **绑定方式**
|
|
|
|
|
|
- D3D12:通过 CommandList->SetPipelineState
|
|
|
|
|
|
- OpenGL:glUseProgram
|
2026-03-17 17:31:32 +08:00
|
|
|
|
- 解决:基类提供 Bind/Unbind 接口
|
2026-03-17 17:26:41 +08:00
|
|
|
|
|
2026-03-17 17:31:32 +08:00
|
|
|
|
### 5.8 采样器(RHISampler)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.8.1 设计理念对应
|
|
|
|
|
|
|
|
|
|
|
|
| 差异点 | 设计理念 | 处理方案 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| 初始化参数差异 | 求同存异 | 后端各自实现初始化 |
|
|
|
|
|
|
| 句柄类型差异 | 底层逃逸 | 统一返回 void* |
|
|
|
|
|
|
| 绑定方式 | 求同存异 | 基类提供 Bind/Unbind |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.8.2 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12Sampler | OpenGLSampler |
|
|
|
|
|
|
|------|--------------|---------------|
|
|
|
|
|
|
| 初始化 | Initialize(device, desc) | Initialize(desc) |
|
|
|
|
|
|
| 销毁 | Shutdown() | Shutdown() |
|
|
|
|
|
|
| 绑定 | 通过 DescriptorHeap | Bind(unit) |
|
|
|
|
|
|
| 句柄 | GetNativeHandle() | GetID() |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.8.3 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class RHISampler {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHISampler() = default;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Bind(unsigned int unit) = 0;
|
|
|
|
|
|
virtual void Unbind(unsigned int unit) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void* GetNativeHandle() = 0;
|
|
|
|
|
|
virtual unsigned int GetID() = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.8.4 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **初始化参数差异(求同存异)**
|
|
|
|
|
|
- D3D12:需要 device 参数
|
|
|
|
|
|
- OpenGL:不需要 device
|
|
|
|
|
|
- 解决:Device 的 CreateSampler() 统一接收 SamplerDesc,后端各自实现 Initialize()
|
|
|
|
|
|
|
|
|
|
|
|
2. **句柄类型差异(底层逃逸)**
|
|
|
|
|
|
- D3D12:通过 DescriptorHeap 管理
|
|
|
|
|
|
- OpenGL:GLuint
|
|
|
|
|
|
- 解决:GetNativeHandle() 返回 void*
|
|
|
|
|
|
|
2026-03-17 17:36:17 +08:00
|
|
|
|
### 5.9 同步栅栏(RHIFence)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.9.1 设计理念对应
|
|
|
|
|
|
|
|
|
|
|
|
| 差异点 | 设计理念 | 处理方案 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| 初始化参数差异 | 求同存异 | 后端各自实现初始化 |
|
|
|
|
|
|
| 句柄类型差异 | 底层逃逸 | 统一返回 void* |
|
|
|
|
|
|
| 状态查询 | 求同存异 | 统一 IsSignaled/GetCompletedValue 接口 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.9.2 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12Fence | OpenGLFence |
|
|
|
|
|
|
|------|-------------|-------------|
|
|
|
|
|
|
| 初始化 | Initialize(device, value) | Initialize(signaled) |
|
|
|
|
|
|
| Signal | Signal(value) | Signal()/Signal(value) |
|
|
|
|
|
|
| Wait | Wait(value) | Wait(timeoutNs) |
|
|
|
|
|
|
| 状态 | GetCompletedValue() | IsSignaled()/GetStatus() |
|
|
|
|
|
|
| 句柄 | ID3D12Fence* | GLsync |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.9.3 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class RHIFence {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHIFence() = default;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Signal(uint64_t value) = 0;
|
|
|
|
|
|
virtual void Wait(uint64_t value) = 0;
|
|
|
|
|
|
virtual uint64_t GetCompletedValue() = 0;
|
|
|
|
|
|
virtual bool IsSignaled() const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void* GetNativeHandle() = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.9.4 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **初始化参数差异(求同存异)**
|
|
|
|
|
|
- D3D12:需要 device 参数
|
|
|
|
|
|
- OpenGL:不需要 device
|
|
|
|
|
|
- 解决:后端各自实现 Initialize()
|
|
|
|
|
|
|
|
|
|
|
|
2. **句柄类型差异(底层逃逸)**
|
|
|
|
|
|
- D3D12:ID3D12Fence*
|
|
|
|
|
|
- OpenGL:GLsync
|
|
|
|
|
|
- 解决:GetNativeHandle() 返回 void*
|
|
|
|
|
|
|
2026-03-17 17:45:01 +08:00
|
|
|
|
### 5.10 设备(RHIDevice)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.10.1 设计理念对应
|
|
|
|
|
|
|
|
|
|
|
|
| 差异点 | 设计理念 | 处理方案 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| 初始化参数差异 | 求同存异 | 统一 Initialize 接口,后端各自处理 |
|
|
|
|
|
|
| 工厂方法差异 | 特性降级 | D3D12 实现,OpenGL 返回 nullptr |
|
|
|
|
|
|
| 窗口管理差异 | 特性降级 | OpenGL 有,D3D12 通过 SwapChain 处理 |
|
|
|
|
|
|
| 适配器枚举差异 | 特性降级 | D3D12 实现,OpenGL 空实现 |
|
|
|
|
|
|
| 底层设备类型差异 | 底层逃逸 | 统一返回 void* |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.10.2 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12Device | OpenGLDevice | 处理方案 |
|
|
|
|
|
|
|------|--------------|---------------|----------|
|
|
|
|
|
|
| 初始化 | Initialize(debugLayer) | CreateRenderWindow/InitializeWithExistingWindow | 统一 Initialize |
|
|
|
|
|
|
| 关闭 | Shutdown() | Shutdown() | 统一 |
|
|
|
|
|
|
| 获取设备 | GetDevice() | 无 | GetNativeHandle 统一 |
|
|
|
|
|
|
| 适配器信息 | GetAdapterInfo() | GetDeviceInfo() | 统一 GetDeviceInfo |
|
|
|
|
|
|
| 工厂方法 | CreateBuffer/Texture/Shader... | 无 | OpenGL 返回 nullptr |
|
|
|
|
|
|
| 窗口管理 | 通过 SwapChain | GetWindow/SwapBuffers/PollEvents | OpenGL 有,D3D12 无 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.10.3 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class RHIDevice {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHIDevice() = default;
|
|
|
|
|
|
|
|
|
|
|
|
virtual bool Initialize(const RHIDeviceDesc& desc) = 0;
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual const RHIDeviceInfo& GetDeviceInfo() const = 0;
|
|
|
|
|
|
virtual const RHICapabilities& GetCapabilities() const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual RHIBuffer* CreateBuffer(const BufferDesc& desc) = 0;
|
|
|
|
|
|
virtual RHITexture* CreateTexture(const TextureDesc& desc) = 0;
|
|
|
|
|
|
virtual RHIShader* CompileShader(const ShaderCompileDesc& desc) = 0;
|
|
|
|
|
|
virtual RHISampler* CreateSampler(const SamplerDesc& desc) = 0;
|
|
|
|
|
|
virtual RHIFence* CreateFence(const FenceDesc& desc) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void* GetNativeDevice() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void* GetNativeHandle() const = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.10.4 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **初始化参数差异(求同存异)**
|
|
|
|
|
|
- D3D12:`Initialize(enableDebugLayer)`
|
|
|
|
|
|
- OpenGL:`CreateRenderWindow` / `InitializeWithExistingWindow`
|
|
|
|
|
|
- 解决:统一 `Initialize(const RHIDeviceDesc& desc)` 接口,Desc 中包含窗口参数
|
|
|
|
|
|
|
|
|
|
|
|
2. **工厂方法差异(特性降级)**
|
|
|
|
|
|
- D3D12:有完整的工厂方法
|
|
|
|
|
|
- OpenGL:资源直接用 glGen* 创建,没有工厂方法
|
|
|
|
|
|
- 解决:OpenGL 后端返回 nullptr,上层需直接创建 OpenGL 资源
|
|
|
|
|
|
|
|
|
|
|
|
3. **窗口管理差异(特性降级)**
|
|
|
|
|
|
- OpenGL:直接管理窗口,有 GetWindow/SwapBuffers/PollEvents
|
|
|
|
|
|
- D3D12:通过 SwapChain 处理
|
|
|
|
|
|
- 解决:OpenGL 提供窗口管理接口,D3D12 空实现
|
|
|
|
|
|
|
|
|
|
|
|
4. **适配器枚举差异(特性降级)**
|
|
|
|
|
|
- D3D12:支持 EnumerateAdapters
|
|
|
|
|
|
- OpenGL:无此概念
|
|
|
|
|
|
- 解决:D3D12 实现具体功能,OpenGL 返回空
|
|
|
|
|
|
|
|
|
|
|
|
5. **底层设备类型差异(底层逃逸)**
|
|
|
|
|
|
- D3D12:ID3D12Device*
|
|
|
|
|
|
- OpenGL:无对等概念
|
|
|
|
|
|
- 解决:GetNativeDevice() 返回 void*,OpenGL 返回 nullptr 或窗口句柄
|
2026-03-17 02:17:41 +08:00
|
|
|
|
- **D3D12**:显式 `RootSignature` 定义资源绑定规则
|
|
|
|
|
|
- **OpenGL**:隐式通过 `glUniformLocation`、`glBindTextureUnit` 绑定
|
|
|
|
|
|
- **解决方案**:
|
|
|
|
|
|
- 用 `RHIPipelineLayout` 统一抽象
|
|
|
|
|
|
- D3D12 后端:内部创建 `ID3D12RootSignature`
|
|
|
|
|
|
- OpenGL 后端:存储绑定点数量,绘制时自动调用 `glBind*`
|
|
|
|
|
|
|
2026-03-17 17:26:41 +08:00
|
|
|
|
### 5.4 描述符堆 vs OpenGL 纹理单元
|
2026-03-17 02:17:41 +08:00
|
|
|
|
- **D3D12**:显式 `DescriptorHeap` 管理资源视图
|
|
|
|
|
|
- **OpenGL**:隐式通过 `glActiveTexture` 绑定
|
|
|
|
|
|
- **解决方案**:
|
|
|
|
|
|
- 用 `RHIDescriptorPool` 统一抽象
|
|
|
|
|
|
- 提供"自动模式"(默认)和"显式模式"(可选)
|
|
|
|
|
|
- D3D12 后端:从堆分配槽位,更新描述符
|
|
|
|
|
|
- OpenGL 后端:维护绑定点计数器,绘制时自动绑定
|
|
|
|
|
|
|
2026-03-17 17:26:41 +08:00
|
|
|
|
### 5.5 多线程命令录制
|
2026-03-17 02:17:41 +08:00
|
|
|
|
- **D3D12**:原生支持多线程录制不同 `CommandList`
|
|
|
|
|
|
- **OpenGL**:状态机模型,单线程上下文
|
|
|
|
|
|
- **解决方案**:
|
|
|
|
|
|
- 抽象层统一提供多线程接口
|
|
|
|
|
|
- D3D12 后端:真·并行提交
|
|
|
|
|
|
- OpenGL 后端:命令缓冲队列,单线程回放
|
|
|
|
|
|
|
2026-03-17 17:26:41 +08:00
|
|
|
|
### 5.6 高级特性(光线追踪等)
|
2026-03-17 02:17:41 +08:00
|
|
|
|
- **解决方案**:
|
|
|
|
|
|
1. **特性检测**:通过 `RHICapabilities` 查询支持情况
|
|
|
|
|
|
2. **降级方案**:不支持时用传统路径替代
|
|
|
|
|
|
3. **底层逃逸**:通过 `GetNativeDevice()` 直接访问原生 API
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-17 17:54:44 +08:00
|
|
|
|
### 5.11 命令队列(RHICommandQueue)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.11.1 设计理念对应
|
|
|
|
|
|
|
|
|
|
|
|
| 差异点 | 设计理念 | 处理方案 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| 初始化参数差异 | 求同存异 | 后端各自实现初始化 |
|
|
|
|
|
|
| 执行命令差异 | 特性降级 | D3D12 实现,OpenGL 空实现 |
|
|
|
|
|
|
| 同步机制差异 | 特性降级 | D3D12 实现,OpenGL 空实现 |
|
|
|
|
|
|
| 句柄类型差异 | 底层逃逸 | 统一返回 void* |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.11.2 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12CommandQueue | OpenGL | 处理方案 |
|
|
|
|
|
|
|------|-------------------|--------|----------|
|
|
|
|
|
|
| 初始化 | Initialize(device, type) | 无 | OpenGL 空实现 |
|
|
|
|
|
|
| 执行命令 | ExecuteCommandLists() | 无 | OpenGL 空实现 |
|
|
|
|
|
|
| 信号同步 | Signal/Wait | 无 | OpenGL 空实现 |
|
|
|
|
|
|
| 空闲等待 | WaitForIdle() | 无 | OpenGL 空实现 |
|
|
|
|
|
|
| 句柄 | ID3D12CommandQueue* | 无 | GetNativeHandle |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.11.3 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class RHICommandQueue {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHICommandQueue() = default;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void ExecuteCommandLists(uint32_t count, void** lists) = 0;
|
|
|
|
|
|
virtual void Signal(RHIFence* fence, uint64_t value) = 0;
|
|
|
|
|
|
virtual void Wait(RHIFence* fence, uint64_t value) = 0;
|
|
|
|
|
|
virtual uint64_t GetCompletedValue() = 0;
|
|
|
|
|
|
virtual void WaitForIdle() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual CommandQueueType GetType() const = 0;
|
|
|
|
|
|
virtual uint64_t GetTimestampFrequency() const = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void* GetNativeHandle() = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.11.4 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **初始化参数差异(求同存异)**
|
|
|
|
|
|
- D3D12:需要 device + type 参数
|
|
|
|
|
|
- OpenGL:无对等概念
|
|
|
|
|
|
- 解决:Device 的 CreateCommandQueue() 统一接收 CommandQueueDesc
|
|
|
|
|
|
|
|
|
|
|
|
2. **执行命令差异(特性降级)**
|
|
|
|
|
|
- D3D12:ExecuteCommandLists() 提交命令列表
|
|
|
|
|
|
- OpenGL:状态机模型,无命令队列概念
|
|
|
|
|
|
- 解决:OpenGL 空实现
|
|
|
|
|
|
|
|
|
|
|
|
3. **同步机制差异(特性降级)**
|
|
|
|
|
|
- D3D12:Signal/Wait/Fence 完整实现
|
|
|
|
|
|
- OpenGL:无对等概念
|
|
|
|
|
|
- 解决:OpenGL 空实现
|
|
|
|
|
|
|
|
|
|
|
|
4. **句柄类型差异(底层逃逸)**
|
|
|
|
|
|
- D3D12:ID3D12CommandQueue*
|
|
|
|
|
|
- OpenGL:无对等概念
|
|
|
|
|
|
- 解决:GetNativeHandle() 返回 void*
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-17 18:01:55 +08:00
|
|
|
|
### 5.12 命令列表(RHICommandList)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.12.1 设计理念对应
|
|
|
|
|
|
|
|
|
|
|
|
| 差异点 | 设计理念 | 处理方案 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| 资源状态转换 | 特性降级 | D3D12 实现转换,OpenGL 空实现 |
|
|
|
|
|
|
| 绑定方式 | 求同存异 | 统一接口,后端各自实现 |
|
|
|
|
|
|
| 渲染目标 | 求同存异 | 统一接口,后端各自实现 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.12.2 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12CommandList | OpenGLCommandList | 处理方案 |
|
|
|
|
|
|
|------|-------------------|-------------------|----------|
|
|
|
|
|
|
| 资源转换 | TransitionBarrier | glBarrier | 统一 TransitionBarrier |
|
|
|
|
|
|
| PSO 设置 | SetPipelineState | UseShader | 统一 SetPipelineState |
|
|
|
|
|
|
| 视口/裁剪 | SetViewport/ScissorRect | SetViewport/Scissor | 统一 |
|
|
|
|
|
|
| 顶点缓冲 | SetVertexBuffer | BindVertexArray | 统一 |
|
|
|
|
|
|
| 索引缓冲 | SetIndexBuffer | BindVertexArray | 统一 |
|
|
|
|
|
|
| 绘制 | Draw/DrawIndexed | Draw/DrawIndexed | 统一 |
|
|
|
|
|
|
| 渲染目标 | SetRenderTargets | glBindFramebuffer | 统一 |
|
|
|
|
|
|
| 清除 | ClearRenderTargetView | Clear | 统一 |
|
|
|
|
|
|
| 复制 | CopyResource | CopyImageSubData | 统一 |
|
|
|
|
|
|
| 计算 | Dispatch | DispatchCompute | 统一 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.12.3 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class RHICommandList {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHICommandList() = default;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Reset() = 0;
|
|
|
|
|
|
virtual void Close() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void TransitionBarrier(void* resource, ResourceStates stateBefore, ResourceStates stateAfter) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void SetPipelineState(void* pso) = 0;
|
|
|
|
|
|
virtual void SetViewport(const Viewport& viewport) = 0;
|
|
|
|
|
|
virtual void SetScissorRect(const Rect& rect) = 0;
|
|
|
|
|
|
virtual void SetRenderTargets(uint32_t count, void** renderTargets, void* depthStencil = nullptr) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void SetVertexBuffer(uint32_t slot, void* buffer, uint64_t offset, uint32_t stride) = 0;
|
|
|
|
|
|
virtual void SetIndexBuffer(void* buffer, uint64_t offset, Format format) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Draw(uint32_t vertexCount, uint32_t instanceCount = 1, uint32_t startVertex = 0, uint32_t startInstance = 0) = 0;
|
|
|
|
|
|
virtual void DrawIndexed(uint32_t indexCount, uint32_t instanceCount = 1, uint32_t startIndex = 0, int32_t baseVertex = 0, uint32_t startInstance = 0) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Clear(float r, float g, float b, float a, uint32_t buffers) = 0;
|
|
|
|
|
|
virtual void ClearRenderTarget(void* renderTarget, const float color[4]) = 0;
|
|
|
|
|
|
virtual void ClearDepthStencil(void* depthStencil, float depth, uint8_t stencil) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void CopyResource(void* dst, void* src) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Dispatch(uint32_t x, uint32_t y, uint32_t z) = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.12.4 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **资源状态转换(特性降级)**
|
|
|
|
|
|
- D3D12:显式 TransitionBarrier 管理资源状态
|
|
|
|
|
|
- OpenGL:无资源状态概念
|
|
|
|
|
|
- 解决:D3D12 实现转换,OpenGL 空实现
|
|
|
|
|
|
|
|
|
|
|
|
2. **绑定方式(求同存异)**
|
|
|
|
|
|
- D3D12:通过 DescriptorHeap 和 RootSignature
|
|
|
|
|
|
- OpenGL:通过 glBind* 和 VAO
|
|
|
|
|
|
- 解决:统一 Set* 接口,后端各自实现
|
|
|
|
|
|
|
|
|
|
|
|
3. **渲染目标(求同存异)**
|
|
|
|
|
|
- D3D12:SetRenderTargets 设置渲染目标视图
|
|
|
|
|
|
- OpenGL:glBindFramebuffer 绑定帧缓冲
|
|
|
|
|
|
- 解决:统一 SetRenderTargets 接口
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-17 18:05:40 +08:00
|
|
|
|
### 5.13 交换链(RHISwapChain)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.13.1 设计理念对应
|
|
|
|
|
|
|
|
|
|
|
|
| 差异点 | 设计理念 | 处理方案 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| 初始化参数差异 | 求同存异 | 统一 Desc,后端各自处理 |
|
|
|
|
|
|
| 窗口管理差异 | 特性降级 | OpenGL 有,D3D12 无 |
|
|
|
|
|
|
| 呈现方式差异 | 求同存异 | 统一 Present 接口 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.13.2 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12SwapChain | OpenGLSwapChain | 处理方案 |
|
|
|
|
|
|
|------|----------------|------------------|----------|
|
|
|
|
|
|
| 初始化 | factory/queue/hwnd | window | 统一 Initialize(Desc) |
|
|
|
|
|
|
| 后缓冲 | GetBackBuffer() | 无 | 通过 GetCurrentBackBuffer |
|
|
|
|
|
|
| 显示 | Present(sync, flags) | Present() | 统一 Present() |
|
|
|
|
|
|
| 调整大小 | Resize(w, h) | Resize(w, h) | 统一 |
|
|
|
|
|
|
| 窗口事件 | 无 | ShouldClose/PollEvents | OpenGL 实现 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.13.3 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class RHISwapChain {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHISwapChain() = default;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual uint32_t GetCurrentBackBufferIndex() const = 0;
|
|
|
|
|
|
virtual RHITexture* GetCurrentBackBuffer() = 0;
|
|
|
|
|
|
virtual void Present(uint32_t syncInterval = 1, uint32_t flags = 0) = 0;
|
|
|
|
|
|
virtual void Resize(uint32_t width, uint32_t height) = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual bool ShouldClose() const = 0;
|
|
|
|
|
|
virtual void SetShouldClose(bool shouldClose) = 0;
|
|
|
|
|
|
virtual void PollEvents() = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.13.4 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **初始化参数差异(求同存异)**
|
|
|
|
|
|
- D3D12:factory + commandQueue + hwnd
|
|
|
|
|
|
- OpenGL:window
|
|
|
|
|
|
- 解决:Device 的 CreateSwapChain() 统一接收 SwapChainDesc
|
|
|
|
|
|
|
|
|
|
|
|
2. **窗口管理差异(特性降级)**
|
|
|
|
|
|
- OpenGL:ShouldClose/PollEvents
|
|
|
|
|
|
- D3D12:无
|
|
|
|
|
|
- 解决:OpenGL 实现具体功能,D3D12 空实现
|
|
|
|
|
|
|
|
|
|
|
|
3. **呈现方式差异(求同存异)**
|
|
|
|
|
|
- D3D12:Present(syncInterval, flags)
|
|
|
|
|
|
- OpenGL:Present() / SwapBuffers()
|
|
|
|
|
|
- 解决:统一 Present(syncInterval, flags)
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-17 18:09:34 +08:00
|
|
|
|
### 5.14 管线状态(RHIPipelineState)抽象设计
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.14.1 设计理念对应
|
|
|
|
|
|
|
|
|
|
|
|
| 差异点 | 设计理念 | 处理方案 |
|
|
|
|
|
|
|--------|---------|---------|
|
|
|
|
|
|
| 初始化差异 | 求同存异 | 后端各自处理 |
|
|
|
|
|
|
| 状态管理差异 | 特性降级 | D3D12 实现状态块,OpenGL 分离状态 |
|
|
|
|
|
|
| 绑定方式差异 | 求同存异 | 统一 Bind 接口 |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.14.2 现有实现对比
|
|
|
|
|
|
|
|
|
|
|
|
| 功能 | D3D12PipelineState | OpenGLPipelineState | 处理方案 |
|
|
|
|
|
|
|------|-------------------|-------------------|----------|
|
|
|
|
|
|
| 初始化 | device + desc | 构造函数 | 后端各自处理 |
|
|
|
|
|
|
| 状态设置 | 单一 PSO 对象 | 分离状态对象 | 后端各自处理 |
|
|
|
|
|
|
| 绑定 | CommandList->SetPipelineState | AttachShader/Apply | 统一 Bind |
|
|
|
|
|
|
| 句柄 | ID3D12PipelineState* | GLuint (program) | 统一 void* |
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.14.3 抽象接口定义
|
|
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
|
class RHIPipelineState {
|
|
|
|
|
|
public:
|
|
|
|
|
|
virtual ~RHIPipelineState() = default;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Shutdown() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void Bind() = 0;
|
|
|
|
|
|
virtual void Unbind() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
virtual void* GetNativeHandle() = 0;
|
|
|
|
|
|
virtual PipelineType GetType() const = 0;
|
|
|
|
|
|
};
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 5.14.4 差异处理策略
|
|
|
|
|
|
|
|
|
|
|
|
1. **初始化差异(求同存异)**
|
|
|
|
|
|
- D3D12:device + D3D12_GRAPHICS_PIPELINE_STATE_DESC
|
|
|
|
|
|
- OpenGL:通过 SetDepthStencilState/BlendState/RasterizerState
|
|
|
|
|
|
- 解决:Device 的 CreatePipelineState() 统一接收 PipelineStateDesc
|
|
|
|
|
|
|
|
|
|
|
|
2. **状态管理差异(特性降级)**
|
|
|
|
|
|
- D3D12:单一 PSO 对象包含所有状态
|
|
|
|
|
|
- OpenGL:分离的状态对象
|
|
|
|
|
|
- 解决:后端各自实现,基类提供统一 Bind/Unbind
|
|
|
|
|
|
|
|
|
|
|
|
3. **绑定方式差异(求同存异)**
|
|
|
|
|
|
- D3D12:通过 CommandList->SetPipelineState
|
|
|
|
|
|
- OpenGL:AttachShader + Apply
|
|
|
|
|
|
- 解决:统一 Bind/Unbind 接口
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-17 02:17:41 +08:00
|
|
|
|
## 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 预留空间
|
|
|
|
|
|
|
|
|
|
|
|
需要我帮你细化某个具体模块的实现代码吗?
|