Commit Graph
4 Commits
Author SHA1 Message Date
company-desktop d671000269 fix: AecRxBase 里的 3D 缓存块去掉对 CoreLibrary 的依赖
修 rebase 后暴露的编译/链接问题(AecRxBase 不链接 CoreLibrary):
- 去掉 SectionPerf 计数器(SectionPerfCounter 的实现只在 CoreLibrary 里,
  AecRxBase 用的是自己那份静态副本,打不进同一份报告,本来也没有意义);
- 去掉 CMFCDbDwgFiler 判断(CMFCDbDwgFiler 也定义在 CoreLibrary),
  内存 filer 走同一条存取路径即可。
2026-10-30 08:47:58 +08:00
company-desktop 9088c47bee feat: 通用 3D 缓存块存取(AecDbEntityCommon)+ 先挂在管件上
按"缓存挂在母体实体的 3dbuffer 上"的思路,把上一轮在 AecDbX3dPartEntity 里写的存取逻辑
提成通用能力:

- AecDbEntityCommon::Write3DBufferBlock() / Read3DBufferBlock():
  只能在最派生类的 dwgOut/dwgInFields 末尾调用;缓存里**全是 brep 才写**,
  有一个非 brep(中心线/箭头等)就整条不写(用户定的语义);
  读不到 magic / 校验失败 → 保持空缓存,照旧重建;不动版本号;内存 filer 不参与。
- AecDbEwFitting 上先挂了两个 hook(管件是全库 Add3DBuffer 用得最多的类,96 处)。
- 开关 AEC_3D_DWG_CACHE,默认关(=1 才写/读),Release 与正常存盘零影响。
- AEC_HAS_MODELER_FILER 对中望也打开(沿用上一轮的 cmake 改动)。

实测结论(big1.dwg,MOVE 弄脏 + REGENALL + QSAVE):
- 存盘后的 DWG 里 magic A3DB 出现 0 次 —— 一个块都没写出去;
- 同一次存盘里 EwPipe::RegionAcisout 3011 次,说明"弄脏+重序列化"这条路本身是通的。

原因(两堵墙互相顶):改过的实体在 AssertWriteEnabled 里就被清空了 3D 缓存
(而且 REGENALL 只重建视口可见的对象);没改过的实体增量存盘按字节拷贝、根本不调
dwgOutFields。所以"缓存有效"和"实体是脏的"在存盘那一刻基本不同时成立 ——
"塞进实体自己的流"这条路机制上不成立,不是值不值的问题。

分析写进 3d-cache-dwg-verdict.md §9,并给出唯一自洽的方向:缓存与实体序列化解耦
(隐藏块/字典里的 Xrecord 旁挂 + 命令结束/空闲时写入 + 按 handle 失效)。
这一版的两个函数就是那个方向的 modeler 存取基础,留着复用。
2026-10-30 08:39:35 +08:00
company-desktop 7038a98441 diag: 用 PDB 解析栈帧,定位到 AecDbEwPipeBase::copyFrom 里的多余序列化
上一版只给了"模块+RVA"的栈,我据此先后推断成
AecDbCurveBase::subGetTransformedCopy 和 AecDbEntityCommon::base_DeepClone,两者都是错的
(用户在那里下断点不命中;新加的 PerfTraceMark 打点也没有触发)。本次用符号解析定死。

本次改动:
- 新增 inc/PerfTraceMark.h:inline 的"某函数被调用过"打点,Debug 且 AEC_WRITEBACK_TRACE=1
  才生效。AecRxBase.arx 不链接 CoreLibrary(静态库只被 CoreCommand 链接),拿不到 SectionPerf,
  所以做成 header-only。
- 在 5 个候选入口打点:AecDbCurveBase::subGetTransformedCopy / subDeepClone、
  AecDbEntityBase::subDeepClone、AecDbEntityCommon::base_DeepClone、CKTCadUtility::CloneObject。
  跑一次开图,5 个都没触发 —— 这些候选被排除。
- 新增 tools/resolve_rva.ps1:用 dbghelp 的 SymLoadModuleEx / SymFromAddr 配本地 PDB,
  把"模块+RVA"解析成函数名。Windows 没有自带 symbolizer,这个脚本很轻,可反复用。

解析结果(CoreCommand.arx):
  0x58f051  AecDbEwPipeBase::copyFrom+0x41
  0x7e1300  AecDbZLineStair::DrawGuarBar3d+0x2c0
  0x7e09d0  AecDbZLineStair::DrawSteep3d+0xbe0
  0x7ddcef  AecDbZLineStair::Draw3d+0x34f

真实成因:Z 型楼梯画护栏(DrawGuarBar3d)时 copyFrom 一份管道实体,
而 AecDbEwPipeBase::copyFrom 用通用的 CopyObject(inc/AecDbEntityCommon.h:331)
做"整实体 dwgOutFields/dwgInFields 往返"来拷字段,于是截面被写成临时 SAT 文件再读回来。

而且这次序列化是多余的:copyFrom 随后把所有字段又用内存级方式拷了一遍
(曲线 clone/copyFrom、截面 clone/copyFrom、XData CopyFrom、m_arUserInfs append、
标志位/图层/线型/Breaks 逐项赋值),WriteUserInterface 写的也只是 m_arUserInfs。
所以最小修改是把那句 CopyObject 去掉,并补上源为 NULL 时清空目标的分支
(目前这个"清空"是 CopyObject 顺带完成的)。

本次只做定位与记录(分析写进 pipe-section-region-performance-plan.md 并纠正了上一版的误判),
不改 copyFrom 的行为——它影响所有管系实体的复制粘贴/块内拷贝,需要单独验证。
2026-10-28 21:28:00 +08:00
gjm c84bc78869 重构底层
重构AecDbEntityBase,AecDbCurveBase
2026-10-19 09:19:05 +08:00