CD Code Digest Hub /GTA V · v2

后处理、阴影、遮挡与图形辅助库:grpostfx / grshadowmap / grlightprepass / grcustom / rmocclude / softrasterizer / grprofile / video / jpeg / squish / stb

53 分钟阅读 17 个章节 1 张图

本页覆盖 RAGE 图形层中围绕“完整渲染器”的可选模块与辅助库。阅读这些目录时最重要的事实是:它们在 GTA V 中的地位差别极大——softrasterizer(软件光栅化遮挡剔除)、grprofile(计时条/PIX)、jpeg、squish、stb 被游戏实际链接和调用;而 grpostfx、grshadowmap、grlightprepass、grcustom、rmocclude 是 RAGE 早期为样例/其他项目提供的通用实现,GTA V 的后处理、阴影与遮挡都由游戏层(game/renderer)自行实现。本页先用构建证据划清边界,再按重要度展开。

背景与相关页面#

相关源码文件#

目录关键文件在 GTA V 中的地位
rage/suite/src/softrasterizersoftrasterizer.h/.cpp、scansetup.h、tiler.h/.cpp、scan.h/.cpp、boxoccluder.h/.cpp、occludeModel.h/.cpp、scanwaterreflection.*、tsklib.*、occluders.psc、*.job/*.frag核心,游戏使用
rage/base/src/grprofiletimebars.h/.cpp、pix.h、pix_*.cpp、ekg.h/.cpp、drawmanager.h、profiler.h、chart.h、trail.h、stats.h、gcmtrace.h游戏使用(调试/性能)
rage/base/src/jpegIJG libjpeg 6b经 grcore/image_jpeg.cpp 使用
rage/base/src/squishsquish.h、squishspu.h/.cpp、各 fit 实现游戏使用(运行时 DXT 压缩)
rage/base/src/stbstb_dxt.h/.cpp游戏使用(运行时 DXT 压缩)
rage/base/src/grpostfxpostfx.h/.cpp、rage_postfx.fx、PS3 edgepost*、*spu.frag未进入游戏构建
rage/base/src/grshadowmapcascadedshadowmap.*、charactershadowmap.*、cubeshadowmap.*、spotlightshadowmap.*、cloudshadowmap.*、shadowcollector.*、*.fx、*.psc未进入游戏构建
rage/base/src/grlightprepasslightprepass.h/.cpp死代码
rage/base/src/grcustomcustomlighting*.{h,cpp}仅样例/工具
rage/base/src/rmoccludeoccluder*.{h,cpp}未进入游戏构建(遗留)
rage/base/src/video仅 makefile.txt 与 vcxproj空壳;实现在 rage/framework/src/video

1. 构建边界:哪些模块被游戏链接#

证据内容
游戏解决方案RageMisc 与 RageGraphics 等 RAGE 工程被列入 src/dev_ng/game/VS_Project_NM/game.slndef:28、src/dev_ng/game/VS_Project_NM/game.slndef:40-50;其中没有 RageGraphics2
RageGraphics包含 grprofile、jpeg(以及 grcore/grmodel/rmcore 等)src/dev_ng/rage/base/src/vcproj/RageGraphics/RageGraphics.txt:7-22
RageGraphics2只含 grshadowmap、rmocclude、text,不在游戏解决方案中 src/dev_ng/rage/base/src/vcproj/RageGraphics2/RageGraphics2.txt:1-11
RageMisc包含 squish、stb、softrasterizer(及 scaleform、bink、fragment、rmptfx 等)src/dev_ng/game/VS_Project/RageMisc/ragemisc.txt:23-44
失效的 makefilegrpostfx/makefile.txt.dead、grshadowmap/makefile.txt.dead、rmocclude/makefile.txt.dead(文件名本身表明已退役);grlightprepass 没有任何工程/makefile

引用侧佐证(#include "<dir>/ 检索):grpostfx/ 只被 rage/suite/samples/*、suite/src/shadercontrollers、rageShaderViewer 与 grcore/device_d3d11.cpp 包含,而后者只有 #include 与一行被注释的 PARAM_nopostfx 检查 src/dev_ng/rage/base/src/grcore/device_d3d11.cpp:72、src/dev_ng/rage/base/src/grcore/device_d3d11.cpp:2549;grshadowmap/ 只被 suite/src/rmlighting、suite/src/manylights 与样例包含;rmocclude/ 只被自身与 base/samples/sample_rmocclude 包含;grlightprepass/ 无任何包含者;grcustom/ 只被 rageShaderViewer 与 sample_grcore 包含。相反,softrasterizer/ 被 game/renderer/occlusion.*、game/scene/loader/MapData.h、game/Vehicles/Vehicle.cpp、fwscene/scan/*、fwscene/mapdata/mapdata.h 等包含(见 §2.6)。

2. softrasterizer:软件光栅化 Hi-Z 遮挡剔除(游戏核心)#

2.1 解决的问题#

在 CPU/SPU 上把少量“遮挡体”(地图中摆放的盒子与简化网格,以及水面)光栅化成一张很小的深度图,再生成分层 Z(Hi-Z);随后场景扫描对每个实体/批次的屏幕空间包围盒做保守查询,提前剔除被遮挡对象,避免把它们送进 drawlist。整套流程以 sysTask 依赖图并行执行。

2.2 固定分辨率与缓冲尺寸#

宏值说明
RAST_NUM_TILERS_ACTIVE4并行 tiler(分桶)任务数
MAX_TILER_TRIS384+64 = 448(4 tiler 时)每 tiler 可容纳三角形
RAST_NUM_TILES_WIDE × HIGH4 × 3 = 12屏幕分块,每块一个 scan 任务
RAST_BLOCK_WIDTH/HEIGHT8 / 6(因 TILES_HIGH == 3)每块的 4×4 像素块数
RAST_TILE_WIDTH/HEIGHT32 / 24每块“单元”尺寸
RAST_SCREEN_WIDTH/HEIGHT128 × 72(编译期断言)Z 缓冲单元网格
RAST_SCREEN_*_PIXELS256 × 144等效像素分辨率
RAST_HIZ_WIDTH/HEIGHT64 × 36(2304 个 Vec4V,36864 B)Hi-Z 缓冲
RAST_STENCIL_SIZE_VEC72 + 4 = 76模板(水面)缓冲

证据:src/dev_ng/rage/suite/src/softrasterizer/scansetup.h:13-75。注释与代码不一致:行尾注释仍按“4×2 块、每块 36 高”书写(例如 // 9*4 = 36、// 36*2 = 72),但当前 RAST_NUM_TILES_HIGH = 3 使 RAST_BLOCK_HEIGHT = 6、RAST_TILE_HEIGHT = 24;屏幕总高仍为 72,两种配置在总尺寸上等价,读代码时应以宏为准。

2.3 遮挡体数据#

类型布局 / 职责证据
BoxOccluder16 字节压缩 OBB:中心 xyz、cos/sin 绕 Z 旋转、长宽高,全部 s16 且以 0.25 m 为单位;CalculateVerts 展开 8 顶点;Empty() 放在 z = -1000src/dev_ng/rage/suite/src/softrasterizer/boxoccluder.h:38-87
CBoxOccluderBucket / COccludeModelBucket指向一个 mapdata 槽中的遮挡体数组(pArray/pElements/count/mapDataSlotIndex),16 字节对齐以便 DMAsrc/dev_ng/rage/suite/src/softrasterizer/boxoccluder.h:28-36、src/dev_ng/rage/suite/src/softrasterizer/occludeModel.h:53-61
OccludeModel任意简化网格:AABB、打包顶点(VFMT_11_11_10 4 B/顶点 或 VFMT_F32)+ u8 索引;MaxIndexedVerts = 256、MaxWaterOccluders = 64;FLAG_WATER_ONLYsrc/dev_ng/rage/suite/src/softrasterizer/occludeModel.h:63-110
容量MAX_NUM_BOX_OCCLUDERS 4000、MAX_NUM_BOX_OCCLUDERS_RASTERIZED 512、MAX_NUM_OCCLUDE_MODELS 416src/dev_ng/rage/suite/src/softrasterizer/boxoccluder.h:15-16、src/dev_ng/rage/suite/src/softrasterizer/occludeModel.h:15
parser 反射occluders.psc 把两者声明为 simple 结构(地图数据中直接序列化)src/dev_ng/rage/suite/src/softrasterizer/occluders.psc:1-27

2.4 运行时结构#

  • rstTransformToScreenSpace:裁剪平面、合成矩阵、相机位置、屏幕范围(w 分量存深度缩放),由 grcViewport 构造 src/dev_ng/rage/suite/src/softrasterizer/tiler.h:34-47。
  • rstFastTiler:一个 tiler 的三角形缓冲(PreTri2 边方程 C/DX/DY/minMax)与每块索引表、计数表 m_cntTable[12*2](大三角/小三角两组)src/dev_ng/rage/suite/src/softrasterizer/tiler.h:57-110、src/dev_ng/rage/suite/src/softrasterizer/scan.h:32-55。rstTileList 持有 4 个 tiler 和一个水面 tiler src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:33-58。
  • ScratchPadAllocator<Alloc>:每帧线性分配器,16 字节对齐,End() 时检查溢出;BANK 下可把指定对象改为静态分配以便调试显示 src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:61-205。游戏每帧用它为每个遮挡阶段分配 rstTileList 与水面遮挡缓冲 src/dev_ng/game/renderer/occlusion.cpp:961-979。
  • SoftRasterizer : datBase:持有 Z/Hi-Z/模板缓冲、变换、每 tiler 的盒/模型分包 TileDataPacket<T>、阴影方块、水面遮挡输出;以及两套任务表示——sysDependency 数组和 DependantTaskList(m_useSysDependencyTasks 选择);支持父子 rasterizer 共享 tiler src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:560-748。构造函数把 m_useSysDependencyTasks 固定为 false(无公开 setter),因此运行路径是 DependantTaskList/sysTask 版本 src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:283-333。

2.5 每帧流程与任务图#

游戏侧(COcclusion,见 ../11-rendering/render-pipeline-and-phases.md)对每个遮挡阶段调用:BeginSubmit(&vp) → SelectAndRasterizeBoxOccluders(...) → SelectAndRasterizeModelOccluders(...) →(主阶段且启用时)PrepareSubmitGenerateWaterTris(...) → EndSubmit(NULL, false) src/dev_ng/game/renderer/occlusion.cpp:654-677。

图中证据:BeginSubmit src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:350-359;选择任务的参数(PS3 scratch 48 KB,其他 32 KB)src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:724-812;boxselector 选出最多 512 个盒、按屏幕面积降序排序(打包值低 16 位为索引),再按排序后序号轮转分给 4 个 tiler 以平衡负载,并用 BoxOccluder::Empty() 填充对齐 src/dev_ng/rage/suite/src/softrasterizer/boxoccluder.cpp:365-448;tiler 任务 boxoccluder 读入本 tiler 的盒与模型分包并 AddIndexedTriList src/dev_ng/rage/suite/src/softrasterizer/boxoccluder.cpp:254-348、src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:843-870;依赖装配(tiler 依赖两个 selector,scan 依赖 tiler,水面三角与模板任务插入,父 rasterizer 等子 rasterizer 发射后才 scan)src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:483-593;12 个 scan 任务按 3 行 × 4 列创建,每块写入 zbuffer + index*TILE_W*TILE_H src/dev_ng/rage/suite/src/softrasterizer/tiler.cpp:1856-1903;模板与水面任务 src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:714-721、src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:873-967。

补充:

  • 父子 rasterizer:DependsOn(parent) 让一个 rasterizer 复用父对象的 tiler;子对象的 tiler 任务要等父对象 scan 结束,父对象的 scan 依赖计数 +1 直到子对象发射(RemoveChildDependancy)src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:630-639、src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:490-564。这表明游戏的多个遮挡阶段(例如主视图与级联阴影)可以串联共享中间缓冲(推断;阶段划分在游戏层)。
  • 若没有 selector 任务被设置(“简单情形”),EndSubmit 直接创建 scan 任务并可选 perfWait 等待 src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:565-590。游戏在非 _USE_DEPENDANT_TASKS_RASTERIZER 时退化为主线程逐盒 RasterizeModel src/dev_ng/game/renderer/occlusion.cpp:678-705。
  • 每个任务入口都有 .job/.frag 包装,供 PS3 SPU 以作业/片段形式运行;PC/主机上以 sysTask 在工作线程运行(TASK_INTERFACE(...))。

2.6 查询接口与使用者#

Hi-Z 的生成与比较语义:每个 scan 任务把本块三角形扫描进 Z 缓冲,随后 GenerateHiZTile 对相邻 Z 样本做 Min 归约写入 Hi-Z(Hi-Z 分辨率为 Z 缓冲的一半),同时累计本块的“最近深度”(对各 Hi-Z 值取 Max 后求倒数写入 nearZVal)与有效覆盖范围 minMaxBounds(供查询方做平凡接受)src/dev_ng/rage/suite/src/softrasterizer/scan.cpp:664-700、src/dev_ng/rage/suite/src/softrasterizer/scan.cpp:725-756、src/dev_ng/rage/suite/src/softrasterizer/scan.cpp:1476-1485。查询侧 rstScanQueryHiZLargeApprox 取对象屏幕包围盒最近深度的倒数 1/scmin.z,把矩形钳制到 64×36 的 Hi-Z 网格后以 2×2 单元步进,只要任一 Hi-Z 值小于 1/scmin.z 就判“可见”;每行开始前检查已有结果以提前退出——注释记录该早退在 360 上使 TestOcclusion 提速约 35–45% src/dev_ng/rage/suite/src/softrasterizer/scan.h:143-242。这表明缓冲中保存的是深度倒数(越大越近),Hi-Z 的 Min 即“最远遮挡深度”,因而测试是保守的(推断:依据是 Invert/Min 的使用方式,未追踪顶点变换中的深度定义)。

函数作用证据
rstCalculateScreenSpaceBound(IsVis)用 SoA 一次变换 AABB 的 8 个角,齐次裁剪、透视除法得到屏幕空间 min/max(含深度);IsVis 版本先做全外裁剪拒绝,并处理 w<0src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:280-416
rstScanQueryHiZLarge(Approx)屏幕矩形 vs Hi-Z 的保守可见性测试src/dev_ng/rage/suite/src/softrasterizer/scan.h:143-245
rstTestAABBExactEdgeList / rstTestOOBBExactEdgeList / rstTestModelExact / rstTestAABBExact精确边表测试(返回可见面积),支持正交投影(阴影)src/dev_ng/rage/suite/src/softrasterizer/tiler.h:302-314
rstCalculateOcclusion / rstCalculateOcclusionAABBExactEdgeList批量 AABB 查询,写结果位src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.h:750-765

使用者:fwscene 扫描在 ScanEntities.cpp 中直接 #include "softrasterizer/scan.cpp"(把实现编进扫描作业),对实体包围盒调用 rstTestAABBExactEdgeList(级联阴影阶段用正交模式)与 rstScanQueryHiZLargeApprox(注释称其结果与 rstScanQueryHiZLarge 极接近且有提前退出)src/dev_ng/rage/framework/src/fwscene/scan/ScanEntities.cpp:55、src/dev_ng/rage/framework/src/fwscene/scan/ScanEntities.cpp:1367、src/dev_ng/rage/framework/src/fwscene/scan/ScanEntities.cpp:1415-1420;游戏 COcclusion 暴露 GetHiZBuffer(phase) 并用 rstTestModelExact 测试二十面体/圆锥等体积(例如灯光体积)src/dev_ng/game/renderer/occlusion.cpp:475-476、src/dev_ng/game/renderer/occlusion.cpp:758-760。扫描与可见性的完整流程见 ../04-rage-framework/scene-graph-and-visibility.md。

2.7 约束与边界#

  • 分辨率、tiler 数、每 tiler 三角形数均为编译期常量;超出 MAX_TILER_TRIS 的输入由 IsFull 判定(调用方需处理)src/dev_ng/rage/suite/src/softrasterizer/tiler.h:72-75。
  • 每帧最多光栅化 512 个盒遮挡体;超出部分被选择任务丢弃(按面积排序后截断)。
  • 遮挡结果是保守的:查询失败只会导致多画,不会错误剔除(这是 Hi-Z 测试的设计意图;具体阈值如 THRESHOLD_PIXELS_SIMPLE_TEST 在 BANK 下可调)。
  • __RASTERSTATS(非 FINAL、非 SPU)启用统计计时器 src/dev_ng/rage/suite/src/softrasterizer/scansetup.h:13;BANK 下可把 Hi-Z/模板拷贝到 grcTexture 调试显示(256×144 L8)src/dev_ng/rage/suite/src/softrasterizer/softrasterizer.cpp:289-298。

3. 硬件遮挡/条件渲染查询(grcore)#

与软件 Hi-Z 并存,grcDevice 暴露 GPU 遮挡查询与条件渲染:CreateOcclusionQuery(Xenon 下需考虑平铺)、Begin/EndOcclusionQuery、GetOcclusionQueryData(返回通过深度测试的像素数),以及 Create/Begin/EndConditionalQuery、Begin/EndConditionalRender src/dev_ng/rage/base/src/grcore/device.h:2469-2505。D3D11 实现直接映射到 D3D11_QUERY_OCCLUSION,GetData 非阻塞,未就绪返回 false src/dev_ng/rage/base/src/grcore/device_d3d11.cpp:6429-6472。游戏在何处使用(例如镜头光晕/日光可见性)由 ../11-rendering/render-pipeline-and-phases.md 说明。

4. rmocclude:遗留的几何遮挡系统(未链接)#

rmOccluderSystem(注释强调“不是单例”)基于多面体/多边形遮挡体(rmOccludePolyhedron、rmOccludePoly、rmOccludeFacet/Edge)、span buffer 与 PVS 视图,提供 LoadDataset、StartNewFrame/EndFrame、IsSphereOccluded、IsSphereSpanBufferOccluded、IsHotDogOccluded 等 src/dev_ng/rage/base/src/rmocclude/occluder.h:278-600。大量文件是空壳或整体禁用:occluder_hom.h 用 #if 0 包裹全部内容 src/dev_ng/rage/base/src/rmocclude/occluder_hom.h:6-8,occluder_umbra.h、occluder_vu0.h(PS2 VU0)、occluder_fusion.h 只剩 include 守卫。它属于 RageGraphics2,不进入游戏构建(§1)。GTA V 的遮挡完全由 §2 的 softrasterizer 承担。

5. grpostfx:RAGE 通用后处理管线(未链接)#

  • 设计:grPostFX : datBase 管理后处理 RT、着色器与预设(grcPPPPreset:DOF、bright-pass、bloom、色调映射等参数),Process() 执行已注册的效果,BeginFrame()、CreateRenderTargets(w,h);效果插件基类 grPostFXEffect { virtual Process(grPostFX*) },内置 None/Edge/ToneMapping/ToneMappingDepthOfField/...GaussFog/Fog 等 src/dev_ng/rage/base/src/grpostfx/postfx.h:129-200、src/dev_ng/rage/base/src/grpostfx/postfx.h:861-961。编译开关(Kawase streak、blue shift、MC4 运动模糊等)全为 0 src/dev_ng/rage/base/src/grpostfx/postfx_cfg.h:1-8。
  • PS3:edgepost_task.cpp 与一组 *spu.frag(bloom capture、DOF、下采样、高斯、ILR、运动模糊、ROP、上采样)把后处理卸载到 SPU(基于 edge/post 的预编译程序);旧 makefile 列出了这些文件与嵌入式着色器 src/dev_ng/rage/base/src/grpostfx/makefile.txt.dead:1-41。
  • 目录附带 HDR、gamma、PPP 使用指南等文档(Doc/)。
  • GTA V 的后处理在 game/renderer/PostProcessFX* 与 game/shader_source/PostFX,见 ../11-rendering/deferred-lighting-and-shadows.md。

6. grshadowmap:RAGE 通用阴影图(未链接)#

类职责证据
CShadowMap + CShadowMapTile级联(瓦片)阴影图;平台默认尺寸 PC/PS3 640²、Xenon 800²;mip 级 8;瓦片参数(近/远切片、深度缩放、偏移、斜率偏移、FOV 除数)可由 .psc 加载src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.h:39-60、src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.h:137-175、src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.psc:8-25
CCascadedShadowCulling级联的光空间视锥平面裁剪src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmapculling.h:21-85
CCharacterShadowMap、CCubeShadowMap/CShadowedPointLight、CShadowedSpotLight/CShadowCache、CloudShadowMap、CShadowCollector角色专用阴影、点光立方阴影、聚光阴影与缓存、云影、屏幕空间阴影收集src/dev_ng/rage/base/src/grshadowmap/charactershadowmap.h:55-137、src/dev_ng/rage/base/src/grshadowmap/cubeshadowmap.h:42-85、src/dev_ng/rage/base/src/grshadowmap/spotlightshadowmap.h:29-159、src/dev_ng/rage/base/src/grshadowmap/cloudshadowmap.h:15-36、src/dev_ng/rage/base/src/grshadowmap/shadowcollector.h:32

不一致:CShadowMap 构造注释写“The maximum # is 4”,而 CShadowMapTile::MAX_TILES = 8 src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.h:58、src/dev_ng/rage/base/src/grshadowmap/cascadedshadowmap.h:140-146;由于模块不在游戏构建中,未进一步核实实现取哪一个。GTA V 自己的级联阴影(CRenderPhaseCascadeShadows、wdcascade technique group)见 ../11-rendering/deferred-lighting-and-shadows.md;共享 HLSL 阴影头(rage_shadow*.fxh、rage_shadow_config.h)在 shaderlib 中,与本目录的 .fx 不同。

7. grlightprepass:死代码#

头文件守卫与注释仍是 sagrender/lightprepass.h,依赖 lighting/spotlight.h 与 sagSpotLight 类型;renLightPrePassLightsMgr 提供 light pre-pass(先渲染光照累积再主颜色 pass)的点/方向/聚光灯绘制与裁剪矩形计算,PS3/360 专用的 Hi-Stencil 与深度边界辅助 src/dev_ng/rage/base/src/grlightprepass/lightprepass.h:1-100。目录中没有 makefile/工程,也没有任何代码包含它(§1)。这表明它是从其他项目(“sag” 前缀)复制来的参考实现,未在 RAGE 当前树中维护(推断,依据:命名与缺失的构建入口)。

8. grcustom:可切换光照模型(样例/工具)#

grcCustomLightImplementation 是光照模型插件基类:构造时自动向管理器注册,Register() 在着色器加载前调用(用于注册 technique group),SetLightingGroup(const grcLightGroup&) 实现具体光照模型;grcCustomLighting 管理所有实现并按名切换,SafeInitImplementations 把最后一个初始化成功的设为默认 src/dev_ng/rage/base/src/grcustom/customlighting.h:22-110。具体实现有 grcRageLightImplementation、grcGtaLightImplementation、grcMp3LightImplementation、grcRdr2LightImplementation(各项目的光照约定)src/dev_ng/rage/base/src/grcustom/customlighting_gta.h:19、src/dev_ng/rage/base/src/grcustom/makefile.txt:1-13。使用者是 rageShaderViewer 与 sample_grcore(例如 src/dev_ng/rage/base/samples/sample_grcore/sample_grcore.cpp:27),用于在工具中用接近游戏的光照预览 shader。

9. grprofile:计时条、PIX 标记与 pfDraw#

9.1 计时条(timebars)#

  • 动态装配:profile/timebars.h 中的 PF_START_TIMEBAR/PF_PUSH_TIMEBAR/PF_POP_TIMEBAR/PF_AUTO_PUSH_TIMEBAR 只是调用 pfTimebarFuncs::g_StartCb/g_PushCb/g_PopCb 函数指针 src/dev_ng/rage/base/src/profile/timebars.h:36-85,默认是空操作 src/dev_ng/rage/base/src/profile/timebars.cpp:39-41;grprofile 的 pfTimeBarMgr::Init 把它们替换为 grProfileCallbacks::Start/Push/Pop 等实际实现 src/dev_ng/rage/base/src/grprofile/timebars.cpp:2102-2115。因此底层模块(如 grcore)可以无依赖地打计时条,而图形化显示由 grprofile 提供。
  • 启用条件 RAGE_TIMEBARS = (!__FINAL || __FINAL_LOGGING) && !__PROFILE && !__TOOL;PC/主机最多 10 组计时条集合(其他 5);5 重缓冲;函数栈深 15;平均值平滑系数 0.95;DEV/BANK 才包含 detail 计时条 src/dev_ng/rage/base/src/grprofile/timebars.h:17-47。
  • 预定义分桶 eTIMEBAR_BUCKET:流式、人口、动画、人物/物体/载具更新、物理、脚本、渲染更新、可见性、构建 drawlist、GBuffer、阴影、反射、SSAO、方向/环境光、透明、VFX、SSA、PostFX src/dev_ng/rage/base/src/grprofile/timebars.h:52-77——这份清单本身就是 GTA V 帧预算的分类。
  • pfTimeBars 每条记录名称、起止时间、预算、父子/兄弟链、超预算/空闲/detail 标志、层与桶 src/dev_ng/rage/base/src/grprofile/timebars.h:84-108;pfTimeBarMgr 提供启动条/GPU 条、FrameInit/FrameEnd、Start/Push/Pop、超预算跟踪 src/dev_ng/rage/base/src/grprofile/timebars.h:333-360。

9.2 PIX 与其他#

  • PIXBegin/PIXBeginN/PIXEnd/PIXIsGPUCapturing(Cached) 按 Xenon/PC/Durango、GCM、Orbis 分别实现(pix_pc.cpp/pix_gcm.cpp/pix_gnm.cpp);PIXBeginFrame 每帧刷新“是否在 GPU 捕获”的缓存 src/dev_ng/rage/base/src/grprofile/pix.h:13-80。grcore 用这一缓存决定是否为每个 pass 打详细标签(见 grcore-device-and-effects.md)。
  • pfEKGLog 等(__STATS)绘制滚动曲线(每日志 300 个采样)src/dev_ng/rage/base/src/grprofile/ekg.h:19-50;pfDrawManager/pfDrawGroup/pfDrawItem 与 PFD_DECLARE_* 宏声明可在 RAG 中开关的调试绘制项 src/dev_ng/rage/base/src/grprofile/drawmanager.h:36-57(rmcDrawable::ProfileDraw 即在 __PFDRAW 下使用);pfProfileRenderer/pfStatsView、pfChart、pfTrail、pfStatsManager、PS3 pfGcmTrace 构成其余的屏显与追踪工具。
  • GPU 计时(grcGpuTimer)在 grcore/gputimer.*,见 grcore-device-and-effects.md。

10. video:空壳目录#

rage/base/src/video 只有 makefile.txt、vcxproj 与 guid;makefile 与工程列出的 mediaencoder_buffer*、mediaencoder_params、mediaencoder_win 源文件不在该目录中 src/dev_ng/rage/base/src/video/makefile.txt:1-14。游戏代码 #include "video/..." 实际解析到 rage/framework/src/video(媒体编码/解码、录制接口、VideoPlayback、PS4 内容导出等)。该模块属于视频录制/回放主题,见 ../19-persistence-replay/replay-and-video.md。

11. jpeg:IJG libjpeg 6b#

第三方 Independent JPEG Group 库,版本字符串 6b 27-Mar-1998(jversion.h),文件改为 .cpp 编译;makefile 只收录编解码核心(jc*/jd*/jf*/ji*/jm*/jq*/jutils)而不含命令行工具(cjpeg/djpeg/...)src/dev_ng/rage/base/src/jpeg/makefile.txt:1-63。唯一使用者是 grcore/image_jpeg.cpp(grcImage::LoadJPEG/SaveJPEG、LoadJPEGToRGBA8Surface/DXT1Surface,截图与照片/头像纹理),见 grcore-device-and-effects.md。

12. squish:libsquish DXT 压缩 + 任务化包装#

  • 第三方 libsquish(Simon Brown,MIT 许可头),API 标志:kDxt1/3/5、kColourIterativeClusterFit(最慢最好)、kColourClusterFit(默认)、kColourRangeFit(快)、感知/均匀误差度量、按 alpha 加权 src/dev_ng/rage/base/src/squish/squish.h:39-67。
  • Rockstar 包装 sqCompressState:把 grcTexture → DXT 纹理(或多级 mip)的压缩拆成多个“切片”任务(sysTaskManager),调用方每帧 Poll() 推进或 Wait() 阻塞;状态对象必须存活到完成,析构时断言未等待 src/dev_ng/rage/base/src/squish/squishspu.h:21-82。Xenon 改用 VMX 快速压缩并边压缩边去平铺,SQUISH_USE_STB_COMPRESSION 关闭 src/dev_ng/rage/base/src/squish/squishspu.h:84-87。
  • 游戏使用者:人物头像(PedHeadshotManager)与人物伤害贴图(PedDamage)以 kColourIterativeClusterFit 压缩运行时生成的纹理 src/dev_ng/game/Peds/rendering/PedHeadshotManager.cpp:995-996、src/dev_ng/game/Peds/rendering/PedDamage.cpp:5061-5062;MeshBlendManager.h 也包含该头;工具侧 fwtextureconversion 与 ragebuilder 纹理转换使用它。

13. stb:stb_dxt v1.04#

单头文件 DXT1/DXT5 压缩器(原作者 ryg,public domain),STB_DXT_HIGHQUAL 做两次细化;stb_dxt.cpp 只负责定义 STB_DXT_IMPLEMENTATION 生成实现 src/dev_ng/rage/base/src/stb/stb_dxt.h:1-30、src/dev_ng/rage/base/src/stb/stb_dxt.cpp:1-7。游戏在三处用它逐 4×4 块压缩:MeshBlendManager(人物头部混合纹理)src/dev_ng/game/renderer/MeshBlendManager.cpp:4822、PedHeadshotManager src/dev_ng/game/Peds/rendering/PedHeadshotManager.cpp:227、DownloadableTextureManager(可下载纹理,如云端/社交图片)src/dev_ng/game/scene/DownloadableTextureManager.cpp:157。头部混合细节见 ../06-peds/ped-motion-and-rendering.md。

约束与边界行为(汇总)#

  1. 不要把 grpostfx/grshadowmap/rmocclude/grlightprepass 当作 GTA V 的实现来读:它们不在游戏解决方案或无任何包含者;游戏有自己的后处理、阴影与遮挡。
  2. 软件遮挡的分辨率与任务并行度是编译期常量(128×72 单元 / 64×36 Hi-Z / 4 tiler / 12 scan),注释中的旧数值(2 行瓦片)已过时。
  3. 遮挡体选择有硬上限(每帧 512 个盒,网格 416),按屏幕面积排序截断。
  4. sqCompressState 生命周期必须覆盖整个异步压缩过程;运行时 DXT 压缩在主机上走任务系统,结果写入调用者提供的 DXT 纹理(其格式优先于 flags)。
  5. 计时条宏在 FINAL(无 __FINAL_LOGGING)、PROFILE 与工具构建中为空;在 pfTimeBarMgr::Init 之前调用只是空操作。

未决问题 / 证据不足#

  • scan.cpp(87 KB)与 tiler.cpp(82 KB)的光栅化内核(边方程增量、大/小三角形分流、Hi-Z 生成)只做了接口级阅读;水面模板(scanwaterreflection.*、stencilwriter)细节未展开。
  • COcclusion 的阶段划分(主视图、级联阴影、水面反射等)与阈值调优属于游戏层,未在本页核实。
  • grpostfx、grshadowmap、grcustom 只做了结构级盘点,未阅读实现;它们是否在其他 RAGE 工具(如 rageShaderViewer)中仍可用未验证。
  • grprofile 中 profiler.cpp、stats.cpp、trail.cpp 的具体屏显逻辑未展开。