返回资讯中心
外部精选
软件工程
#开发者实时流

开发者用JIT技术在RP2350微控制器上实现极速位图文字渲染

来源标题:JIT bitmap text rendering for microcontrollers

开发者分享了在RP2350微控制器上基于JIT的极速位图文字渲染技术,并已将其应用于自制的vic-2350项目。该方案支持比例间距和字距调整,核心思路是运行时为字符串生成高度优化的渲染代码,突破了微控制器上常见的固定字符格渲染方式。

Hacker News 最新raphlinus2026/11/7 · 今天30 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

我一直在开发 vic-2350,这是一个在 RP2350 微控制器板子上对 80 年代家用电脑的重新构想。当然,这样的项目需要文本渲染。尽管点阵字体如今已不再流行,但我选择它既是出于效率考虑,也是因为在低分辨率下,我更偏爱清晰、经过精心设计的点阵字体的美感,而不是抗锯齿字体渲染那种模糊的一团。它们仍然有其用武之地,尽管很狭窄。我还想要比例间距和字距调整,同样是因为我喜欢早期 Macintosh 及其前代的美学风格。RP2350 项目中的大多数文本渲染都基于固定字符单元,因为要获得良好的性能并不容易。这篇博客文章介绍了一种在 RP2350 等微控制器上极速渲染点阵文本的技术。我将其实现为我的 race-the-beam 渲染器的一部分,但同样的技术也适用于写入 framebuffer 的情况。核心思想是一个 JIT,在运行时为渲染字符串生成高度优化的代码。大约在 80 年代中期,计算机显示文本的方式发生了分化。既有的技术是固定单元大小,硬件在图像扫描输出到显示器的过程中实时从字体 ROM 中查找字符。其优势是在有限的硬件条件下实现非常快速的更新和响应。许多终端就是这样工作的,家用电脑也是如此。缺点是不够灵活。特别是只支持等宽字体。较新的技术是点阵 framebuffer,最早由源自 Xerox Alto 的一系列计算机开创,经由 Apple Lisa 延续,最终在 Macintosh 上流行起来。framebuffer 灵活得多,但需要多得多的计算能力来保持更新。在 80 年代初,你通常会看到文本逐渐渲染出来。我还应该提到,家用电脑通常也有图形模式,但它们的分辨率通常低于文本模式,而 1MHz 的 6502(或类似处理器)根本不够强大,所以像文字处理器和电子表格这样严肃的基于文本的程序都使用文本模式。快进到 RP2350。借助 HSTX 外设,它能够输出 DVI 视频,但填充视频缓冲区仍然完全由软件负责。有些项目选择使用 framebuffer,但芯片上只有 520kB 的 SRAM,因此 framebuffer 必须在分辨率或位深度或两者上受到限制,而且这部分 RAM 最好还能供应用用于其他目的。我选择的是 race the beam,即逐扫描线填充视频缓冲区。这允许更丰富的视觉效果和低得多的延迟,但对渲染器构成了严格的性能约束。每像素大约有 6 个周期的预算。我们低于预算越多,就有越多资源可用于渲染其他图形对象和其他应用功能。Rust 无法满足性能要求,所以我开始编写 ARM 汇编语言。渲染器以及 vic-2350 的大部分内容现在都是用 symbolasm 编写的,这是我为极高性能 Cortex-M33 编程创建的一种编程语言。使用 JIT 可以进一步加速渲染。渲染通常被建模为流水线,vic-2350 渲染器也不例外。应用与渲染器之间的接口是显示列表。本质上,它就是一个显示对象的列表。显示列表是双缓冲的;一个正在被渲染和扫描输出,另一个由应用构建。在每个 vsync 时,如果应用准备就绪,显示列表就会交换。构建显示列表的计算量不大,但应用当然可能忙于其他事情。由于显示列表在编译时大小未知,它会进行分配。显示对象被装入两个向量;一个存放显示对象本身,另一个存放指向第一个向量的索引列表。一个显示对象由 vtable、边界矩形和对象特定的负载组成。分配是可以接受的,因为构建显示列表不是时间关键的操作。渲染则是另一回事。也就是说,显示列表的内存效率很重要,尤其是因为有两份副本。在呈现之前,索引按 y0 升序排序。在渲染过程中,渲染器维护一个活动列表,它只是与当前扫描线相交的显示对象的子集。在每个扫描线,y1 = y 的对象从活动列表中删除,y0 = y 的新对象被插入,这就是之前排序的原因;这正是对象插入活动列表的顺序。活动列表按显示对象顺序保持。然后渲染器只需对活动列表中的每个显示对象调用渲染方法。我很快就会做更多优化,跟踪不透明区间并省略将被后续覆盖的像素区间的渲染工作,但这对于本文所介绍的文本渲染来说并非根本性的。在对象的开始和结束处(当它被插入和删除时),渲染器会在显示对象上调用 start 和 end 方法。这些方法可以分配暂存空间并做其他工作来为对象的渲染做准备。有一个专门的位图分配器,既快速又确定。所有这些为我们提供了将文本渲染实现为显示对象实例所需的一切。文本对象本身包含字符串(每字符 1 字节)、指向字体的指针以及前景色和背景色。RAM 很宝贵,对于双缓冲的显示列表来说更是如此。在渲染器的早期迭代中,我在显示列表中存储了文本的展开版本,当屏幕充满文本时,这造成了不可接受的内存压力。start 方法为 JIT 代码和每像素 1 位的中间缓冲区分配暂存空间,并调用 JIT 编译器,将字符串展开为代码。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →