diff --git a/a.md b/a.md deleted file mode 100644 index adc6fae..0000000 --- a/a.md +++ /dev/null @@ -1,1919 +0,0 @@ -下面这份直接作为 Codex 的完整执行计划使用。所有条目都按强制要求执行,不保留旧实现,不增加兼容层,不引入独立 PerfTrace 库。 - -# Renderive Kernel Render DAG 完整改造执行计划 - -## 0. 总目标 - -将 Plot 内部渲染执行统一改造成: - -```text -Renderable 状态 - + -Renderable 数据依赖 - + -Renderable 图层依赖 - + -prepare_buffer 状态 - + -paint_buffer 状态 - + -Renderable 内部任务 DAG - │ - ▼ - render_plan compiler - │ - ▼ - ONE Render DAG - │ - ▼ - ONE Taskflow - │ - ▼ - Frame 执行 - │ - ├── 普通运行:不记录详细性能 - │ - └── Capture:直接写 Frame execution slots - │ - ▼ - 三缓冲完成交换 - │ - ▼ - immutable frame_snapshot - │ - ┌─────┴────────┐ - ▼ ▼ -frame_analysis node_statistics - │ │ - └──────┬───────┘ - ▼ - 后端 API - │ - ▼ -前端 DAG + Worker Timeline + 多帧统计 -``` - -Kernel Render DAG 必须同时成为: - -```text -执行依赖的唯一事实来源 -Taskflow 编译的唯一事实来源 -单帧性能分析的唯一事实来源 -前端 DAG 展示的唯一事实来源 -``` - ---- - -# 1. 锁死 Renderable 三阶段语义 - -Renderable 的执行语义必须明确分成: - -```text -prepare - ↓ -paint - ↓ -composite -``` - -这三个阶段不是全局阶段,不允许建立全局 barrier。 - -它们是每个 Renderable 以及 Renderable 内部任务自己的局部依赖关系。 - -必须严格执行以下语义。 - -### `prepare` - -`prepare` 必须完成: - -```text -读取自身业务数据 -读取其他 Renderable 提供的数据 -处理所有跨 Renderable dependency -坐标转换 -数据转换 -几何计算 -可见范围计算 -裁剪信息计算 -布局结果准备 -分片 -索引生成 -raster 前置数据生成 -paint 所需全部输入生成 -``` - -`prepare` 最终必须只产生当前 Renderable 自己的: - -```text -prepare_buffer -``` - -### `paint` - -`paint` 必须满足: - -```text -禁止读取其他 Renderable -禁止解析 dependency -禁止查询其他 Renderable 当前状态 -禁止重新执行跨 Renderable 数据计算 -禁止临时从 Axis/Series/其他对象读取绘制输入 -``` - -`paint` 只能读取: - -```text -自身 prepare_buffer -自身 paint-only 配置 -自身 paint target -``` - -`paint` 只能写: - -```text -自身 paint_buffer -``` - -必须满足这个验证原则: - -> 将其他 Renderable 全部从 `paint` 的可访问环境中移除,只保留当前 Renderable 的 `prepare_buffer`,`paint` 仍必须能够完整正确执行。 - -### `composite` - -`composite` 必须: - -```text -只读取已经完成的 paint_buffer -按照 layer 关系完成图层组合 -不读取 Renderable 原始业务数据 -不执行 prepare 计算 -``` - ---- - -# 2. 建立强类型 `prepare_buffer` - -每一个需要 prepare 数据的 Renderable 必须拥有自己的强类型 Prepare Buffer。 - -禁止实现: - -```cpp -std::unordered_map -``` - -禁止通过通用字符串字段传递 Renderable 绘制输入。 - -例如: - -```text -Axis -└── axis_prepare_buffer - -Spectrum -└── spectrum_prepare_buffer - -Waterfall -└── waterfall_prepare_buffer - -Afterglow -└── afterglow_prepare_buffer -``` - -具体字段由各 Renderable 自己定义。 - -例如 Waterfall: - -```text -waterfall_prepare_buffer -├── transformed_data -├── visible_range -├── partition_description -├── chunk_metadata -├── raster_parameters -└── 其他 paint 必需数据 -``` - -Paint 不得绕过这些结构重新访问数据源。 - ---- - -# 3. 审计并拆除所有混合 Prepare/Paint 实现 - -逐个审计所有 Renderable。 - -重点处理: - -```text -Waterfall -Spectrum -Afterglow -``` - -同时扫描其他 Renderable 中: - -```text -paint() -build_paint_task_graph() -render() -raster() -``` - -内部是否仍包含: - -```text -数据变换 -跨 Renderable 查询 -坐标计算 -布局计算 -分片 -输入数据准备 -``` - -全部迁移到 Prepare。 - -原来的混合实现直接删除。 - -不得保留: - -```text -旧 paint path -+ -新 prepare path -``` - -两套兼容逻辑。 - -绘制结果必须保持一致。 - ---- - -# 4. Prepare Buffer 与 Paint Buffer 完全独立缓存 - -每个 Renderable 必须独立维护: - -```text -prepare_buffer validity - -paint_buffer validity -``` - -不得继续使用一个 Renderable 整体缓存状态同时代表两者。 - -缓存关系必须严格满足: - -```text -prepare invalid - ↓ -paint 必须 invalid -``` - -但: - -```text -paint invalid -``` - -不得无条件导致: - -```text -prepare invalid -``` - ---- - -# 5. 建立独立 Prepare/Paint Revision - -现有 revision/cache revision 体系必须拆到能够分别回答: - -```text -当前 prepare_buffer 是否仍有效 - -当前 paint_buffer 是否仍有效 -``` - -至少在语义上存在: - -```text -prepare input revision -prepare output revision - -paint input revision -paint output revision -``` - -具体字段名称保持现有项目命名风格。 - -### Prepare 有效性必须依赖 - -```text -自身数据 revision -依赖 Renderable 提供的数据 revision -会影响 prepare 的尺寸/范围/坐标参数 -prepare-only properties -``` - -### Paint 有效性必须依赖 - -```text -当前 prepare_buffer revision -paint-only properties -影响 raster/output 的尺寸和配置 -``` - -例如: - -```text -仅颜色变化 -``` - -必须能够得到: - -```text -prepare cache = valid -paint cache = invalid -``` - -例如: - -```text -依赖 Axis 范围变化 -``` - -必须得到: - -```text -prepare cache = invalid -paint cache = invalid -``` - ---- - -# 6. 修正 Dependency Invalidations - -跨 Renderable dependency 必须只描述 Prepare 数据依赖。 - -例如: - -```text -Series depends on Axis -``` - -必须编译成: - -```text -Axis Prepare - ↓ -Series Prepare -``` - -不得编译成: - -```text -Axis Paint - ↓ -Series Prepare -``` - -不得继续使用: - -```text -整个 Renderable A - ↓ -整个 Renderable B -``` - -这种粗粒度执行约束。 - -Prepare 数据变化向 dependency 后继传播: - -```text -A prepare invalid - ↓ -B prepare invalid - ↓ -B paint invalid -``` - -Paint-only 状态变化不得传播到其他 Renderable 的 Prepare: - -```text -A paint invalid -``` - -不得导致: - -```text -B prepare invalid -``` - ---- - -# 7. 建立 Renderable DAG Builder 接口 - -Renderable 必须正式提供建图能力。 - -保留运行时多态。 - -建立与现有类体系匹配的虚函数,语义必须等价于: - -```cpp -virtual void build_prepare_graph(render_graph_builder &builder); -virtual void build_paint_graph(render_graph_builder &builder); -``` - -两个函数必须写入同一个: - -```text -render_graph_builder -``` - -不得分别生成两张最终 Graph。 - -简单 Renderable: - -```text -Prepare - ↓ -Paint -``` - -复杂 Renderable 可以展开自己的内部 DAG。 - ---- - -# 8. Waterfall 必须展开真实内部 DAG - -Waterfall 分片必须全部成为正式 Node。 - -不得把分片隐藏为一个 Waterfall Task 内部的匿名并行执行。 - -例如: - -```text -Waterfall Prepare - │ - ├── Chunk 0 Prepare -> Chunk 0 Paint ─┐ - ├── Chunk 1 Prepare -> Chunk 1 Paint ─┤ - ├── Chunk 2 Prepare -> Chunk 2 Paint ─┤ - └── Chunk N Prepare -> Chunk N Paint ─┤ - ▼ - Merge -``` - -如果某些分片只需要单独的 Prepare 或单独 Paint,则按真实依赖建立节点。 - -不得为了统一结构制造不存在的任务。 - -动态 Chunk 必须拥有稳定逻辑 Node ID。 - ---- - -# 9. `prepare -> paint` 只能是局部依赖 - -禁止建立: - -```text -所有 Prepare 完成 - ↓ -所有 Paint 开始 -``` - -这种全局 Barrier。 - -必须形成流水式 DAG: - -```text -Prepare A -> Paint A - -Prepare B -------------> Paint B - -Prepare C -> Paint C -``` - -因此实际运行允许: - -```text -Prepare A 完成 - ↓ -Paint A 开始 -``` - -同时: - -```text -Prepare B -Prepare C -``` - -仍在执行。 - -这条必须通过并发测试明确验证。 - ---- - -# 10. Paint 必须最大程度并行 - -所有 Renderable 的 Paint 必须只写自己的独立: - -```text -paint_buffer -``` - -因此: - -```text -Axis Paint -Series Paint -Waterfall Paint -Legend Paint -``` - -在不存在真实 Paint 依赖的情况下必须允许完全并行。 - -不得直接将: - -```text -layer_node_ -``` - -转换为: - -```text -Paint A -> Paint B -``` - -从而人为串行化 Paint。 - ---- - -# 11. Layer 关系必须编译到 Composite - -图层顺序必须主要落实到 Composite DAG。 - -例如: - -```text -Background Paint -Series Paint -Axis Paint -``` - -可以并行。 - -最终: - -```text -Background Paint - ↓ -Composite Background - │ -Series Paint - └────> Composite Series - │ -Axis Paint - └────> Composite Axis -``` - -具体依赖按照现有 Layer Graph 的真实顺序生成。 - -必须保持最终像素结果与原实现一致。 - ---- - -# 12. 最终只有一张 Render DAG - -最终 Compiler 输入必须为: - -```text -Renderable internal graph -+ -dependency_node_ -+ -layer_node_ -+ -prepare_buffer validity -+ -paint_buffer validity -+ -Renderable 当前状态 -``` - -输出必须只有: - -```text -render_plan -└── graph -``` - -Graph 内统一存在: - -```text -prepare node -paint node -composite node -``` - -不得生成: - -```text -prepare_graph -paint_graph -``` - -两张最终执行图。 - ---- - -# 13. Buffer 必须在建图阶段裁剪任务 - -缓存命中的工作必须直接从本帧有效 DAG 中删除。 - -禁止继续生成: - -```text -cache_hit -``` - -空 Task。 - -完整路径: - -```text -Prepare - ↓ -Paint - ↓ -Composite -``` - -### Prepare Cache Hit - -本帧必须生成: - -```text -Paint - ↓ -Composite -``` - -Paint 直接读取已有 Prepare Buffer。 - -### Paint Cache Hit - -本帧必须生成: - -```text -Composite -``` - -Composite 直接读取已有 Paint Buffer。 - -### Prepare/Paint 均失效 - -生成: - -```text -Prepare - ↓ -Paint - ↓ -Composite -``` - ---- - -# 14. 建立稳定 `node_id` - -Kernel/Plot 必须统一分配 DAG Node 身份。 - -所有逻辑任务必须拥有: - -```text -node_id -``` - -包括: - -```text -Prepare -Paint -Composite -Waterfall dynamic chunks -内部 merge -内部 geometry task -``` - -规则严格保持: - -```text -逻辑任务身份不变 -=> node_id 不变 -``` - -```text -逻辑任务语义改变 -=> 分配新 node_id -``` - -```text -node 退休 -=> node_id 永不复用 -``` - ---- - -# 15. Node 必须带最小元数据 - -每个 Render Node 至少包含: - -```text -node_id -owner/renderable id -name -kind -execution_index -``` - -`kind` 至少有: - -```text -prepare -paint -composite -``` - -不提前添加无实际使用场景的分类。 - ---- - -# 16. 建立单一 `render_plan` - -建立: - -```text -render_plan -├── version -└── graph - ├── nodes - └── edges -``` - -`render_plan` 必须代表: - -> 当前 Plot 在当前 Renderable、Dependency、Layer、Prepare Cache、Paint Cache 状态下真正会执行的完整 Render DAG。 - ---- - -# 17. 建立 `render_plan_version` - -以下任一情况发生时必须产生新 Version: - -```text -active node set 改变 -Node 增加 -Node 删除 -Edge 改变 -Waterfall 分片拓扑变化 -dependency topology 变化 -layer/composite topology 变化 -prepare cache 裁剪结果变化 -paint cache 裁剪结果变化 -``` - -仅以下变化不得产生新 Version: - -```text -Task 实际耗时变化 -Task Worker 改变 -调度顺序不同 -实际并行程度不同 -``` - ---- - -# 18. Render Plan 编译成一个 Taskflow - -必须满足: - -```text -1 Render Node -= -1 Taskflow Task -``` - -以及: - -```text -1 Render Edge -= -1 Taskflow dependency -``` - -最终: - -```text -render_plan.graph - ↓ -Taskflow - ↓ -Taskflow Executor -``` - -不得生成两个前后 Taskflow。 - ---- - -# 19. Taskflow 只遵守偏序关系 - -DAG Edge 只表示: - -```text -B 不能在 A 完成以前执行 -``` - -没有 Edge 的 Node 必须交由 Taskflow 自由调度。 - -不得写: - -```text -固定 Worker -固定执行次序 -手工串行队列 -``` - -除非任务本身存在真实依赖。 - ---- - -# 20. 性能采集必须请求式开启 - -正常运行: - -```text -capture = disabled -``` - -不得常驻记录完整 Node 时序。 - -必须实现: - -```text -capture_next_frame() -``` - -以及: - -```text -capture_frames(count) -``` - -例如: - -```text -capture_frames(20) -``` - -必须从后续完整 Render Frame 开始连续捕获 20 帧,然后自动停止。 - ---- - -# 21. Capture Controller 必须保持极简 - -Plot/Kernel 内维护: - -```text -capture enabled -remaining frame count -capture session id -``` - -使用必要的原子状态实现。 - -不得增加: - -```text -Event system -Record system -MPSC performance queue -TLS trace system -collector thread -``` - ---- - -# 22. Frame 必须持有 Capture 状态 - -每个正在 Render 的 Frame 在开始执行时必须确定: - -```text -capture_this_frame -``` - -该状态在本 Frame 生命周期内保持不变。 - -不得执行到一半再打开 Capture。 - ---- - -# 23. Frame 性能数据使用预分配 List - -不得在 Task 热路径使用: - -```text -map -unordered_map -``` - -Render Plan 编译时给每个 Node 分配: - -```text -execution_index -``` - -例如: - -```text -Node #100 -> slot 0 -Node #101 -> slot 1 -Node #203 -> slot 2 -``` - -Capture Frame 创建: - -```text -node_execution[] -``` - -长度直接根据 Plan 确定。 - ---- - -# 24. `node_execution` 必须记录真实时序 - -至少记录: - -```text -node_id -start_time -end_time -worker_id -status -``` - -`duration` 不重复存储: - -```text -duration = end_time - start_time -``` - -时间源必须保持单调并能在 Worker 间比较。 - ---- - -# 25. Taskflow Worker 只能写自己的 Execution Slot - -编译 Taskflow 时将: - -```text -Task -``` - -直接绑定: - -```text -execution_index -``` - -Capture 开启: - -```text -execution.start = now -execution.worker = worker - -执行真实任务 - -execution.end = now -execution.status = complete -``` - -不同 Task 不得写同一个 slot。 - -热路径不得用 mutex 保护整个性能数据结构。 - ---- - -# 26. Capture 关闭时不得采集详细时间 - -Capture 关闭时 Task 必须直接进入正常执行路径。 - -不得仍然执行: - -```text -now() -start record -end record -statistics aggregation -``` - -只保留最小 capture branch。 - ---- - -# 27. Renderable 自定义指标直接写 Execution Slot - -Renderable 实现允许对自己当前 Node 补充固定性能指标。 - -例如 Waterfall Prepare: - -```text -input_count -chunk_size -prepared_cells -``` - -Paint: - -```text -pixel_count -primitive_count -``` - -不得在 Worker 热路径实现: - -```cpp -unordered_map -``` - -使用固定结构或固定 metric slot。 - ---- - -# 28. Frame Snapshot 必须绑定 `render_plan_version` - -Capture Frame 至少包含: - -```text -frame_id -render_plan_version -render_start -render_end -node_execution[] -``` - -不再创建: - -```text -Trace -Span -Record -Event -``` - -等额外运行层。 - -一帧自己的执行数据就是唯一运行快照。 - ---- - -# 29. 三缓冲交换必须成为 Snapshot 发布边界 - -运行阶段: - -```text -working frame - │ -Taskflow 写 execution slots - │ -render complete - │ -triple-buffer exchange - │ -completed frame -``` - -进入 Completed 后: - -```text -frame performance -``` - -必须不可再修改。 - -外部读取 Completed Frame 时不得需要锁住 Taskflow Worker。 - ---- - -# 30. 建立 Capture Repository - -三缓冲不负责保存历史性能帧。 - -Capture 请求的 Completed Frame 必须在冷路径复制/移动到: - -```text -capture_repository -``` - -结构: - -```text -capture_session -├── session_id -├── requested_count -├── captured_count -├── active -└── frame_snapshots[] -``` - -抓取达到请求数量以后必须自动结束 Session。 - ---- - -# 31. 保存 Render Plan 历史结构 - -必须能够: - -```text -render_plan_version - ↓ -找到当时对应的 Render DAG -``` - -连续 20 帧过程中允许: - -```text -Frame 100 -> Plan 30 -Frame 101 -> Plan 30 -Frame 102 -> Plan 31 -Frame 103 -> Plan 32 -``` - -每帧必须绑定自己真实执行的 Plan Version。 - -不得假定一个 Capture Session 只有一个 DAG Version。 - ---- - -# 32. 实现 `frame_analysis` - -所有重分析必须发生在 Render 热路径之外。 - -输入: - -```text -render_plan -+ -frame_snapshot -``` - -输出: - -```text -frame_analysis -``` - -至少计算: - -```text -total_render_duration -node_duration -node_start_offset -node_end_offset -dependency_ready_time -scheduler_wait -critical_path -critical_path_duration -critical_path_contribution -total_work_duration -peak_parallelism -average_parallelism -parallel_overlap -worker utilization -bottleneck nodes -``` - ---- - -# 33. Scheduler Wait 必须从 DAG 和实际时间推导 - -对于: - -```text -A ─┐ - ├──> C -B ─┘ -``` - -计算: - -```text -dependency_ready(C) -= -max(A.end, B.end) -``` - -然后: - -```text -scheduler_wait(C) -= -C.start - dependency_ready(C) -``` - -Source Node: - -```text -dependency_ready -= -render_start -``` - -不得为了获得 Wait 再增加事件采集系统。 - ---- - -# 34. 正确处理并行节点的耗时占比 - -不得简单计算: - -```text -node_duration / sum(all node durations) -``` - -作为“帧耗时占比”。 - -必须明确输出不同指标: - -```text -work_contribution -critical_path_contribution -``` - -并行节点允许 Work Duration 总和远大于 Wall Duration。 - ---- - -# 35. 实现 `node_statistics` - -按稳定: - -```text -node_id -``` - -聚合多帧数据。 - -至少维护: - -```text -execution_count -average -moving_average -p50 -p95 -p99 -min -max -critical_path_frequency -average_scheduler_wait -``` - -短生命周期 Waterfall Node 同样统计。 - ---- - -# 36. 支持按 `render_plan_version` 聚合 - -必须支持: - -```text -Plan v30 -├── frame... -└── statistics - -Plan v31 -├── frame... -└── statistics -``` - -用于直接比较 DAG 编译策略变化后的性能。 - -例如: - -```text -Plan v30 P95 render = 8.4 ms -Plan v31 P95 render = 6.1 ms -``` - ---- - -# 37. 后端增加 Capture API - -按照当前后端/Adminive API 风格接入。 - -必须提供等价能力: - -```text -请求下一帧 -请求连续 N 帧 -查看 capture 状态 -查看 capture session -查看 captured frame 列表 -读取单帧 snapshot -读取单帧 analysis -读取 render plan topology -读取 node statistics -读取 plan version statistics -``` - -禁止为了这些 API 重新实时读取 Worker 数据。 - -接口只读取: - -```text -completed snapshots -analysis -statistics -``` - ---- - -# 38. 前端增加 Performance Capture 页面 - -前端必须提供: - -```text -Capture next frame - -Capture N frames -``` - -默认 N 可输入: - -```text -20 -``` - -Capture 时显示: - -```text -captured 7 / 20 -``` - -完成后显示捕获到的 Frame 列表。 - ---- - -# 39. Frame 列表必须显示 Version - -例如: - -```text -Frame #10381 Plan v57 6.81 ms -Frame #10382 Plan v57 7.02 ms -Frame #10383 Plan v58 5.93 ms -``` - -点击 Frame 后必须加载: - -```text -frame_snapshot -+ -对应 render_plan_version -+ -frame_analysis -``` - ---- - -# 40. 前端主视图必须是一张完整 Render DAG - -不得拆成: - -```text -Prepare DAG -Paint DAG -``` - -两个主图。 - -必须显示完整: - -```text -Prepare - ↓ -Paint - ↓ -Composite -``` - -以及跨 Renderable 数据依赖。 - -例如: - -```text -Axis Prepare ────────────────┐ - │ │ - ▼ ▼ -Axis Paint Series Prepare - │ │ - │ ▼ - │ Series Paint - │ │ - │ ▼ - │ Composite Series - │ │ - └──────────────────────┼──> Composite Axis -``` - -Waterfall 内部 Chunk 必须可以展开。 - ---- - -# 41. 前端 DAG Node 必须按 `kind` 区分 - -至少区分: - -```text -prepare -paint -composite -``` - -节点上直接显示: - -```text -当前 duration -scheduler_wait -worker -critical contribution -historical p95 -``` - -不得只有一个模糊的百分比字段。 - ---- - -# 42. 前端必须显示 Prepare/Paint Cache 独立状态 - -Renderable Detail 必须显示: - -```text -prepare cache: HIT/MISS -paint cache: HIT/MISS -``` - -例如: - -```text -Spectrum - -prepare cache: HIT -paint cache: MISS -``` - -用户必须能够直接理解为什么本 Frame DAG 中: - -```text -Spectrum Prepare -``` - -不存在,而: - -```text -Spectrum Paint -``` - -存在。 - ---- - -# 43. 前端必须实现真实 Worker Timeline - -同一个 Frame 必须能够按真实时间显示: - -```text -time ─────────────────────────────────────────> - -Worker 0 -[Axis Prepare][Axis Paint ] - -Worker 1 -[Series Prepare ][Series Paint] - -Worker 2 -[WF Prepare][Chunk0 Prep][Chunk0 Paint] - -Worker 3 - [Chunk1 Prep][Chunk1 Paint] - -Worker 4 - [Composite] -``` - -这张 Timeline 使用: - -```text -start_time -end_time -worker_id -``` - -直接生成。 - ---- - -# 44. DAG 与 Timeline 必须双向联动 - -点击 DAG Node: - -```text -Chunk 7 Paint -``` - -必须在 Timeline 高亮它的真实执行区间。 - -点击 Timeline 区间: - -```text -Worker 3 / 2.3ms ~ 3.7ms -``` - -必须高亮对应 DAG Node。 - ---- - -# 45. 前端 Node Detail 必须展示当前与历史对比 - -例如: - -```text -Waterfall / Chunk 7 / Paint - -current duration 1.42 ms -scheduler wait 0.18 ms -worker 3 - -moving average 1.13 ms -p95 1.67 ms -p99 2.10 ms - -critical contribution 12.4% -critical path frequency 14 / 20 -``` - -Renderable 自定义指标同时显示。 - ---- - -# 46. 连续 N 帧必须提供统计视图 - -Capture 20 帧以后必须提供: - -```text -total render -avg -p50 -p95 -max - -parallelism -average -peak - -scheduler wait -average -p95 - -critical path -node frequency -``` - -不得只提供 20 个单帧链接。 - ---- - -# 47. 不同 Plan Version 必须支持直接比较 - -如果 Capture 中存在: - -```text -Plan v57 -Plan v58 -``` - -必须能够比较: - -```text -frame count -render avg -render p95 -peak parallelism -average parallelism -scheduler wait -critical path nodes -``` - -并展示拓扑变化: - -```text -新增 node -删除 node -新增 edge -删除 edge -缓存裁剪变化 -``` - ---- - -# 48. 测试执行顺序 - -所有阶段必须遵守: - -```text -先补测试 -↓ -确认测试失败 -↓ -修改实现 -↓ -相关测试通过 -↓ -全量测试通过 -↓ -再进入下一阶段 -``` - -不得先整体改完再补测试。 - ---- - -# 49. 必须增加的核心测试 - -覆盖: - -```text -prepare 禁止依赖 paint 结果 - -paint 不访问其他 Renderable - -prepare_buffer 独立有效 - -paint_buffer 独立有效 - -prepare invalid -> paint invalid - -paint invalid 不反向 invalid prepare - -dependency 只约束 prepare - -prepare 完成后对应 paint 可立即执行 - -不存在全局 prepare barrier - -无依赖 Renderable prepare 真并行 - -独立 paint_buffer 的 paint 真并行 - -layer 顺序只正确约束 composite - -cache hit 节点真正不进入 DAG - -node_id 跨 plan version 稳定 - -retired node_id 不复用 - -Waterfall 动态分片 node 正确 - -render_plan_version 正确变化 - -一张 DAG 正确编译一个 Taskflow - -Capture off 不生成 execution timing - -Capture next frame 只抓一帧 - -Capture 20 frames 正好抓 20 帧 - -多 worker 写不同 execution slot 无竞争 - -Frame A/B 不串 performance 数据 - -三缓冲交换以后 snapshot 不再变化 - -Plan version 与 Frame 正确绑定 - -scheduler_wait 推导正确 - -critical path 正确 - -并行时间重叠计算正确 - -前端 API 返回 Plan + Frame 完整数据 -``` - ---- - -# 50. 并发与 Sanitizer 验证 - -必须执行: - -```text -高并发 Taskflow 测试 -Waterfall 大量动态 Chunk -持续 Render -Capture 连续多帧 -Capture 开关反复操作 -Plan 高频变化 -缓存高频命中/失效 -``` - -并运行项目当前环境可用的: - -```text -ASan -UBSan -TSan -``` - -TSan 重点检查: - -```text -Frame execution slots -capture controller -triple-buffer publish -capture repository -plan history -``` - ---- - -# 51. 性能回归验证 - -必须单独比较: - -```text -Capture OFF -``` - -情况下改造前后的 Render 性能。 - -Capture OFF 不得因为性能分析系统引入明显: - -```text -锁竞争 -动态内存分配 -hash lookup -时间采样 -队列 push -observer 聚合 -``` - -Capture ON 的开销单独测量。 - ---- - -# 52. 清理旧性能统计路径 - -当 Frame Capture + `node_statistics` 完成以后,审计现有 Renderable Task Observer / Task Execution Snapshot / Rolling -Statistics 等机制。 - -如果职责已经完全被新结构替换: - -```text -直接删除旧实现 -``` - -不得保留双统计路径。 - -仅保留仍有独立语义、没有被新系统替代的统计能力。 - ---- - -# 53. 最终代码结构必须满足 - -```text -Plot -│ -├── Renderable graph relationships -│ -├── render_plan compiler -│ └── ONE Render DAG -│ -├── Taskflow executor -│ -├── frame buffers -│ ├── prepare_buffer state -│ ├── paint_buffer state -│ └── optional performance snapshot -│ -├── capture controller -│ -├── capture repository -│ -├── frame_analysis -│ -└── node_statistics -``` - -前端: - -```text -Performance -│ -├── Capture Control -├── Captured Frames -├── Render DAG -├── Worker Timeline -├── Node Detail -├── Multi-frame Statistics -└── Plan Version Comparison -``` - ---- - -# 54. 最终不可破坏的设计规则 - -这部分直接放到 Codex 任务最顶部: - -> **所有跨 Renderable 数据访问必须在 `prepare` 完成。** -> -> **`paint` 禁止访问其他 Renderable,只能消费自身 `prepare_buffer`。** -> -> **`prepare_buffer` 与 `paint_buffer` 必须是完全独立的两层缓存。** -> -> **`prepare` 缓存失效必须使 `paint` 缓存失效;`paint` 缓存失效不得反向污染 `prepare`。** -> -> **Prepare、Paint、Composite 最终必须构成同一张 Render DAG。** -> -> **禁止建立全局 Prepare→Paint Barrier。** -> -> **某个 Prepare 完成后,只要其真实依赖已经满足,对应 Paint 必须立即允许进入 Taskflow 调度。** -> -> **独立 `paint_buffer` 的 Paint 必须尽可能并行,Layer 顺序落实到 Composite。** -> -> **缓存命中的工作必须在 Render DAG 构建阶段直接裁剪。** -> -> **Kernel Render DAG 是执行、Taskflow 编译和性能分析的唯一拓扑事实来源。** -> -> **性能时序完全绑定 Frame,不建立 Trace/Event/Record/MPSC 性能事件体系。** -> -> **Capture 必须请求式开启,支持下一帧和连续 N 帧。** -> -> **Capture 开启时 Taskflow Task 直接写 Frame 预分配 Execution Slot。** -> -> **三缓冲交换完成后 Frame Snapshot 必须不可变。** -> -> **性能分析必须在完成帧冷路径执行。** -> -> **前端必须同时展示 Render DAG 偏序关系和本 Frame 的真实 Worker 时序。** -> -> **不得触碰 git。** -> -> **所有代码保持 K&R 风格,不增加无意义空行。** -> -> **被替换的旧实现直接删除,不做兼容实现。** - -执行完成后的最终数据流必须严格为: - -```text -Renderable / Dependency / Layer / Cache - │ - ▼ - render_plan compiler - │ - ▼ - ONE Render DAG - │ - ▼ - Taskflow - │ - ┌──────┴──────┐ - │ │ - Capture OFF Capture ON - │ │ - 正常执行 Frame slots - │ - ▼ - completed Frame - │ - ▼ - triple-buffer publish - │ - ▼ - immutable snapshot - │ - ┌──────────┴──────────┐ - ▼ ▼ - frame_analysis node_statistics - │ │ - └──────────┬──────────┘ - ▼ - Backend API - │ - ▼ - DAG + Worker Timeline - + Multi-frame Analysis - + Plan Version Compare -``` - -这份计划直接从 Renderable 边界改造一直执行到最终前端性能分析页面。 diff --git a/renderive_package.zip b/renderive_package.zip deleted file mode 100644 index 585d71c..0000000 Binary files a/renderive_package.zip and /dev/null differ diff --git a/web_server/CMakeLists.txt b/web_server/CMakeLists.txt index 2802de3..243de3f 100644 --- a/web_server/CMakeLists.txt +++ b/web_server/CMakeLists.txt @@ -23,11 +23,14 @@ if (WIN32 AND DEFINED ENV{APPDATA}) endif () find_program(Renderive_Web_node_executable NAMES node node.exe HINTS ${Renderive_Web_node_search_paths} REQUIRED) +get_filename_component(Renderive_Web_node_dir "${Renderive_Web_node_executable}" DIRECTORY) if (WIN32) - find_program(Renderive_Web_npm_executable NAMES npm.cmd - HINTS ${Renderive_Web_node_search_paths} REQUIRED) + set(Renderive_Web_npm_executable "${Renderive_Web_node_dir}/npm.cmd") else () - find_program(Renderive_Web_npm_executable NAMES npm REQUIRED) + set(Renderive_Web_npm_executable "${Renderive_Web_node_dir}/npm") +endif () +if (NOT EXISTS "${Renderive_Web_npm_executable}") + message(FATAL_ERROR "npm was not found next to Node.js: ${Renderive_Web_node_dir}") endif () set(Renderive_Web_frontend_dir "${CMAKE_CURRENT_LIST_DIR}/../webapp_gallery") set(Renderive_Web_frontend_install_stamp "${CMAKE_CURRENT_BINARY_DIR}/webapp_gallery_npm_ci.stamp") @@ -43,9 +46,16 @@ set(Renderive_Web_frontend_configuration "${Renderive_Web_frontend_dir}/tsconfig.app.json" "${Renderive_Web_frontend_dir}/index.html" ) +if (WIN32) + set(Renderive_Web_node_path "${Renderive_Web_node_dir};$ENV{PATH}") +else () + set(Renderive_Web_node_path "${Renderive_Web_node_dir}:$ENV{PATH}") +endif () add_custom_command( OUTPUT "${Renderive_Web_frontend_install_stamp}" - COMMAND "${Renderive_Web_npm_executable}" ci + COMMAND "${CMAKE_COMMAND}" -E env + "PATH=${Renderive_Web_node_path}" + "${Renderive_Web_npm_executable}" ci COMMAND "${CMAKE_COMMAND}" -E touch "${Renderive_Web_frontend_install_stamp}" DEPENDS "${Renderive_Web_frontend_dir}/package.json" @@ -56,7 +66,9 @@ add_custom_command( ) add_custom_command( OUTPUT "${Renderive_Web_frontend_build_stamp}" - COMMAND "${Renderive_Web_npm_executable}" run build + COMMAND "${CMAKE_COMMAND}" -E env + "PATH=${Renderive_Web_node_path}" + "${Renderive_Web_npm_executable}" run build COMMAND "${CMAKE_COMMAND}" -E touch "${Renderive_Web_frontend_build_stamp}" DEPENDS "${Renderive_Web_frontend_install_stamp}" ${Renderive_Web_frontend_configuration} @@ -124,7 +136,7 @@ append_glob_source(Renderive_Web_Server_sources "${Renderive_Web_Server_source_d add_executable(Renderive_Web_Server ${Renderive_Web_Server_sources}) target_compile_features(Renderive_Web_Server PRIVATE cxx_std_20) target_link_libraries(Renderive_Web_Server PRIVATE Renderive_Web) -add_dependencies(Renderive_Web_Server Renderive_Web_Assets) +#add_dependencies(Renderive_Web_Server Renderive_Web_Assets) if (MSVC) target_compile_options(Renderive_Web PRIVATE /utf-8) target_compile_options(Renderive_Web_Server PRIVATE /utf-8) @@ -146,4 +158,4 @@ if (RENDERIVE_BUILD_TESTS) target_link_libraries("${Renderive_Web_test_target}" PRIVATE Renderive_Web Adminive::Nlohmann GTest::gtest_main) add_test(NAME "${Renderive_Web_test_target}" COMMAND "${Renderive_Web_test_target}") endforeach () -endif () +endif () \ No newline at end of file diff --git a/webapp_gallery/package-lock.json b/webapp_gallery/package-lock.json index 1cdfc7c..f3e7259 100644 --- a/webapp_gallery/package-lock.json +++ b/webapp_gallery/package-lock.json @@ -4117,22 +4117,6 @@ "dev": true, "license": "ISC" }, - "node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", - "extraneous": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/zustand": { "version": "4.5.7", "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz",