Plans and assembles the batch that starts at items[from], or returns
null when that item does not start one.
const batch = batcher.next(list, i, viewMask);
if (batch !== null) { draw(batch); i += batch.items - 1; }
Returning null is the common answer and costs one predicate plus, at
most, one comparison against the next item: an item that cannot batch, or
whose successor carries a different material, is rejected before anything
is written. A caller that skips the merged items (i += batch.items - 1)
pays O(n) in total for a whole list, since each item is examined by the
scan that consumes it and by the scan that stops at it.
layerMask is §46's per-view filter, applied here for the same reason a
backend applies it per item: an item this view does not draw must not be
merged into a batch it would draw. A masked-out item ends the run
rather than being skipped inside it, so the returned items count is
always a contiguous span of the list and the caller's index arithmetic
stays trivial.
a render list, as buildRenderList produced it.
index of the item to start at.
§46 mask of the view being drawn; defaults to ALL_LAYERS.
the pooled batch — valid until the next call — or null.
§65's batcher: finds runs of compatible consecutive render items and merges each into one draw's worth of vertex data.
One instance per consumer (a renderer owns one), because the staging arrays and the batch record are reused across calls. Holds no GPU resources, no scene references and nothing to dispose: between calls it retains only its two typed arrays and the material of the last batch it built.