Skia 正确性测试实战:构建、运行与解读 DM 测试工具
图形学图像处理【免费下载链接】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),仅供参考

相关新闻

51c大模型~合集140:EfficientVLA免训练推理加速实战,TaoToken统一Key接入配置指南

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/30 13:21:51 阅读更多 →
openapi-react-query 的 useInfiniteQuery 实战指南:基于 OpenAPI 的无限分页查询

openapi-react-query 的 useInfiniteQuery 实战指南:基于 OpenAPI 的无限分页查询

开发工具代码生成后端 【免费下载链接】openapi-typescript Generate TypeScript types from OpenAPI 3 specs 项目地址: https://gitcode.com/gh_mirrors/op/openapi-typescript 点击查看 免费下载 导读 useInfiniteQuery 是 openapi-react-query 在 tanstack/re…

2026/9/27 12:05:52 阅读更多 →
TypeScript 原始类型完全指南:typescript-book 中的 7 种内置基元与实战要点

TypeScript 原始类型完全指南:typescript-book 中的 7 种内置基元与实战要点

文档教程 【免费下载链接】typescript-book The Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source. 项目地址: https://gitcode.com/gh_mirrors/typ/typescript-book 点击查看 免费下载 导读 本文基于开源…

2026/9/27 12:06:00 阅读更多 →

最新新闻

开题报告别再只问“哪个网站第一”了:智能材料与结构同学的分环节工具清单 [特殊字符]

开题报告别再只问“哪个网站第一”了:智能材料与结构同学的分环节工具清单 [特殊字符]

如果你读的是工学 / 材料类 / 智能材料与结构,大概率会遇到一种很典型的“开题焦虑”: 题目看起来又酷又前沿,比如**“基于压电传感器阵列的纤维增强复合材料冲击定位与损伤识别”**,但真到写开题报告时,问题一下子全冒…

2026/9/30 13:20:44 阅读更多 →
Linux下ORCA与xtb联用安装配置与构象筛选实践

Linux下ORCA与xtb联用安装配置与构象筛选实践

标题里的"OCRA"是个常见的笔误,圈内都写作 ORCA——量子化学里那套 ADF 之外最常被计算化学工作者搬上集群的从头算/DFT 程序。而 xtb 是另一条线上的东西:GFN 系列半经验紧束缚方法,速度比 DFT 快两三个数量级。这两个程序单拎出来…

2026/9/30 13:20:44 阅读更多 →
资源加载与缓存机制全解析:从HTTP强缓存到Service Worker实践

资源加载与缓存机制全解析:从HTTP强缓存到Service Worker实践

页面卡在白屏不动,打开控制台一看,一堆资源在排队下载,接口响应挺快,但页面就是迟迟不渲染。这种问题排查到最后,几乎都会落到两个词上:资源加载和缓存机制。尤其是系统性的前端项目或大型 Web 应用,资源加载管的是“东西怎么运过来”,缓存管的是“东西到了之后怎么存、怎么复用…

2026/9/30 13:20:44 阅读更多 →
2026深圳靠谱的高端定制网站建设公司哪家好?十大设计、开发、口碑兼优建站服务商推荐榜发布及选型避坑指南

2026深圳靠谱的高端定制网站建设公司哪家好?十大设计、开发、口碑兼优建站服务商推荐榜发布及选型避坑指南

一、2026年深圳网站建设市场现状:官网的价值定位正在被重写 2026 年,企业官网已经彻底突破"线上名片"的传统定位,进化为承载品牌信任塑造、智能流量承接、商务线索沉淀与全域市场拓展的核心数字化经营载体。据行业数据机构发布的年…

2026/9/30 13:20:44 阅读更多 →
PHP + Apache2 一键容器化:基于 Docker Compose 的 apache-php 示例完整实战指南

PHP + Apache2 一键容器化:基于 Docker Compose 的 apache-php 示例完整实战指南

示例工程 【免费下载链接】awesome-compose Awesome Docker Compose samples 项目地址: https://gitcode.com/gh_mirrors/aw/awesome-compose 点击查看 免费下载 本指南围绕 awesome-compose 仓库中 apache-php 示例展开,讲解如何用 Docker Compose 将一…

2026/9/30 13:20:44 阅读更多 →
URP、HDRP与UE4全局光照对比:烘焙与实时GI选型指南

URP、HDRP与UE4全局光照对比:烘焙与实时GI选型指南

前阵子一个做独立游戏的朋友问了我一个挺典型的问题:同一套低模场景,在URP里烘焙完,切到HDRP之后光照颜色和亮度全变了;放到UE4里用Lightmass重新烘焙,出来的效果又是另一个味道。我说这太正常了,因为三个方…

2026/9/30 13:19:43 阅读更多 →

日新闻

Base64 图片头部特征识别:从文件头到格式判断的完整指南

Base64 图片头部特征识别:从文件头到格式判断的完整指南

1. 项目概述:为什么说看懂 base64 图片头部是基本功这几年跟 base64 打交道的机会越来越多,后端接口返回图片、前端渲染验证码、小程序里存小图、还有一些老系统导出报表,动不动就给你一段长到怀疑人生的 base64 字符串。很多人拿到字符串就直…

2026/9/30 0:00:35 阅读更多 →
Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

Java公交站牌广告管理系统:JSP+Servlet+MySQL实战落地指南

简介:本资源是一份面向Java初学者与课程设计学生的公交站牌广告灯箱管理系统毕业设计文档,聚焦城市公共广告资源信息化管理痛点,提供从需求分析到技术实现的完整方案。文档采用标准学术论文结构,含摘要、英文摘要、目录及五章正文…

2026/9/30 0:00:35 阅读更多 →
用 Redis Lua 构建大模型 API 多租户原子配额治理体系

用 Redis Lua 构建大模型 API 多租户原子配额治理体系

我去年年底接了一个内部 AI 平台的治理需求,背景很直接:公司把 DeepSeek、MiniMax 这类大模型 API 统一封装成内部网关,开放给几个业务团队用。结果第一个月账单出来,额度直接超了 4 倍。仔细查日志,发现原因并不复杂—…

2026/9/30 0:00:35 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/30 13:14:22 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 16:41:41 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/9/30 13:14:49 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/29 19:29:29 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/29 5:58:00 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/29 3:55:56 阅读更多 →