Runtime Procedural Virtual Texture for Unity Terrain in Universal Render Pipeline(URP).
基线 main@0e4ec82;实际验证为 Unity 6000.6.0f1 / URP 17.6.0 / Burst 2.0.0 / Collections 6.6.0 / Mathematics 1.4.0 / Apple M3 Max / Metal。项目使用 Linear、1920×1080、render scale 1、MSAA 1、VSync 关闭。不能据此宣称 Unity 6000.0、Windows、Android、D3D、Vulkan 或 GLES/OpenGL 已通过实测。
| 任务 | 结果 | 验证 |
|---|---|---|
| T0 环境与基线 | 完成 | 一个最小临时宿主,基线 EditMode 67/0/0,保护已有 Editor 与工程 |
| T1 编码优化 | 完成 | ASTC 预计算 infill、合并双平面累加;EAC 常量 alpha 快路。随机块 17,024 个 UInt 字与原编码器一致,保留原拟合质量 |
| T2 确定性过滤 | 完成 | 整数 lod 或相同驻留祖先只采样一次;六组 GPU 对照、三层输出误差 ≤1e-6 |
| T3 按层压缩 | 完成 | BC1 颜色 / BC5 法线 / BC3 Mask;ETC2 RGB 颜色 / RGBA 数据;各档非零槽与重复覆盖通过 |
| T4 时间 mip | 完成 | temporalMip 默认 false;实际 URP TAA 积累对比、历史重置、多相机及拒绝条件通过 |
| T5 硬件各向异性 | 质量门槛拒绝 | 单 mip SampleGrad 候选发生邻槽污染;保护候选仍有明显条纹误差。候选代码、枚举和测试全部移除,保留软件各向异性 |
| T6 页面调度 | 完成 | BC、ETC2、ASTC 4×4 最多四页分组;其余单页。完整链 A/B 与 10,036,224 纹素逐值比较通过 |
| T7 回归与收尾 | 完成 | 最终 EditMode 90/0/0;147 次指定 pass/关键字编译无消息;72 档×3 次运行及最终 72 档近远画面自查无错误;约定、元数据及临时产物清理通过 |
始终保留反馈 → Job 请求链 → 驻留 → 小页烘焙/编码/复制 → 间接表 → 着色采样这一条通路。没有硬件 mip、硬件各向异性选项或整图重压缩。border 仍为 4。asmdef 不变,不新增 DESIGN.md 或兼容字段。
| 提交 | 对应改动及原因 |
|---|---|
3aff1a7、831317f |
编码:预计算 ASTC 固定权重数学、双平面配对累加;移除实测会拖慢随机内容的 EAC 分歧退出,只保留常量 alpha 快路 |
b2499c7 |
采样:合并相同驻留页的重复三线性物理采样 |
cc3a2a6 |
驻留资源:正确销毁 EditMode 下的物理图与间接表 GPU 对象 |
45de679 |
压缩:按层选择 BC/ETC2 格式及 64/128 位块图;BC5 RG 解码归一到原 AG 法线约定 |
6ea19f8 |
间接表:用整数格子、显式 mip 的 Load;HLSL int 使用真正 Integer 绑定,修复错误 mip 和写入偏移 |
e4a650b |
采样:仅在当前相机确有 TAA 历史与像素抖动时启用时间 mip |
b3b3c2f |
烘焙:按实测收益限制四页工作集,显式导入全部 scratch / 块图并在复制之后发布间接表 |
b48ddf3 |
采样:过滤参数随相机图记录,修复运行中切换设置不生效 |
3b2891e |
着色器:统一时间 mip 返回值,消除 Metal 变体的未初始化警告 |
158f000 |
反馈回归:153 个 R32_UInt 栅格 PageId 经真实回读逐位一致 |
临时场景为 2×2 相邻地形、每块五层,包含 mask、非零 tileOffset、方向纹理和法线、连续 stochastic UV 与原始梯度。固定光照,近远与掠射角飞行。默认 pageCount 2048、pageTexels 256、border 4、poolSize 16、bakesPerRound 8、queueCapacity 512、queueTimeout 30。
以下每格都包含三种 layers:BaseColor / BaseColorNormal / BaseColorNormalMask,合计 72 档。每档三个窗口,每窗口预热 300 帧、采集 600 帧,共 194,400 个 Game 帧,运行错误为 0。最终另跑 72 档近远画面自查,未见倒置、黑块或本次调度新增的明显页缝;12 张自查截图已逐张查看并删除。
| 压缩 | Bilinear | Trilinear | Anisotropic 4 | Anisotropic 16 |
|---|---|---|---|---|
| None | 3/3 | 3/3 | 3/3 | 3/3 |
| BC | 3/3 | 3/3 | 3/3 | 3/3 |
| ETC2 | 3/3 | 3/3 | 3/3 | 3/3 |
| ASTC 4×4 | 3/3 | 3/3 | 3/3 | 3/3 |
| ASTC 6×6 | 3/3 | 3/3 | 3/3 | 3/3 |
| ASTC 8×8 | 3/3 | 3/3 | 3/3 | 3/3 |
- 页方向、颜色、法线与 Mask 各通道以 GPU 解码对照;颜色在 Linear 工程检查 sRGB,避免把 Gamma 宿主的差异归咎编码器。BC 颜色没有 alpha 用途,BC1 不减少既有颜色端点精度。
- 分组与逐页顺序在六档、三层、八个槽(包含 border 与跨地形烘焙)比较 10,036,224 个纹素,最大误差为 0。部分工作集、末尾一页、非零槽和覆盖也有永久回归。
- 确定性三线性/各向异性保留原足迹、虚拟 mip 与长轴 taps 数学。GPU 测试覆盖整数 mip、不同驻留页、相同祖先及域边缘;不把缩略截图当作锐度提升的定量证据。
- 时间 mip 对三线性、各向异性 4/16,实际 TAA 积累图的 RGB MAE 分别为 0.000134 / 0.0000904 / 0.000101,P95 为 0.000525 / 0.000316 / 0.000349。图像为同一静止视角 33 帧平均、240×135 线性读值,对照确定性过滤。此结果不代表所有移动内容的鬼影/噪声保证。
- 无 TAA、后处理关闭、动态分辨率、Scene 相机、MSAA 4、相机堆叠、零抖动、组件关闭与设置关闭均不启用时间 mip;重置历史及重启组件均先回退再恢复。两 Game 相机(一个有 TAA、一个没有)反馈轮转 189 / 188 次,后者没有误启用时间 mip;含相机启停、组件重建、小池 4×4、队列 32、超时 2 轮压力。
- Frame Debugger 实际捕获
VT Bake Page → VT Encode → VT Indirect → VT Feedback,第二 Game 相机也有 Feedback;R32_UInt 反馈目标 60×34 与第二相机 960×540 相符。Readback 没有当作可见 draw 事件冒称捕获,其执行由实际回调及回归确认。 - 最终 C# / Burst 没有本包诊断。Metal 同步编译 IndirectMap、TerrainBake 两个 pass×三种层关键字、TerrainLit_VT 五个 pass(阴影、软阴影、洞、实例化、法线、雾、光照贴图相关选定组合),147 次请求没有消息;六个 compute kernel 均实际执行。此为明确覆盖的变体范围,不是所有关键字笛卡尔积或跨平台编译声明。
| 风险 | 本轮结论 |
|---|---|
| UInt 块图 → 压缩 Texture2D | Metal 五种压缩档均成功;64 位颜色块为 R32G32_UInt,其他为 R32G32B32A32_UInt。源区域以块计、目标偏移以像素计,非零槽、边缘及重复写入验证通过。仍保留 Copy,不使用 Unity 未暴露的压缩资源别名 |
| Apply(false, true) 后 Copy | Metal 通过,释放 CPU 可读副本后仍可 GPU 写入和重复覆盖,采样正确 |
| R32_UInt 异步回读 | 153 个不同 PageId 的全部 uint 位一致;实际 RG 场景也持续反馈。旧回调不能释放新请求的在途标志,销毁后不提交 |
| GLES/OpenGL y 方向 | 未验证;只确认 Metal 下间接表方向与烘焙结果。不能外推 |
| Unsafe 外部资源依赖 | 所有持久物理图、scratch、块图均导入 RG 并声明访问;间接表在物理复制后发布。结合连续帧内容及 Frame Debugger 验证,避免只靠禁止裁剪 |
| 多 Game 相机 | 单请求管线、单在途回读,轮转与组件重建通过;时间参数按相机捕获。Scene / Reflection 保留原生产者材质策略 |
M3 Max 支持本轮所有压缩档,因此不伪造“真实不支持硬件”的测试结论;CanCreate 参数/格式检查继续保留,其他硬件的拒绝与回退需要在相应设备验证。
完整地形烘焙链:128 页、三层、相同 producer 和资源;同一进程交替原逐页顺序与当前调度,预热三次后各采 20 次。末尾 compute 读取三张最终物理图并回读同步,确保计时依赖实际写入完成。下表是 CPU 提交 + GPU 工作 + 同步的完成墙钟时间,不等于独立 GPU 时间或整帧 FPS 提升。
| 格式 | 原顺序中位/P95 ms | 当前中位/P95 ms | 中位改善 |
|---|---|---|---|
| None | 23.077 / 24.657 | 23.063 / 27.626 | 同一路径,噪声范围 |
| BC | 37.318 / 38.670 | 27.442 / 28.383 | 26.5% |
| ETC2 | 39.036 / 40.296 | 32.523 / 33.127 | 16.7% |
| ASTC 4×4 | 60.794 / 61.778 | 51.896 / 53.132 | 14.6% |
| ASTC 6×6 | 59.959 / 61.946 | 60.092 / 61.281 | 保留单页,无收益声明 |
| ASTC 8×8 | 71.401 / 72.238 | 71.470 / 72.697 | 保留单页,无收益声明 |
独立编码 A/B 同样用输出依赖同步,128 页、20 次、高熵输入:ASTC 4×4 颜色/数据中位 20.698/22.593 → 12.953/14.241 ms;6×6 为 15.339/15.540 → 12.733/12.857 ms;8×8 为 19.178/19.385 → 16.318/16.853 ms。拟合迭代与模式不缩水。ETC2 变动 alpha 数据约 7.67 ms,未见显著变化;BC Mask 约 8.5 ms,未宣称提速。
CPU 示例为 BC / 三层 / Trilinear 的第三个 600 帧移动窗口:
| 阶段 | 中位 µs | P95 µs | 口径 |
|---|---|---|---|
| Record | 6.583 | 29.792 | 每帧记录 marker |
| Decode | 37.999 | 55.124 | 172 个有任务的帧,各 worker 执行时间之和 |
| Collect | 72.292 | 86.917 | 同上 |
| Resolve | 6.917 | 14.333 | 同上 |
| Indirect Job | 0.750 | 19.917 | 同上 |
Job 数字不是单次延迟,也不是等待时间;无任务帧没有混成“优化后的平均值”。整帧 GC 中位 34 B,禁用 VT 的对照也是 34 B;观察到的增量为 0 B,但未取得每条 VT 分配调用栈的严格归因,不能宣称整个 Editor 每帧 0 B。supportsGpuRecorder=false;虽尝试有界 Metal capture,最终没有完整可信的分阶段 GPU 中位/P95,因此 Bake / Encode / Indirect / Feedback 独立 GPU 时间留为不可得,不以墙钟或 0 值代替。
默认 PBR 三层,物理图边长 4224,无 mip,单位 MiB:
| 格式 | 物理图逻辑字节 | Scratch 逻辑字节 | 块图逻辑字节 | Unity 物理对象统计 |
|---|---|---|---|---|
| None | 204.1875 | 0.7976 | 0 | 204.1910 |
| BC | 42.5391 | 3.1904 | 0.6647 | 85.0810 |
| ETC2 | 42.5391 | 3.1904 | 0.6647 | 85.0810 |
| ASTC 4×4 | 51.0469 | 3.1904 | 0.7976 | 102.0966 |
| ASTC 6×6 | 22.6875 | 0.7976 | 0.0295 | 45.3779 |
| ASTC 8×8 | 12.7617 | 0.7976 | 0.0166 | 25.5263 |
ASTC 查找表另有 9,128 B。页目录 5,592,405 项×4 B = 22,369,620 B,目录结构另 88 B。Unity 对压缩 Texture2D 的对象统计约为逻辑字节两倍,不能据此断言有 CPU 可读副本或把该计数视为驱动实际驻留。Apple 统一内存的实际驻留量本轮未取得。相对旧 BC3/ETC2 RGBA 全层预算,按层格式的单颜色省 50%、颜色+法线省 25%、三层省 16.7%。分组额外工作集为有界数 MiB,没有整张物理 RT 中间副本。
所有代码提交在 main,无推送、PR 或新分支。AGENTS 同步数据通路约束;无旧名转发、兼容字段、Obsolete;新增文件有手写唯一 meta,asmdef 不变。测试纹理、反馈、间接表、编码结果只在内存中读取;Profiler 每次有界、Deep Profile 关闭,没有构建 Player。
临时宿主(文件合计 1,308,248,552 B)、日志、XML、脚本、截图和捕获已全部删除,另外删除本轮 21 个宿主外辅助文件与 10 个已确认的未跟踪 AppleDouble 副文件;没有清理用户的 Unity 缓存或其他 Editor。保留既有 Git 对象目录中的 AppleDouble 索引副文件,避免混入无关仓库维护。清理释放容量,不能撤销已发生的 SSD 写入,也不承诺零写入。
尚未覆盖:其他平台/Unity 6000.0 实测、移动内容长期 TAA 画质统计、XR、独立 GPU pass 完整计时、严格 GC 调用栈及驱动驻留显存。硬件各向异性候选已淘汰,不留下等待后续修补的公开开关。

