Re: hb-raster: a new CPU rasterizer
Behdad Esfahbod <[email protected]> Thu, 26 Feb 2026 14:47:10 -0300
| Newsgroups | gmane.comp.freedesktop.harfbuzz,gmane.comp.fonts.freetype.devel |
|---|---|
| Message-ID | <CAF63+7UN+swkWcj1JCwjr6hRTrkbGLGAeCy_uyHYKb64grigUQ@mail.gmail.com> |
--00000000000050c08e064bbdb73c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Alexei, I don't have a Linux machine handy to get good perf numbers until mid March. But looking at the FT code vs mine, a few things pop out: - gray_render_line seems to be doing a lot of int divisions. My code avoids divisions by converting them to multiplies by keeping slope instead. - gray_render_line does the integration as it goes? I do a final pass for integration that is fused to the pixel fill. The pixel fill is done in SIMD, which gave me a nice boost. Here's a few more numbers: With NotoSerifCJK-Varsc: At 400ppem, FreeType is ~10s, font.rs is ~10s, hb-raster is ~5s. At 40ppem, FreeType is 4.2s, font.rs is 3.6s, hb-raster is 3.1s. At 12ppem, FreeType is 2.3s, font.rs is 1.78s, hb-raster is 1.92s. I'll get more numbers when I'm home. Thanks, behdad http://behdad.org/ On Wed, Feb 25, 2026 at 9:24=E2=80=AFAM Alexei Podtelezhnikov <apodtele@gma= il.com> wrote: > Behdad, > > > With help from my AI assistants, I finally put together a rasterizer in > HarfBuzz, in a new harfbuzz-raster library. Accompanying the rasterizer i= s > a COLRv1 color-font renderer, but I like to focus on the rasterizer in th= is > email: > > Congratulations! > > > While it was designed from scratch, the general algorithm is similar to > FreeType's, that is, a coverage based AA rasterizer. From there though, > different approaches are taken. The end result is that the code runs 2x o= r > more faster than FreeType's in my testing. > > Do you mind dissecting the performance of your rasterizer a bit > further with the perf counter? This would help to compare performance > more carefully. For example, > $ perf record bin/ftbench -f2 -s32 -bc tahoma.ttf > $ perf report > > 26.49% ftbench libfreetype.so.6.20.4 [.] gray_render_line > 19.30% ftbench libfreetype.so.6.20.4 [.] gray_set_cell > 18.37% ftbench libfreetype.so.6.20.4 [.] gray_convert_glyph > 7.78% ftbench libfreetype.so.6.20.4 [.] TT_Load_Simple_Glyph > 4.92% ftbench libfreetype.so.6.20.4 [.] gray_conic_to > > This shows how FreeType rasterizer spends its time at 32 ppem. After > subtracting other activities, the curve and line integration is about > 40%, the pixel list management is 30%, the final sweep is 30%. I > suspect that the linked list management is what you avoid at the > expense of more memory usage, with a faster sweep too. > > > I long had intuited that a tightly woven rasterizer code will perform > really well, and this experiment seems to prove that. The code is very > short (~1000 lines) and readable: > > > > https://github.com/harfbuzz/harfbuzz/blob/main/src/hb-raster-draw.cc > > Thanks, > Alexei > --00000000000050c08e064bbdb73c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div>Hi Alexei,</div><div><br></div><div>I don't have = a Linux machine handy to get good perf numbers until mid March. But looking= at the FT code vs mine, a few things pop out:</div><div><br></div><div>- g= ray_render_line seems to be doing a lot of int divisions. My code avoids di= visions by converting them to multiplies by keeping slope instead.</div><di= v><br></div><div>- gray_render_line does the integration=C2=A0as it goes? I= do a final pass for integration that is fused to the pixel fill. The pixel= fill is done in SIMD, which gave me a nice boost.</div><div><br></div><div= >Here's a few more numbers: With NotoSerifCJK-Varsc:</div><div><br></di= v><div>At 400ppem, FreeType is ~10s, font.rs is ~10s, hb-raster is ~5s.</di= v><div>At 40ppem, FreeType is 4.2s, font.rs is 3.6s, hb-raster is 3.1s.<br>= At 12ppem, FreeType is 2.3s, font.rs is 1.78s, hb-raster is 1.92s.</div><di= v><br></div><div>I'll get more numbers when I'm home.</div><div><br= ></div><div>Thanks,</div><div><br></div><div><div dir=3D"ltr" class=3D"gmai= l_signature" data-smartmail=3D"gmail_signature">behdad<br><a href=3D"http:/= /behdad.org/" target=3D"_blank">http://behdad.org/</a></div></div><br></div= ><br><div class=3D"gmail_quote gmail_quote_container"><div dir=3D"ltr" clas= s=3D"gmail_attr">On Wed, Feb 25, 2026 at 9:24=E2=80=AFAM Alexei Podtelezhni= kov <<a href=3D"mailto:[email protected]">[email protected]</a>> wr= ote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px= 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Behdad,<br> <br> > With help from my AI assistants, I finally put together a rasterizer i= n HarfBuzz, in a new harfbuzz-raster library. Accompanying the rasterizer i= s a COLRv1 color-font renderer, but I like to focus on the rasterizer in th= is email:<br> <br> Congratulations!<br> <br> > While it was designed from scratch, the general algorithm is similar t= o FreeType's, that is, a coverage based AA rasterizer. From there thoug= h, different approaches are taken. The end result is that the code runs 2x = or more faster than FreeType's in my testing.<br> <br> Do you mind dissecting the performance of your rasterizer a bit<br> further with the perf counter? This would help to compare performance<br> more carefully. For example,<br> $ perf record bin/ftbench -f2 -s32 -bc tahoma.ttf<br> $ perf report<br> <br> =C2=A0 26.49%=C2=A0 ftbench=C2=A0 libfreetype.so.6.20.4=C2=A0 [.] gray_rend= er_line<br> =C2=A0 19.30%=C2=A0 ftbench=C2=A0 libfreetype.so.6.20.4=C2=A0 [.] gray_set_= cell<br> =C2=A0 18.37%=C2=A0 ftbench=C2=A0 libfreetype.so.6.20.4=C2=A0 [.] gray_conv= ert_glyph<br> =C2=A0 =C2=A07.78%=C2=A0 ftbench=C2=A0 libfreetype.so.6.20.4=C2=A0 [.] TT_L= oad_Simple_Glyph<br> =C2=A0 =C2=A04.92%=C2=A0 ftbench=C2=A0 libfreetype.so.6.20.4=C2=A0 [.] gray= _conic_to<br> <br> This shows how FreeType rasterizer spends its time at 32 ppem. After<br> subtracting other activities, the curve and line integration is about<br> 40%, the pixel list management is 30%, the final sweep is 30%. I<br> suspect that the linked list management is what you avoid at the<br> expense of more memory usage, with a faster sweep too.<br> <br> > I long had intuited that a tightly woven rasterizer code will perform = really well, and this experiment seems to prove that. The code is very shor= t (~1000 lines) and readable:<br> ><br> >=C2=A0 =C2=A0<a href=3D"https://github.com/harfbuzz/harfbuzz/blob/main/= src/hb-raster-draw.cc" rel=3D"noreferrer" target=3D"_blank">https://github.= com/harfbuzz/harfbuzz/blob/main/src/hb-raster-draw.cc</a><br> <br> Thanks,<br> Alexei<br> </blockquote></div> --00000000000050c08e064bbdb73c--