渲染框架、命令列表、平台后端与视觉工作集
范围:Base grcore/grmodel/rmcore/grshadowmap/grpostfx/grlightprepass、Framework fwrenderer/fwdrawlist/fwlight,结合 GTA 的实际 render phases。静态分析,未运行。入口:Summary。
1. 渲染的四个层次#
RAGE 把可渲染资源、世界可见性、帧命令组织和设备执行分开。rmcDrawable 连接 geometry/model/shader/skeleton 与 LOD,Framework 把 entity 放进 render phases 和列表,draw list 序列化绘制工作,grcore 负责后端设备与资源。
这使游戏更新线程能够构建后续渲染工作,但并不消除同步。资源活到什么时候、哪一帧使用哪一份 matrix/shader 数据,是这套架构的核心。
2. Drawable 与实例数据#
rmcDrawableBase 提供普通、skinned、无 shader 等 Draw 入口,绑定 bucket mask、LOD 和矩阵。资源级 drawable 可被多个世界实例共享;每实例变换和参数由独立数据提供。
源码特别要求 streaming drawable 使用规定的 Delete 路径,而不是直接 delete。这说明资源销毁与普通 C++ 对象析构并不等价,可能涉及资源块、引用及专门分配器。
实例 buffer 又有 draw-list 内存、pool 和特定平台 GPU memory 版本。硬件 instancing 的收益取决于 mesh/material/pass 能否共享;每实例不同 shader permutation、骨架或透明排序需求仍会拆批。存在 instancing API 不等于所有植被、道具都自动一次 draw。
3. Render list 排序是多目标优化#
fwEntityList 不只保存 entity 指针,还缓存 base flags、render/custom flags 和 sort value;高位 flag 与距离共同组成比较键,存在升序、降序、ped bias、LOD 顺序等分支,且显式处理 endian。
因此列表顺序同时服务遮挡效率、透明正确性、LOD 渐变及特殊对象规则。前到后有利于深度剔除,后到前满足常见透明混合;按材质排序减少状态切换,却可能破坏透明关系。引擎用 phase/bucket 划分不同约束,而不是找一个全局最优排序。
布局耦合也很明显:快速排序直接读取组合的 64 位区域。移动结构字段、改 flag 位宽会影响比较键,不能视为普通内部重构。
4. Draw list 是命令存储,也保管被引用的数据#
fwdrawlist 有 instruction ID、命令注册、data block、matrix/shader/entity 等共享数据类型、资源引用上限和分配页。默认页尺寸 128 KiB,平台分支最大页数 128 或 48,另有 emergency pages。
这些值是命令内存管理上限,不是 GPU draw call 上限。大场景、高 pass 数、额外 viewport 和大量 instance 参数可能先挤满 CPU 命令页或引用列表,即便 GPU 尚未满负荷。
draw list 保存后续消费的数据时,需要区分复制进去的数据和仍指向外部对象的引用。后台卸载、动画矩阵覆盖和 defrag 必须尊重该列表的存活期。地址历史支持诊断多缓冲页,但不能从历史条目数推断所有渲染资源统一三缓冲。
5. Update/render 交接与安全窗口#
fwRenderThreadInterface::Synchronise 先确保 draw-list creation 完成,发送 update-done 信号,等待上一帧 render-done;接下来注释明确标记主线程 safe area,此时 render thread 保证阻塞。接口维护 updateBuffer/renderBuffer,访问时有线程类型断言。
Flush 能把异步管线推进到更强同步点,GPU_IdleSection 用于特定安全工作。它们服务资源切换、设备状态和生命周期,频繁调用也可能缩短 CPU/GPU 重叠窗口。
要区分三种完成:主线程构建完、渲染线程提交/执行完 CPU 列表、GPU 真正完成访问。render-done semaphore 不应未经后端代码证明就当作所有 GPU 工作已经结束;GPU buffer 回收需要遵循各平台 fence 和资源管理协议。
6. 图形 API 抽象与状态管理#
grcore 内有 device、effect、stateblock、vertex/index/instance buffer、render target、texture、compute shader、gfxcontext 和 GPU timing。D3D11/GNM 等后端实现共享上层语义,但资源创建、context、cache coherency、锁定和设备重置策略不同。
这支持“同一内容系统在不同平台执行”,不等于所有平台功能一致。旧后端、实验后端和现行分支共存,不能由某个 .cpp 文件存在推断发行目标支持它。
Effect/ShaderMaterial/ShaderLib 负责参数、技术和材质层级。预编译变体减少运行时编译工作,但变体数量膨胀会影响构建、资源大小、切换和调试。新项目应有 permutation 清单及使用统计,而不是让条件宏任意相乘。
7. GTA 视觉管线是框架的具体使用者#
RenderPhaseDefLight.cpp 直接接入 GBuffer、DeferredLighting 与 TiledLighting,并有 SceneToGBuffer phase 的列表构建、视口和剔除设置。游戏目录还包含 cascade/paraboloid shadows、water/reflections、mirror、tree imposters 和 FX phases。
可确认这是含 deferred/GBuffer 与专门透明/水面/反射等阶段的复杂管线;不能把所有内容强行归为唯一的 forward 或 deferred 模式。Base 中 grlightprepass 存在也不能代替游戏实际 phase 的调用证据。
CTiledLighting 使用 tile 尺寸参数、classification texture、tile buffers 与 depth reduction 等数据。它证明灯光分区/分类机制存在;仅凭类名不应直接宣称所有平台都用某种 compute clustered 算法,实际执行需按 GetPlatformSupport、technique 与 shader 路径核对。
8. 阴影、反射与大世界成本#
主视图看不到的对象仍可能进入阴影或反射列表。级联阴影扩大了被查询的空间集合,局部灯光阴影、镜面、水面反射又有额外视口。LOD 与资源请求必须考虑这些消费者,而非只考虑屏幕上的几何。
可分析的成本链是:扩大视距 → 更多 scene candidates → 更多 phase 列表/命令 → 更多纹理/几何驻留 → 更高 CPU 和 GPU 成本。减三角形只影响其中一部分;减少阴影投射者、降低重复 pass 和可见工作集往往更有效。
timecycle 和环境参数进一步控制光照/天气外观,postfx 用全屏或局部 pass 合成画面。全屏处理主要受分辨率、render-target 带宽和格式影响,透明粒子则常受 overdraw 影响,两者都不能仅用 draw count 判断。
9. 架构限制与现代化方向#
| 当前机制 | 价值 | 新项目需要重新审视 |
|---|---|---|
| CPU draw list 与固定 phase | 可调试、平台接口清晰 | 多核构建扩展、命令内存峰值和人工资源依赖 |
| 显式同步安全区 | 资源切换正确性容易定位 | 频繁 Flush 导致流水线空泡 |
| 有界资源引用与命令页 | 预算可控 | 高密度/多视口内容需明确溢出策略 |
| 多 pass 与专用视觉系统 | 支持复杂世界效果 | 重复剔除/提交、内存带宽和版本配置复杂 |
| 平台专门后端 | 能深入硬件优化 | 新 API 的 descriptor/barrier/residency 不能只做接口机械翻译 |
可考虑现代 render graph 来表达资源读写、生命周期和临时 render target 复用,但必须保留现有跨 CPU 阶段的对象发布规则。GPU-driven culling/indirect drawing 值得实验,不能仅改 draw API 就绕开 streaming、材质和动画数据准备。
10. 建议验证#
分别记录主线程构建、排序 worker、render thread、GPU 各 pass 与等待时间;再用控制变量改变分辨率、视距、阴影、人口、植被和材质复杂度。分辨率降低而 CPU 构建不变,不能据此判定 GPU 优化无效;主线程等待渲染时间变长也可能是下游负载导致。
加入高密度夜景、透明烟雾、雨天反射、快速穿越和多 viewport,检查命令页、引用列表、资源 cache 与 GPU 时间峰值。本次未采集 GPU capture 或运行结果。
11. 源码证据#
| 文件 | 关键内容 |
|---|---|
| drawable.h | Drawable、DrawSkinned、LOD 及销毁约定 |
| renderlistgroup.h | CElement、排序键和 flags |
| drawlist.h | 57–86 页/引用/命令 ID;共享数据和命令定义 |
| instancing.h | draw-list/pool/平台 GPU 内存实例缓冲 |
| renderthread.cpp | 377–449 Synchronise;498 起 buffer/Flush |
| device_d3d11.cpp | 平台设备实现入口 |
| RenderPhaseDefLight.cpp | GBuffer、deferred、phase 列表 |
| TiledLighting.cpp | tile 数据、depth reduction、平台支持和 shader |