Networked client on the existing Godot 4.7 + libgr2 renderer:
- net: m2dev wire protocol (libsodium KX + XChaCha20), auth/select/game
phases, EntityStore world model, ~all GC/CG headers. char create/delete,
private shop / mall / cube, SHOP_GC_START_EX, guild, party (+ CG_PARTY_SET_STATE),
quests, dragon soul, refine, safebox, exchange.
- UI: in-game windows migrated 1:1 from the reference uiscript/root .py —
char status (/stat), inventory+equipment, select-item ([SELECT_ITEM] quest
token), system-option + game-option + ESC system menu, private-shop 39-grid,
party info board, shop tabs, atlas, minimap, quickbar, chat, …
- EterGrnLib polish: GR2 material blend/two-sided, LOD crossfade, motion-event
dispatch, contact shadow, ray-AABB picking, weapon grip pre-transform.
Portable asset IO (A1) — all extension/libgr2/formats/mtproto reads routed
through godot::FileAccess (res:// PCK works on iOS/Android); standalone-lib
*_path() kept for the non-Godot CTests. AssetResolver + PropertyRegistry
switched to a baked index (bake_asset_index.gd) instead of std::filesystem.
Mobile builds: build-{android,ios}.sh, export-android.sh, pack-assets.sh,
gen-debug-keystore.sh. Assets ship as a zip mounted at runtime by
project/asset_pack.gd (adb push now; HTTP download is a drop-in later).
ctest 10/10, 34 GDScript suites, macOS/iOS/Android all build.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EJxkHiNKS4kybHS3XKyAJ
8.7 KiB
8.7 KiB
M3 · iOS + Android 真机
总纲:
../PLAN.md§04 / §06 / §07。 本文件是 M3 的详细施工文档。与 M2 尾段并行。
目标
把 M2 的工程原样交叉编译到 iOS + Android 真机跑基准场景, 证明三端渲染一致、移动端性能达标、生命周期(context loss / 后台)稳。
前置
交付物
| 产物 | 位置 |
|---|---|
iOS .app(Xcode / CMake iOS toolchain) |
platform/ios/ |
Android APK(NDK / Gradle 或纯 CMake + native_app_glue) |
platform/android/ |
| 三端 CI(macOS 原生 + iOS 模拟器 + Android 模拟器) | .github/ 或等价 |
| 真机性能采集报告 | test/m3-perf.json |
| 三端快照互拍报告 | test/m3-snapshot.json |
任务分解
T1 · 资产上真机方案(PLAN §04 / §08)
- 9166 个散装
.gr2+.dds不能直接堆进 APK /.bundle(体积、iOS 限制)。二选一:- A(推荐):M3 前提前接
EterPack(现排 M4),资产走.eix/.epk,CMappedFile的 mmap /AAsset_getBuffer路径。 - B(最小):只把
test/assets.list里那 ~15 个 + 依赖贴图打进去。
- A(推荐):M3 前提前接
- 完成判据:真机上
libgr2能加载 warrior + dance_1,路径与桌面散文件结果一致。
T2 · 平台壳
- 窗口 / 生命周期:按 M1 T0b 结论——sokol_app(若交接成了)或各平台最小原生壳(iOS
MTKView+CADisplayLink;AndroidNativeActivity/GLSurfaceView)。 - iOS:全静态链接(无
dlopen);.bundle打包资产;Info.plist/ 签名走开发证书(不涉及上架)。 - Android:NDK
arm64-v8a+armeabi-v7a;AAssetManager经 JNI 注入(复用 MobileSourceAndroidMain.cpp形态)。 - bgfx
init.type:iOS =Metal;Android =OpenGLES(或Vulkan,先 GLES3 稳)。
T3 · Android context loss(PLAN §08 高危,确定项)
- 切后台 → GL context 连同 GPU 资源可能失效。
- 在
SUSPENDED/RESUMED(或onSurfaceDestroyed/Created)里按 bgfx 的重置流程:bgfx::reset+ 必要时重建sg_*/ bgfx 资源句柄。 - 测试:切后台 ×100(
adb shell input keyevent KEYCODE_HOME+ 回前台脚本循环)。 - 完成判据:100 次无崩、无黑屏、无资源泄漏(
adb shell dumpsys meminfo稳定)。
T4 · iOS 后台 / drawable 生命周期(PLAN §10.1)
- 切后台 / 锁屏 / 来电 → 丢
CAMetalDrawable。 applicationWillResignActive暂停渲染循环;didBecomeActive恢复;nextDrawable返回 nil 时跳过该帧不崩。- 完成判据:后台 / 锁屏 / 来电各 ×20 恢复正常。
T5 · mediump 精度专项(PLAN §08 / §10.1)
- 移动 GPU 上
mediump存不下 60 骨链的骨骼矩阵 / 大坐标 → 抖动 / 爆顶点。 - 顶点着色器里骨骼矩阵与位置强制
highp;必要时把模型原点归一(减去包围盒中心)。 - 测试:highp 前后对比截图,确认抖动 / 爆顶点消失。
- 完成判据:highp 版无可见抖动。
T6 · 性能采集(PLAN §07 性能层)
- 基准硬件写死具体机型:iPhone 11(A13)+ Pixel 6(Mali-G78)+ 一台 Adreno 机。
- 两种角色:① 简化(≈5k 三角、≈60 骨、单 draw call);② 满配(多部件 + 武器 + 时装 + 挂点特效,1–2 万三角、多 draw call)。每种 1 → 8 → 20 → 50 个。
- 指标:帧时间 p50/p99、FPS、draw call、GPU 显存(Xcode GPU report / Android GPU Inspector /
adb dumpsys meminfo)、冷启动到首帧、单.gr2加载耗时、峰值 RSS。 - 写进
test/m3-perf.json,逐项标注是否越线。
T7 · 三端快照互拍 + CI
- 确定性场景在 macOS / iOS / Android 各渲一帧,两两 SSIM。
- 三端之间应比各自与 oracle 更接近(同
shaderc源、同逻辑)。 - CI:iOS 模拟器 + Android 模拟器构建并启动,断言"到达首帧 + 连续 N 帧无 bgfx / Metal / GLES 验证层报错"(开
BGFX_DEBUG_*、Metal API validation、GLESKHR_debug)。
门禁(go / no-go)
- 三端渲染差异分类通过(不是"逐像素一致",见 PLAN §07 视觉层:SSIM ≥ 0.98 直接过;0.95–0.98 进分类;< 0.95 fail)。
- 性能:简化角色 1 个 ≥ 60fps、20 个 ≥ 30fps;满配角色 1 个 ≥ 60fps、8 个 ≥ 30fps;冷启动 < 3s;基准 RSS < 300MB;单角色加载 < 30ms。
- 无 bgfx / 图形验证层报错。
- Android 切后台 ×100 恢复正常;iOS 后台 / 锁屏 / 来电恢复正常。
- mediump 精度专项通过(highp 后无抖动)。
验证
- 三端快照互拍矩阵(T7)。
- 真机性能逐项对通过线(T6)。
- 生命周期压力测试脚本可复现(T3 / T4)。
本步风险(从 PLAN §08 筛)
| 风险 | 缓解 |
|---|---|
| Android GL context 丢失后 GPU 资源需重建(确定项) | T3 在 suspend/resume 走 bgfx reset;M3 就做别拖 |
| iOS 全静态 + 后台丢 drawable | T2/T4 全静态链接 + drawable nil 跳帧 |
| 9166 散装资产上真机方式没定 | T1 二选一,M3 交付显式包含 |
| 移动 GPU mediump 精度不足 | T5 骨骼矩阵 / 位置用 highp |
shaderc 跨编译 metal / 300_es 行为差异 |
单一 .sc 源;开验证层;T7 三端快照对拍 |
| 深度范围 / Y 翻转后端差异 | bgfx::getCaps()->homogeneousDepth / originBottomLeft 抹平 |
| sokol_app 交接在 iOS/Android 也不成 | 用各平台最小原生壳(T2 备选) |
DoD 清单
- [~] iOS 模拟器跑起来,播 dance_1,CPU 蒙皮 + bgfx Metal,输出与 macOS 同 t 像素级一致(同
.bin着色器、同demo_core)。test/golden/m3-ios-*.png。真机(差异分类、后台/锁屏/来电、mediump、perf)待设备。 - Android 真机 —— 脚手架就绪(
platform/android/)未构建:本机无 NDK。 test/m3-perf.json—— 待真机- Android 切后台 ×100 —— 待设备(
android_main.cpp的APP_CMD_TERM/INIT_WINDOW分支已写 shutdown/reinit) - iOS 后台 / 锁屏 / 来电 —— 待设备(
ios_main.mm的applicationWillResignActive/DidBecomeActive暂停/恢复 CADisplayLink 已写) - mediump → highp 专项 ——
vs_pnt_skinned.sc已写(骨骼矩阵 + 位置全highp);对比测试待真机 GPU - CI 三端 job —— 待
- M3 全绿 = PLAN §01 判定"方案可行" —— iOS 一端已验证(编译 + 运行 + 渲染一致);Android 端 + 真机压测待设备
M3 实现结果(本轮)
| 项 | 结果 |
|---|---|
| 平台无关核心 | app/demo_core.{h,cpp} —— 加载 gr2 + 建场景 + 采样姿势 + 画,无窗口/输入依赖。桌面壳(app/main.cpp GLFW)+ iOS 壳(platform/ios/ios_main.mm UIKit)+ Android 壳(platform/android/android_main.cpp native_app_glue)都调它。 |
| iOS 壳(T2) | ios_main.mm:UIApplicationMain → MetalView(+layerClass = CAMetalLayer)→ CADisplayLink 驱 demo::frame。bgfx nwh = CAMetalLayer*,init.type = Metal。生命周期回调(T4 骨架)已接。 |
| iOS 构建 + 运行 | cmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator → BUILD SUCCEEDED。xcrun simctl 装 + 跑 iPhone 16 Pro 模拟器:libgr2 加载 warrior + dance_1、DXT3/DXT1 解码、bgfx Metal init、CADisplayLink 跑 120 帧无崩、requestScreenShot 出图。渲染结果与桌面同 t 一致。 |
| 交叉编译坑 | ① BGFX_CONFIG_VIDEO 默认 ON,video_mtl.cpp 在 iOS 模拟器编不过(CVMetalTextureCache 不可用)→ 关掉。② shaderc 跑不了目标平台 → xrender_compile_shaders(... PREBUILT <dir>) 用宿主机预编译的 metal .bin(Metal 字节码 macOS/iOS 通用)。③ iOS 不建 GLFW(third_party/CMakeLists.txt 加 NOT IOS 守卫)。 |
| Android 壳(T2) | platform/android/:android_main.cpp(native_app_glue + ANativeWindow → bgfx GLES nwh + AAssetManager 解资产)、CMakeLists.txt(NDK,链 xr_democore + bgfx GLES)、build.gradle + AndroidManifest.xml(NativeActivity)。未构建(本机无 NDK,platform/android/README.md 记了装 NDK 后的步骤)。 |
| T5 GPU 蒙皮 shader | app/shaders/vs_pnt_skinned.sc:u_bones[64] 混合,骨骼矩阵 + 位置 + 法线全 highp。未接进 demo(demo 走 CPU 蒙皮 = M2 数值门禁路径),留 M4 CPU/GPU 一致性 + 真机 mediump 对比。 |