初次简单了解一下UE的代码长什么样子,参考视频https://www.bilibili.com/video/BV1VK411x7bH?spm_id_from=333.788.videopod.sections&vd_source=9df9034e2f1978b1018f5b387ec3eacd
向下
FRHIResource
/** The base type of RHI resources. */
|
|
ERHIResourceType 枚举包含的资源类型可归纳为以下大类:
- 渲染状态资源(管线状态配置类)
- 着色器及相关资源(各类着色器程序与绑定布局类)
- 缓冲与数据存储资源(数据载体及布局描述类)
- 纹理及纹理访问资源(图像数据及访问接口类)
- 光线追踪专用资源(光线追踪加速与绑定类)
- 查询与同步资源(GPU/CPU 交互及数据查询类)
- 其他辅助资源(视口、自定义呈现、资源集合等)
这里的每个实现都用子类实现
|
|
再进一步就到了具体API的子类
|
|
其他资源都一样的继承思路
这套架构已经简单实现
FDynamicRHI
类似创建操作(上下文无关操作)是在FDynamicRHI,上下文有关的操作(也就是在固定生命周期内执行的操作)是在IRHICommandContext
一些图形渲染场景的操作API都定义在这里,创建shader、更新纹理等等
|
|
封装了渲染所需的核心资源创建与管理逻辑,包括:
- 缓冲(顶点缓冲、索引缓冲、常量缓冲等)的创建 / 更新 / 销毁;
- 纹理(2D 纹理、立方体贴图等)的加载 / 格式转换 / 内存管理;
- 渲染管线状态(着色器、混合状态、深度测试等)的配置与绑定;
- 绘制命令(Draw Call)的提交与执行。
IRHICommandContext
定义上下文相关的操作,比如RHIDispatchComputeShader,这明显需要在Pass中间调用。
RHIDrawPrimitive``RHIDrawPrimitiveIndirect``RHIDrawIndexedIndirect这些,内部都是虚函数,由具体平台实现
|
|
进入API层,类内部都会有一个用于定义当前上下文的对象,比如FVulkanCommandListContext,在执行上边那些命令时,会使用Manager来获得当前激活的commandBuffer来记录命令
|
|
当创建一个IRHICommandContext时,在Vulkan中就是创建一个新的CommandBuffer
|
|
向上
FRHICommand
UE的命令是用链表串起来的
|
|
FRHICommand继承Base后只添加了一个函数 (调用命令)
|
|
再下一层就是各种具体命令 比如FRHICommandSetShaderParameters、FRHICommandSetViewport等等,每个具体命令都有一个Execute方法
|
|
再下面就是各个API具体的实现了
FRHICommandList
它内部的函数也是这种API,根据情况Bypass()选择直接调用API还是把命令缓存起来
|
|
主要看两个指针
|
|
Base下一层FRHIComputeCommandList
|
|
再下一层才是FRHICommandList。听了UE的RHI介绍视频,我觉得这样设计是因为渲染Queue可以进行渲染命令也可以是计算命令(我现在自己的项目的ComputeShader都是放在渲染Queue中进行的)。是有包含关系的。
|
|
再下一层是立即模式
|
|
再进到API层面还有封装
Mesh的DrawCall流程
数据流转:
FPrimitiveSceneProxy->FMeshBatch->FMeshDrawCommand->RHICommandList->GPU

FMeshDrawCommand
存储渲染一个Mesh的具体信息,粒度是DrawCall级别的了,上层的收集工作目的就是生成各种FMeshDrawCommand,FMeshDrawCommand进一步才转化成RHI层指令(CommandList)
|
|
SubmitDraw主要是一个Begin和一个End组成
|
|
FMeshBatch
比如相同材质、相同xxx的一组模型放在一个Batch,一个Batch有一组FMeshBatchElement,FmeshBatch由FSceneRenderer的Gatherxxx这个函数来收集,这个函数有一个参数是
MeshDrawCommand里没有材质信息,材质信息来自MeshBatch
FMeshPassProcessor
上层收集组装成FMeshBatch,通过FMeshPassProcessor的BuildMeshDrawCommands来构建FMeshDrawCommand(有历史原因,4.22之前是没有FMeshDrawCommand的)
|
|
RDG
FRDGResource
RDG层面也封装了一层Resource,其内部就是FRHIResource
|
|
FRDGTexture继承来自FRDGResource。但是在RDG层的Resource不能自己创建,必须统一经过RDGBuilder来创建
|
|
FRDGPass
把一个Pass的渲染指令进行存储
FRDGBuilder
比如贴图的创建需要RDGBuilder的CreateTexture来创建
|
|
对于已经存在的资源,也需要通过RDGBuilder进行注册,生命周期不经过RDG管理
|
|
一个Pass需要输出的资源需要经过Extraction来输出
|
|
上面三种情况就定义了资源在一个Pass的创建、输入、输出设置
添加一个Pass到RDG,ExecuteLambda就是存储具体的渲染流程
|
|
