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:
shenlei
2026-09-29 19:08:19 +09:00
co-authored by Claude Opus 5.5
parent 70710477cf
commit a46093104c
2817 changed files with 13728 additions and 13744 deletions
+116
View File
@@ -0,0 +1,116 @@
#!/usr/bin/env bash
# M2 门禁·主:对测试资产集跑 oracle dump + oracle_diff,汇总 tools/granny-oracle/m2-numeric.json。
# 前置:tools/granny-oracle/build-wine.sh 已产出 oracle.exe;WINEPREFIX 已 init(见 RUNBOOK.md);
# oracle_diff 已构建(cmake -B build/tools -DMT_BUILD_TOOLS=ON)。
set -uo pipefail
cd "$(dirname "$0")/../.."
REPO="$(pwd)"
ASSETS="$(cd "${MT_ASSETS:-$REPO/assets}" && pwd)"
DUMPS="$REPO/build/oracle_dumps"
DIFF=""
for c in "$REPO/build/tools/oracle_diff"; do
[ -x "$c" ] && DIFF="$c" && break
done
[ -n "$DIFF" ] || { echo "oracle_diff not built — run: cmake -B build/tools -DMT_BUILD_TOOLS=ON && cmake --build build/tools"; exit 2; }
mkdir -p "$DUMPS"
WINE="${WINE:-/tmp/wine/Wine Stable.app/Contents/Resources/wine/bin/wine}"
export WINEPREFIX="${WINEPREFIX:-$HOME/.wine-oracle}" WINEDEBUG="${WINEDEBUG:--all}"
# Z: 盘映射到 /
winpath() { printf 'Z:%s' "$(printf '%s' "$1" | sed 's#/#\\#g')"; }
# 用例:<model 相对 assets> | <anim 相对 assets,或 -> | <t> | <mesh idx>
CASES=$(cat <<'EOF'
PC/ymir work/pc/warrior/warrior_cheongrin.gr2|-|0|4
PC/ymir work/pc/warrior/warrior_cheongrin_lod_01.gr2|-|0|4
PC/ymir work/pc/warrior/warrior_cheongrin_lod_02.gr2|-|0|4
PC/ymir work/pc/warrior/warrior_cheongrin_lod_03.gr2|-|0|4
PC/ymir work/pc/warrior/warrior_lord.gr2|-|0|1
PC/ymir work/pc/warrior/warrior_lord_lod_01.gr2|-|0|1
PC/ymir work/pc/warrior/warrior_lord_lod_02.gr2|-|0|1
PC/ymir work/pc/warrior/warrior_lord_lod_03.gr2|-|0|1
PC/ymir work/pc/assassin/assassin.gr2|-|0|16
PC/ymir work/pc/shaman/shaman_lord.gr2|-|0|0
metin2_patch_dragon_rock_mobs/ymir work/monster2/redthief2_soldier2/redthief2_soldier2_lod_01.gr2|-|0|4
monster2/ymir work/monster2/snakeman_bow/snakeman_bow_lod_01.gr2|-|0|0
monster2/ymir work/monster2/snakeman_bow/snakeman_bow_lod_01.gr2|-|0|1
metin2_patch_easter1/ymir work/pc/warrior/warrior_rabbit1_backup.gr2|-|0|0
Zone/ymir work/zone/oxevent/ox_01.gr2|-|0|0
PC/ymir work/pc/warrior/warrior_cheongrin.gr2|PC/ymir work/pc/warrior/action/dance_1.gr2|0|4
PC/ymir work/pc/warrior/warrior_cheongrin.gr2|PC/ymir work/pc/warrior/action/dance_1.gr2|4.7|4
PC/ymir work/pc/warrior/warrior_cheongrin.gr2|PC/ymir work/pc/warrior/action/dance_1.gr2|11.333|4
PC/ymir work/pc/warrior/warrior_cheongrin.gr2|PC/ymir work/pc/warrior/action/dance_1.gr2|20|4
PC/ymir work/pc/warrior/warrior_cheongrin.gr2|PC/ymir work/pc/warrior/general/attack.gr2|0.3|4
PC/ymir work/pc/warrior/warrior_cheongrin.gr2|PC/ymir work/pc/warrior/general/run.gr2|0.5|4
PC/ymir work/pc/warrior/warrior_lord.gr2|PC/ymir work/pc/warrior/action/dance_1.gr2|10|1
PC/ymir work/pc/warrior/warrior_lord.gr2|PC/ymir work/pc/warrior/general/wait.gr2|1.0|1
EOF
)
key_for() { echo "$1|$2|$3|$4" | md5 -q | cut -c1-12; }
# ── 1. dump(并行,4 个一批)──────────────────────────────────────────
run_dump() {
local model="$1" anim="$2" t="$3" mesh="$4" out="$5"
local wm; wm="$(winpath "$ASSETS/$model")"
local wa="-"; [ "$anim" != "-" ] && wa="$(winpath "$ASSETS/$anim")"
local wo; wo="$(winpath "$out")"
"$WINE" "$REPO/tools/granny-oracle/oracle.exe" dump "$wm" "$wa" "$t" -o "$wo" --mesh "$mesh" >/dev/null 2>&1
}
echo "== oracle dump =="
i=0
while IFS='|' read -r model anim t mesh; do
[ -z "$model" ] && continue
k=$(key_for "$model" "$anim" "$t" "$mesh")
out="$DUMPS/suite_$k.bin"
run_dump "$model" "$anim" "$t" "$mesh" "$out" &
i=$((i+1)); [ $((i % 4)) -eq 0 ] && wait
done <<< "$CASES"
wait
# ── 2. diff + 汇总 ─────────────────────────────────────────────────────
echo "== oracle_diff =="
JSON="$REPO/tools/granny-oracle/m2-numeric.json"
{
echo '{'
echo ' "granny": "2.9.12.0",'
echo ' "threshold": {"mat": 1e-3, "vtx": 1e-3},'
echo ' "cases": ['
} > "$JSON"
total=0; passed=0; first=1
worst_mat=0; worst_vtx=0
while IFS='|' read -r model anim t mesh; do
[ -z "$model" ] && continue
k=$(key_for "$model" "$anim" "$t" "$mesh")
bin="$DUMPS/suite_$k.bin"
total=$((total+1))
if [ ! -s "$bin" ]; then
line=" {\"model\":\"$(basename "$model")\",\"anim\":\"$(basename "$anim")\",\"t\":$t,\"mesh\":$mesh,\"status\":\"NO_DUMP\"}"
else
amodel="$ASSETS/$model"; aanim="-"; [ "$anim" != "-" ] && aanim="$ASSETS/$anim"
v=$("$DIFF" "$amodel" "$aanim" "$bin" --mesh "$mesh" 2>/dev/null | tail -1)
m=$(echo "$v" | sed -n 's/.*mat \([0-9.e+-]*\) <.*/\1/p')
vt=$(echo "$v" | sed -n 's/.*vtx \([0-9.e+-]*\) <.*/\1/p')
st="FAIL"; echo "$v" | grep -q PASS && { st="PASS"; passed=$((passed+1)); }
awk -v m="$m" -v w="$worst_mat" 'BEGIN{exit !(m+0>w+0)}' && worst_mat=$m
awk -v m="$vt" -v w="$worst_vtx" 'BEGIN{exit !(m+0>w+0)}' && worst_vtx=$vt
printf ' [%-4s] %-40s %-14s mat=%-10s vtx=%s\n' "$st" "$(basename "$model")" "$(basename "$anim") @${t}" "$m" "$vt"
line=" {\"model\":\"$(basename "$model")\",\"anim\":\"$(basename "$anim")\",\"t\":$t,\"mesh\":$mesh,\"mat\":$m,\"vtx\":$vt,\"status\":\"$st\"}"
fi
[ $first -eq 1 ] && first=0 || echo ',' >> "$JSON"
printf '%s' "$line" >> "$JSON"
done <<< "$CASES"
{
echo ''
echo ' ],'
echo " \"summary\": {\"total\": $total, \"passed\": $passed, \"worst_mat\": $worst_mat, \"worst_vtx\": $worst_vtx}"
echo '}'
} >> "$JSON"
echo
echo "== $passed/$total PASS worst mat=$worst_mat vtx=$worst_vtx → $JSON =="
[ "$passed" -eq "$total" ]