layout: restructure into src/ tests/ android/ scripts/ tools/
- extension/src/{port,platform,codepage} -> src/; native_render -> src/host
(+ dxt, shaders/); libgr2 -> src/gr2; extension/third_party -> third_party
- extension/tests -> tests/port, libgr2/tests -> tests/gr2
- android-native -> android (build.sh, push-client.sh moved in)
- script -> scripts; tools/40250 -> tools/server; oracle -> tools/granny-oracle;
perf tools -> tools/perf
- all build trees under build/ (native, release, android, port-gate)
- xrender:: CMake aliases -> mt::; port-map ledger impl paths rewritten
No code changes. ctest 15/15, port_gate macos+android PASS, port_map check 0 errors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
70710477cf
commit
a46093104c
@@ -69,7 +69,7 @@
|
||||
### 3. 屏幕刷新率(ProMotion 120Hz)与 40250 逻辑时钟(60 FPS)失步
|
||||
* **代码位置**:
|
||||
- `project/project.godot`(未配置 `max_fps`)
|
||||
- `extension/src/port/EterBase/Timer.cpp:109-116`
|
||||
- `src/port/EterBase/Timer.cpp:109-116`
|
||||
* **机制危害**:
|
||||
- MacBook 屏幕通常为 120Hz ProMotion。当前 `project.godot` 没有设置帧率上限,Godot 默认以 120 FPS 运行 `_process`。
|
||||
- 这导致上述所有 C++ 内存封包、显存频繁重建、线程唤醒**以每秒 120 次的频率翻倍运行**。
|
||||
@@ -99,7 +99,7 @@
|
||||
---
|
||||
|
||||
### 5. 双线程每帧条件变量往返切换(Ping-Pong Jitter)
|
||||
* **代码位置**:`extension/src/platform/ScriptLib/PythonBoot.cpp:597, 612-616`
|
||||
* **代码位置**:`src/platform/ScriptLib/PythonBoot.cpp:597, 612-616`
|
||||
* **机制危害**:
|
||||
Godot 主线程与 Python Script 线程通过 `g_fiber.cv.notify_all()` 与 `cv.wait()` 互斥锁交替执行。主线程渲染完必须挂起等待 Script 线程完成 `Process()`,若 macOS 系统调度器将其中一个线程调度到了能效核(E-Core)或与其他系统后台任务竞争,会造成帧间隔不均匀(Frame Time Jitter)。
|
||||
|
||||
@@ -206,7 +206,7 @@
|
||||
|
||||
### 独立 Vulkan/MoltenVK 原型(2026-09-25)
|
||||
|
||||
新增 `native_render/`:SDL3 创建独立窗口,Vulkan 创建交换链、顶点缓冲、管线与逐 draw 提交;macOS 通过 MoltenVK 映射到 Metal。它直接读取录制设备的 `Render3DDraw` 结构,也能回放 Godot 客户端显式捕获的一帧。构建和回放命令见 `native_render/README.md`。现有 Godot 客户端运行路径未切换。
|
||||
新增 `src/host/`:SDL3 创建独立窗口,Vulkan 创建交换链、顶点缓冲、管线与逐 draw 提交;macOS 通过 MoltenVK 映射到 Metal。它直接读取录制设备的 `Render3DDraw` 结构,也能回放 Godot 客户端显式捕获的一帧。构建和回放命令见 `src/host/README.md`。现有 Godot 客户端运行路径未切换。
|
||||
|
||||
#### 第一阶段:基础提交与每帧 CPU 展开基线
|
||||
Apple M4 上,合成的 64 draw × 333 三角形(63,936 个展开顶点)运行 60 帧,平均帧间隔 16.64 ms,CPU 几何准备 6.80 ms。真实 64 怪测试捕获的一帧(`64-mob.mtdr`,v1)为 51 draw、51,231 个索引;回放 60 帧,平均帧间隔 16.81 ms,CPU 几何准备 5.96 ms。
|
||||
@@ -217,7 +217,7 @@ Apple M4 上,合成的 64 draw × 333 三角形(63,936 个展开顶点)运
|
||||
|
||||
#### 第三阶段:深度缓冲、DDS 贴图、法线/UV 与 D3D8 固定管线状态(Version 3 捕获)
|
||||
1. **深度与固定管线状态**:新增 `VK_FORMAT_D32_SFLOAT` 深度附件,按 `(cull_mode, z_enable/z_write, alpha_blend/dest_blend)` 缓存 `VkPipeline`,在 `native.vert` / `native.frag`(128 字节 Push Constants,满足桌面与 Android Vulkan 最小保证)中实现 D3D8 方向光(`light0` + 环境光 + 自发光)、`texture_factor` 调制与 `alpha_test` 裁剪。
|
||||
2. **自包含 DDS 贴图回放**:捕获格式升级为 Version 3(向下兼容 v1/v2),在 `MT_NATIVE_CAPTURE_PATH` 触发时自动从 40250 pack 提取被引用的 `.dds` 原始字节写入 `.mtdr`;`mt_native_render` 复用 `extension/src/dxt.cpp` 在首帧软解 DXT1/3/5 并上传至 `VK_IMAGE_TILING_OPTIMAL` 纹理与描述符集。
|
||||
2. **自包含 DDS 贴图回放**:捕获格式升级为 Version 3(向下兼容 v1/v2),在 `MT_NATIVE_CAPTURE_PATH` 触发时自动从 40250 pack 提取被引用的 `.dds` 原始字节写入 `.mtdr`;`mt_native_render` 复用 `src/host/dxt.cpp` 在首帧软解 DXT1/3/5 并上传至 `VK_IMAGE_TILING_OPTIMAL` 纹理与描述符集。
|
||||
3. **修复无 `MT_PROFILE_FRAME` 时 64 怪测试 `dog_screen=(-1,-1)` 失败的根因**:
|
||||
- 根因一:`CPythonNetworkStream::GamePhase()` 每帧最多消费 3 个网络包,64 怪场景的进图突发包(约 147 个包,含末尾 `GC_PING`)需要约 49 帧排空;此前未开启 `MT_PROFILE_FRAME` 时仅等待 30 帧就点击地面移动,导致客户端在回复 `CG_PONG`(254)前先发出了 `CG_CHARACTER_MOVE`(7),伪造服务端报 `expected CG header 254, got 7` 并主动断开连接清空角色。
|
||||
- 根因二:`settled` 闭包未检查 `now.x >= 0.0`,连续两帧 `(-1, -1)` 距离为 `0.0 < 0.5` 会提前退出等待。
|
||||
@@ -237,16 +237,16 @@ Apple M4 上,合成的 64 draw × 333 三角形(63,936 个展开顶点)运
|
||||
#### 第四阶段:硬件 GPU 时间戳、40250 地形 HTP、2D UI/字形/小地图遮罩、GPU 骨骼蒙皮与实时游戏主循环接入(Version 4 捕获)
|
||||
|
||||
1. **分离真实 GPU 执行耗时(`gpu_ms`)与垂直同步等待(`submit_ms`)**:
|
||||
- 在 `native_render/main.cpp` 中接入 `VkQueryPool`(`VK_QUERY_TYPE_TIMESTAMP`),在 `vkCmdBeginRenderPass`(`TOP_OF_PIPE`)与 `vkCmdEndRenderPass`(`BOTTOM_OF_PIPE`)记录硬件时间戳并换算为毫秒级 `gpu_ms`。
|
||||
- 在 `src/host/main.cpp` 中接入 `VkQueryPool`(`VK_QUERY_TYPE_TIMESTAMP`),在 `vkCmdBeginRenderPass`(`TOP_OF_PIPE`)与 `vkCmdEndRenderPass`(`BOTTOM_OF_PIPE`)记录硬件时间戳并换算为毫秒级 `gpu_ms`。
|
||||
- 新增 `--no-vsync`(优先选用 `VK_PRESENT_MODE_IMMEDIATE_KHR` / `MAILBOX_KHR`),将交换链垂直同步等待从 `submit_ms` 中剥离。
|
||||
2. **40250 原生硬件变换地形块(HTP)渲染**:
|
||||
- 在 `extension/src/platform/GameLib/MapOutdoorRenderHTP.cpp` 中实现 `CMapOutdoor::__RenderTerrain_RenderHardwareTransformPatch()` 与 `__HardwareTransformPatch_RenderPatchSplat(...)`(由 `SetNativeTerrainRenderEnabled(true)` 或 `MT_NATIVE_TERRAIN=1` 启用,不影响 Godot 默认测试路径)。
|
||||
- 在 `extension/src/platform/EterLib/RecordingDevice.cpp` 中支持 D3D8 `D3DTSS_TCI_CAMERASPACEPOSITION` 相机空间纹理矩阵生成地形基础层与 Alpha Splat 层 UV,并将 `m_textures[0]` 混入 `geometry_key` 实现跨帧持久化缓存。
|
||||
- 在 `src/platform/GameLib/MapOutdoorRenderHTP.cpp` 中实现 `CMapOutdoor::__RenderTerrain_RenderHardwareTransformPatch()` 与 `__HardwareTransformPatch_RenderPatchSplat(...)`(由 `SetNativeTerrainRenderEnabled(true)` 或 `MT_NATIVE_TERRAIN=1` 启用,不影响 Godot 默认测试路径)。
|
||||
- 在 `src/platform/EterLib/RecordingDevice.cpp` 中支持 D3D8 `D3DTSS_TCI_CAMERASPACEPOSITION` 相机空间纹理矩阵生成地形基础层与 Alpha Splat 层 UV,并将 `m_textures[0]` 混入 `geometry_key` 实现跨帧持久化缓存。
|
||||
3. **2D `UIRenderCommand` 全量渲染(含字形图集与小地图圆角遮罩)**:
|
||||
- 支持 `behind_3d` 与前景两趟正交 2D 渲染,涵盖 `Bar`、`GradientBar`、`Line`、`Image`、裁剪矩形(`clip_x1..y2`)、`mem:<id>@<revision>` 动态字形图集(`"MTRA"` 原始 RGBA 编码)、`.tga`(含未压缩与 RLE)解码,以及 `CPythonMiniMap` 的双纹理(`tex0` + `mask_tex`)圆角遮罩混合。
|
||||
- 相邻同状态、同纹理的 UI 图元与字形自动合并为单次 `vkCmdDrawIndexed` 批次提交(64 怪场景 1,597 个 UI/字形四边形成批为 31 个 Vulkan 批次)。
|
||||
4. **GPU 线性混合骨骼蒙皮(GPU Skeletal Skinning)**:
|
||||
- 在 `extension/src/platform/EterGrnLib/GrannyRuntime.cpp` 中,当启用 GPU 蒙皮(`--gpu-skinning` 或 `MT_GPU_SKINNING=1`)时,`GrannyDeformVertices` 不再逐帧在 CPU 上对每个顶点做矩阵加权变形,而是按不可变的源网格指针(`SourceVertices`)提取一次静态绑定姿态(Bind-Pose)顶点、法线、4 骨骼索引(`bone_indices`)与 4 骨骼权重(`bone_weights`),仅将当前实例的骨骼矩阵调色板(`bone_count * 16` 个 `float`)写入切片表。
|
||||
- 在 `src/platform/EterGrnLib/GrannyRuntime.cpp` 中,当启用 GPU 蒙皮(`--gpu-skinning` 或 `MT_GPU_SKINNING=1`)时,`GrannyDeformVertices` 不再逐帧在 CPU 上对每个顶点做矩阵加权变形,而是按不可变的源网格指针(`SourceVertices`)提取一次静态绑定姿态(Bind-Pose)顶点、法线、4 骨骼索引(`bone_indices`)与 4 骨骼权重(`bone_weights`),仅将当前实例的骨骼矩阵调色板(`bone_count * 16` 个 `float`)写入切片表。
|
||||
- 在 `RecordingDevice.cpp` 中,所有共享同一 `.gr2` 源网格的怪物/角色实例共享同一个 `geometry_key` 且 `geometry_revision` 恒为 `1`;`native.vert` 通过 `set = 1, binding = 0` 的 `BonePalette` SSBO 在顶点着色器中完成 4 骨骼线性混合蒙皮。
|
||||
5. **实时游戏主循环直接接入(`--live-client`)**:
|
||||
- 当 `mt_native_render` 在主构建目录 `build/` 下构建时,直接链接 `port_platform`、`mtpython` 与 `FakeLoginServer`,通过 `--live-client <ClientDir>` 在原生 SDL3 + Vulkan 窗口内直接启动 40250 `system.py`,完成登录、选人、进图、刷出 1~64 只怪物、转发 SDL3 键鼠事件,并可导出包含 3D 骨骼权重、地形、2D UI 与字形页的 Version 4 `.mtdr` 捕获文件。
|
||||
@@ -277,13 +277,13 @@ Apple M4 上,合成的 64 draw × 333 三角形(63,936 个展开顶点)运
|
||||
- 支持 `SDL_WINDOW_RESIZABLE` 与 `VK_ERROR_OUT_OF_DATE_KHR` / `VK_SUBOPTIMAL_KHR` 交换链自动重建,并同步调用 `PythonBoot::SetUISize`。
|
||||
- 接入 macOS `ImageIO` 解码器,支持从 40250 pack 直接解码 `.jpg` / `.png` / `.bmp` 登录背景与 UI 贴图;并在未显式设置 `VK_ICD_FILENAMES` 时自动探测 Homebrew `MoltenVK_icd.json`。
|
||||
2. **补齐剩余 3D 场景视觉要素**:
|
||||
- **水面(Water)**:移植 `extension/src/platform/GameLib/MapOutdoorWater.cpp`(`CMapOutdoor::RenderWater` 与 `DrawWater`),支持 30 帧循环水面贴图、相机空间水面变换矩阵与基于高度差的顶点 Alpha 混合。
|
||||
- **天空盒与动态云层(Skybox & Clouds)**:移植 `extension/src/platform/EterLib/SkyBox.cpp`(`CSkyObjectQuad`、`CSkyObject`、`CSkyBox::Render`、`CSkyBox::RenderCloud`),并在 `RecordingDevice.cpp` 中支持 Stage 0 二维纹理矩阵变换(`D3DTTFF_COUNT2`)与 `D3DTOP_MODULATEINVALPHA_ADDCOLOR`(19)云层着色模式。
|
||||
- **水面(Water)**:移植 `src/platform/GameLib/MapOutdoorWater.cpp`(`CMapOutdoor::RenderWater` 与 `DrawWater`),支持 30 帧循环水面贴图、相机空间水面变换矩阵与基于高度差的顶点 Alpha 混合。
|
||||
- **天空盒与动态云层(Skybox & Clouds)**:移植 `src/platform/EterLib/SkyBox.cpp`(`CSkyObjectQuad`、`CSkyObject`、`CSkyBox::Render`、`CSkyBox::RenderCloud`),并在 `RecordingDevice.cpp` 中支持 Stage 0 二维纹理矩阵变换(`D3DTTFF_COUNT2`)与 `D3DTOP_MODULATEINVALPHA_ADDCOLOR`(19)云层着色模式。
|
||||
- **SpeedTree 森林与树木(SpeedTreeLib)**:实现 `SpeedTreeForest.cpp`、`SpeedTreeForestDirectX8.cpp` 与 `SpeedTreeWrapper.cpp`,读取 40250 `.spt` 属性与 `"TreeSize"` 参数生成带树皮贴图与树叶交叉十字网格的 Z-up 顶点/索引缓冲并参与渲染。
|
||||
- **多级纹理高光(Specular Sphere-Map)与完整混合因子**:在 `PythonApplication.cpp` 中实现 `CGrannyMaterial::CreateSphereMap` 与 `TranslateSpecularMatrix`,在 `native.vert` / `native.frag` 中实现球面环境映射 UV 生成与 `D3DTOP_MODULATEALPHA_ADDCOLOR`(18)高光叠加,并补齐完整 D3D8 `src_blend` / `dest_blend` 因子映射。
|
||||
- **修复退出纯虚函数崩溃**:移除基类析构函数 `CSkyObject::~CSkyObject()` 对纯虚函数 `Destroy()` 的调用,以及 `CSpeedTreeForest::~CSpeedTreeForest()` 对纯虚函数 `Clear()` 的调用(移入派生类 `CSpeedTreeForestDirectX8::~CSpeedTreeForestDirectX8()`),解决客户端退出时 `libc++abi: Pure virtual function called!` 崩溃。
|
||||
3. **音频播放接入(SDL3 Audio + AudioToolbox)**:
|
||||
- 在 `native_render/main.cpp` 中实现 `NativeAudioEngine`,每帧排空 `DrainAudioCommands()`,通过 macOS `AudioToolbox`(`AudioFileOpenWithCallbacks` + `ExtAudioFileRead`)直接从内存解包 `.wav` / `.mp3` 为 44.1 kHz 双声道浮点 PCM,送入 `SDL_AudioStream` 完成 2D/3D 音效混音与 BGM 淡入淡出循环播放。
|
||||
- 在 `src/host/main.cpp` 中实现 `NativeAudioEngine`,每帧排空 `DrainAudioCommands()`,通过 macOS `AudioToolbox`(`AudioFileOpenWithCallbacks` + `ExtAudioFileRead`)直接从内存解包 `.wav` / `.mp3` 为 44.1 kHz 双声道浮点 PCM,送入 `SDL_AudioStream` 完成 2D/3D 音效混音与 BGM 淡入淡出循环播放。
|
||||
4. **完整键盘/IME 文本输入与原生软件光标**:
|
||||
- 补齐 `F1`–`F12`、`Tab`、`Backspace`、`Return`、`Delete`、`Shift`/`Ctrl`/`Alt`、方向键、数字小键盘及符号键的 `SDL_Scancode -> DIK_*` 与 `VK_*`(`PythonBoot::UIIMEKeyDown`)映射,接入 `SDL_EVENT_TEXT_INPUT` 转发 UTF-8 字符至 `PythonBoot::UIChar`。
|
||||
- 启用 40250 `CURSOR_MODE_SOFTWARE`(`OnMouseUpdate` / `OnMouseRender`),当游戏软件光标激活时自动隐藏系统光标并渲染 40250 原生彩色游戏光标。
|
||||
|
||||
Reference in New Issue
Block a user