图形学图像处理【免费下载链接】skiaSkia is a complete 2D graphic library for drawing Text, Geometries, and Images.项目地址https://gitcode.com/gh_mirrors/skia1/skia点击查看免费下载Skia 的正确性测试Correctness Testing主要由一个名为DM的工具承担。本文基于 site/docs/dev/testing/testing.md 展开带你从零构建并运行 DM逐行解读其任务输出与结果目录掌握--src、--config、--match、--dryRun等核心参数并学会用-r与 skdiff 对比历史结果、定位渲染回归。读完本文你将具备用 DM 对 Skia 软件光栅化与 GPU 后端进行正确性验证的完整实战能力。一、DM 是什么Skia 正确性测试的核心工具DMDawn/Draw Manager主程序位于 dm/DM.cpp是 Skia 仓库中面向正确性验证的测试驱动程序。它的工作模型可以概括为把一组绘图源src分别绘制到一组渲染配置sink中并对每次绘制的原始像素计算 MD5 校验和从而验证 CPU 软件后端与 GPU 后端Ganesh/Graphite在不同配置下是否都能正确渲染。从 dm/DM.cpp 的main流程可以看到 DM 的启动顺序gather_srcs()收集所有绘图源GM、SKP、图片、Lottie、SVG 等gather_sinks()根据--config解析并创建渲染后端每个新 sink 还会先跑一个justOneRect的金丝雀绘制来验证其可用性gather_tests()收集单元测试打印任务总览并调度执行。二、快速上手四条命令构建并运行 DMDM 的构建与运行非常简单官方 quickstart 只有四条命令python3 tools/git-sync-deps bin/gn gen out/Debug ninja -C out/Debug dm out/Debug/dm -v -w dm_output各步骤的作用如下python3 tools/git-sync-deps运行仓库根目录下的依赖同步脚本 tools/git-sync-deps按照 DEPS 文件把构建所需的第三方依赖如字体、编解码器源码同步到本地。首次构建前必须执行。bin/gn gen out/Debug使用 GN 生成构建目录out/Debug的构建配置。ninja -C out/Debug dm编译出 DM 可执行文件。out/Debug/dm -v -w dm_output以 verbose 模式运行 DM并把渲染结果写入dm_output目录。其中-v是--verbose的简写见 dm/DM.cpp-w是--writePath的简写指定图像输出目录见 dm/DM.cpp。运行时会看到 CPU 占用率短暂冲到 100%随后回落到 12 个活跃核心直至结束。这是有意为之DM 高度多线程但部分工作尤其是 GPU 后端相关任务仍被迫在单线程上执行。如果机器内存相对 CPU 核数偏少可以用--threads N把并发线程数限制为 N。从源码看dm/DM.cpp 中--threads简写-j的默认行为是每个 CPU 核心额外启动一个线程即并发任务数约等于硬件线程数dm/DM.cpp 通过SkTaskGroup::Enabler enabled(FLAGS_threads)把它接入 Skia 的任务调度系统。三、运行输出解读3.1 启动期的 Skipping 信息不必恐慌DM 启动时通常会打出一批形如下面的提示Skipping nonrendering: Dont understand nonrendering. Skipping angle: Dont understand angle. Skipping nvprmsaa4: Could not create a surface.这些行不是错误。DM 支持非常多的测试配置但并非所有配置都适合当前机器取决于编译选项、驱动能力、显存等。这些提示本质是告知某个你可能期望运行的配置没能启用。以nvprmsaa4: Could not create a surface为例dm/DM.cpp 的push_sink()会先用一个 16×16 的justOneRect金丝雀绘制对每个 sink 做冒烟测试若返回致命错误就跳过该 sink 并打印原因GPU sink 在 dm/DMSrcSink.cpp 中还会检查源尺寸是否超过maxTextureSize()超出则返回Result::Skip无法创建 surface 则返回 Fatal。所以Could not create a surface往往意味着当前环境无法为那个配置创建 GPU 上下文或目标表面。同理日志中的skps: Couldnt read skps.也无需担心——默认情况下你不会遇到它因为默认的skps目录需要额外下载 .skp 文件。如果想测试 .skp 回放需要单独下载这些文件放到skps/目录。3.2 任务总览行492 srcs * 3 sinks 382 tests 1858 tasks接下来这一行是 DM 即将执行的全部工作量概览492 srcs * 3 sinks 382 tests 1858 tasks对应源码在 dm/DM.cppgSrcs-size() * gSinks-size() testCount。它揭示了两类任务1. src绘图源共 492 个来源由--src控制GM 集成测试从 gm/ 目录链接进来的绘图测试每个 GM 是一个独立的绘制场景如aaclip、blurcircles、gradients等图片文件来自--images指定的路径默认是resources资源目录会针对每张图片生成多种解码方式、缩放、子集等变体.skp 文件来自--skps指定的目录默认是skps。注意当前仓库中--src的实际默认值比文档示例更丰富。查看 dm/DM.cpp 的源码定义static DEFINE_string(src, tests gm skp mskp lottie rive svg image colorImage, Source types to test.);即默认启用tests、gm、skp、mskp、lottie、rive、svg、image、colorImage九类源gather_srcs()dm/DM.cpp会按此逐一收集GM 来自skiagm::GMRegistrySKP/MSKP 来自对应目录Lottie 需要SK_ENABLE_SKOTTIE编译开关SVG 需要SK_ENABLE_SVG图片与彩色图片则走 codec 解码路径。2. sink渲染配置共 3 个由--config控制。默认配置随操作系统而变在 Linux 上是8888 gl nonrendering。上例中nonrendering被跳过剩余两个可用配置8888使用软件后端绘制到 32 位 RGBA 位图对应源码 dm/DMSrcSink.cpp 中的SINK(8888, RasterSink, kN32_SkColorType)gl使用 OpenGL 后端Ganesh同样输出到 32 位 RGBA 位图。DM 文档里偶尔把 config 称作 sink两者是同一概念。虽然 config 种类很多但日常最值得关注的就是8888和gl——它们分别覆盖 CPU 与 GPU 两条渲染路径。DM 总是尝试把所有 src 绘制进所有 sink所以总任务数是 492 × 3单元测试不适用这个 src×sink 模型所以单独相加。最终一两千个任务是完全正常的规模。3.3 状态行一条任务输出包含四个信息( 25MB 1857) 1.36ms 8888 image mandrill_132x132_12x12.astc-5-subsets [1] [2] [3] [4]逐段解读25MBDM 到目前为止使用过的最大内存峰值high water mark不是当前内存用量。这个值对 buildbot 监控尤其重要——部分构建机器运行在接近系统内存上限的临界状态。1857尚未完成的任务数正在运行 排队等待。DM 通常每个硬件线程跑一个任务普通笔记本上大概同时有 48 个在跑。启动初期偶尔出现计数乱序是正常现象不影响运行正确性。1.36ms该任务耗时。计时精度约 1 微秒纯粹是信息性展示主要用来帮助定位慢测试。8888 image mandrill_132x132_12x12.astc-5-subsets本次任务的配置与名称——把名为mandrill_132x132_12x12.astc-5-subsets的image源绘制进了8888sink。如果觉得逐行刷新太吵把-v去掉即可DM 会在单行内滚动更新进度。四、输出目录与 dm.json运行结束后dm_output目录下会有dm.json和若干嵌套的图像目录$ ls dm_output 8888 dm.json gl $ find dm_output -name *.png dm_output/8888/gm/3x3bitmaprect.png dm_output/8888/gm/aaclip.png dm_output/8888/gm/aarectmodes.png dm_output/8888/gm/alphagradients.png dm_output/8888/gm/arcofzorro.png ...目录结构先按 sink 类型--config再按源类型--src嵌套。之前那个任务8888 image mandrill_132x132_12x12.astc-5-subsets对应的图像就位于dm_output/8888/image/mandrill_132x132_12x12.astc-5-subsets.pngdm.json供自动化测试系统使用人工可忽略。它记录了每个测试任务的运行情况以及该任务生成图像的校验和。写入逻辑见 dm/DMJsonWriter.cpp字段定义见 dm/DMJsonWriter.h其中md5字段固定为 32 字节十六进制 ASCII 字符串。细节校验和的对象是原始像素一个值得注意的技术细节原文称为 digests校验和不是对 .png 文件本身计算而是对生成该 .png 的原始像素raw pixels计算 MD5。源码佐证在 dm/DM.cpp当位图没有对应的流式数据时DM 用HashAndEncode把位图逐像素喂给SkMD5最终得到hash.finish().toLowercaseHexString()。这意味着一个推论两个不同配置可能生成完全相同的 .png但它们的校验和却不同。例如软件与 GPU 后端对同一像素数据做 PNG 编码时编码参数或元数据差异不影响像素校验和而反过来像素级差异哪怕 PNG 文件因压缩巧合相同也一定会被校验和捕捉。理解这一点对解读 GoldSkia 的图像比较服务的比对结果很有帮助。单元测试通过时通常只输出一条状态更新一旦失败DM 会在失败发生时打印断言失败详情并在全部任务结束后再次汇总输出同时把这些失败记录进dm.json。五、与历史结果对比-r与 skdiff5.1 简单对比-rreadPathDM 内置了一个简单的回归对比机制ninja -C out/Debug dm out/Debug/dm -w good # 做一些改动比如改了渲染代码 ninja -C out/Debug dm out/Debug/dm -r good -w bad-r即--readPathdm/DM.cppDM 会把每次渲染的 MD5 与good目录中记录的校验和做比对。在 dm/DM.cpp 中凡是gGold里找不到当前 MD5 的任务都会被fail()标记——也就是任何没有复现good运行结果的测试都会报失败。由于比对的是原始像素 MD5只要渲染结果有像素级差异就会被发现。5.2 更精细的对比skdiff需要更细致的差异分析时官方推荐使用skdiff工具构建目标定义在 tools/skdiff/BUILD.bazelninja -C out/Debug dm out/Debug/dm -w good # 做一些改动 ninja -C out/Debug dm out/Debug/dm -w bad ninja -C out/Debug skdiff mkdir diff out/Debug/skdiff good bad diff # 用浏览器打开 diff/index.htmlskdiff 会逐像素对比good与bad两个输出目录生成差异图与统计并输出一个可交互的index.html——在浏览器中打开即可直观地按 GM、config、区域浏览差异远比逐条核对 MD5 高效适合定位是哪次改动引入了哪张图的变化。六、常用调试 Flags 速查DM 支持的参数远不止上面这些。以下是文档给出的高频用法并结合 dm/DM.cpp 源码补充了完整语义out/Debug/dm --help # 打印全部 flags、默认值及简要说明 out/Debug/dm --src tests # 只跑单元测试 out/Debug/dm --nocpu # 只测 GPU 后端工作 out/Debug/dm --nogpu # 只测 CPU 后端工作 out/Debug/dm --match blur # 只跑名称含 blur 的任务 out/Debug/dm --dryRun # 不真正执行只打印将要执行的任务--src tests对应源码 dm/DM.cpp。只跑单元测试时gather_sinks()甚至会直接跳过 sink 的收集dm/DM.cpp因为此时不需要绘图配置。--nocpu/--nogpu对应 dm/DM.cpp 中的cpu、gpu、graphite三个布尔开关默认都为 true用于分别压测 CPU 光栅化、Ganesh GPU 后端与 Graphite 后端。--match简写-m匹配语法比想象中灵活见 dm/DM.cpp[~]前缀表示取反即匹配该子串的任务跳过[^]要求名称以该子串开头[$]要求以该子串结尾^与$同时出现即精确匹配支持空格分隔的多个匹配项任务名只要不匹配任何列表项就会被跳过除非某个列表项以~开头。--dryRun见 dm/DM.cpp只打印本应执行的任务列表而不实际运行适合先确认任务规模与匹配范围。此外从源码中还能发现几个在调试 CI 与大型任务集时很实用的参数Flag源码位置说明--threads/-j Ndm/DM.cpp限制线程池并发数默认每核一个额外线程--shards N/--shard idm/DM.cpp把源数据切分为 N 片、只跑第 i 片用于分布式分片执行--skipdm/DM.cpp按config/src/srcOptions/name四元组跳过指定任务_通配任意、~取反--bisectdm/DM.cpp对 SKP 的路径做二分定位辅助还原 path 绘制 bug 的最小复现-q/-Vdm/DM.cpp / dm/DM.cpp静默模式 / 让单个测试输出更详细日志--nameByHashdm/DM.cpp输出文件按hash.png命名而非按 config/源类型/名称分层七、深入DM 的任务调度与校验机制作为收尾从源码视角串一下 DM 的完整执行链路便于你后续按需扩展收集阶段gather_srcs()dm/DM.cpp从 GM 注册表、SKP/MSKP/Lottie/SVG 目录与--images/--colorImages中建好全部 Srcgather_sinks()dm/DM.cpp解析--config并逐个create_sink每个 sink 先跑金丝雀测试gather_tests()dm/DM.cpp收集单元测试。任务计数gPending gSrcs-size() * gSinks-size() testCount即我们看到的srcs * sinks tests tasks总览行。调度执行所有 CPU 串行测试先执行以避免竞态其余任务投入SkTaskGroup并行池标记为串行的 src/sink 任务则进入串行队列dm/DM.cpp。校验与落盘GPU sink 在绘制后调用flushAndSubmit并readBack读回像素dm/DMSrcSink.cpp所有任务的结果像素经SkMD5计算校验和写入dm.json当指定--readPath时还会与历史校验和比对并标记回归。这套源 × 配置 单元测试 像素 MD5的模型让 DM 既能覆盖海量的绘制场景组合又能以极低的存储成本每个任务只需 32 字节 MD5支撑跨机器、跨时间点的自动化回归检测——这正是 Skia 持续集成中正确性把关的基础设施。赞分享图形学图像处理【免费下载链接】skiaSkia is a complete 2D graphic library for drawing Text, Geometries, and Images.项目地址https://gitcode.com/gh_mirrors/skia1/skia点击查看免费下载相关推荐Skia 正确性测试工具 DM 完整指南从构建、运行到回归比对Skia 正确性测试工具 DM 完整指南从构建、运行到回归比对 Skia 的官方文档 Correctness Testing https://link.git图形学Skia dm 工具使用指南GMs 图形测试与单元测试的正确性验证实战Skia dm 工具使用指南GMs 图形测试与单元测试的正确性验证实战 dm 是 Skia 主要的 正确性correctness测试工具 负责运行 GM图形学miniblink49 内置 Skia 的图形正确性测试DM 工具从构建到黄金图对比实战指南miniblink49 内置 Skia 的图形正确性测试DM 工具从构建到黄金图对比实战指南 miniblink49 作为基于 Blink 的轻量级浏览器内核前端桌面应用上一篇Twilio Video React App5分钟构建企业级视频会议系统的完整指南下一篇开源项目 Grapefruit 使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
51c大模型~合集140:EfficientVLA免训练推理加速实战,TaoToken统一Key接入配置指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 2:03:42
使用codex++时遇到skills无法导入的问题:从config.toml到SKILL.md的排查与修复 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 2:03:42
商城积分系统设计:从数据模型到高并发扣减的避坑指南 简介:商城积分系统的完整项目源码包,面向需要完成课程设计、毕业设计或商城类项目二次开发的 ASP.NET(C#)学习者,解决会员积分获取、兑换与后台管理的一体化实现问题。资源覆盖购物消费积分、注册奖励、生日福利等规则… · 2026/9/26 2:03:35
DBeaver数据库转储备份迁移实战:跨平台异构库安全迁移指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 2:36:49
Cursor生成UI后加一步:用TaoToken统一Key打通v0 API与React组件 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 2:36:49
网络药理学+机器学习+分子对接与动力学:复方干预血吸虫病研究全流程 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 2:36:49
LLMs 中的提示缓存:直觉、配置与验证 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 2:36:42
HPE与Juniper联手:面向大规模AI架构的新一代路由器解析 最近AI基础设施圈子里最热的消息,莫过于HPE把Juniper网络业务真正纳入自家AI解决方案版图之后,放出的那批面向大规模AI架构的新路由器。很多朋友看到"HPE推出Juniper路由器"这个新闻时有点懵:HPE不是做服务器的吗?Junip… · 2026/9/26 2:36:36
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46