Skip to content
batch

batch

Mojo module 🡭

batch

Rendering a Canvas batch: the primitives recorded between begin_batch and end_batch, drawn in one banded pass.

Every op was recorded under the state in force when it was called (_BatchOp), so rendering is one walk over the ops per row band, in submission order, each op restricted to the band’s rows by the row-restricted body its shape already had: the area accumulator’s band, the sampled sweep’s band, the closed-form disk and ellipse rows, _fill_region on a rectangle’s rows. Bands own disjoint rows and read the batch only, which is the whole safety argument, the same one fill_circles_aa makes. Order within a band is what makes overlapping translucent shapes come out as drawing them one at a time would.

A row’s pixels do not depend on which band computes it – each row body starts from the op’s own geometry – so the bytes are those of drawing every op at once, at any band count (tests/test_batch.mojo).

Before the band pass, the strokes and paths recorded as geometry are built into edges (_build_ops), in parallel over the ops. Drawn one call at a time, that build ran on one core ahead of every stroke’s raster stage; it is the serial prologue #383 and #373 measured. Each build task appends what it builds into one edge table of its own, allocated and filled by the same thread and read by the bands, so a batch of thousands of small shapes costs a few allocations rather than several per op: with one table per op the parallel build spent its time in the allocator and the teardown ran serially over thousands of tables, and a batch of 2,000 small paths was slower than drawing them one at a time.