Expand description
The image atlas array, and the encoded-image record the strip shader reads it through.
Two halves, split on the same line the rest of crate::gpu is split on.
- Pure decisions over plain values. The texture descriptor, the packing
of an
AtlasRegionand a sampler into aGpuEncodedImage, and the natural-to-device transform an image paint carries — all host-testable with no device. - One live-GPU type.
AtlasArrayowns theRgba8UnormD2Arraytexture the shader’satlas_texture_arraybinding samples, grows it a layer at a time, writes newly resident regions and clears evicted ones.
§Why the atlas is not pooled
crate::gpu::targets pools every transient the engine allocates, on the
rule that a target nothing outlives the frame should be reused rather than
reallocated. The atlas is the opposite kind of resource: its whole purpose
is that an image uploaded on one frame is still there on the next thousand,
so it is owned outright for the life of the renderer and reclaimed a region
at a time by crate::cache::images’s age-based reap. Handing it to the
pool would make residency a lie.
§Growth and clearing
A wgpu texture’s array-layer count is fixed at creation, so growing the
array means creating a deeper texture and copying every existing layer
across — which is why the array carries COPY_SRC alongside COPY_DST.
Growth is rare (a layer holds a whole mobile budget’s worth of images) and
never shrinks: an atlas that grew to four layers under load keeps them.
§Why growth submits a command buffer of its own
That copy is the one piece of engine work that cannot ride the frame’s
encoder. wgpu flushes the queued writes pending at a submit before the
command buffers of that same submit, so a copy recorded into the frame’s
encoder would execute after the frame’s own write_texture uploads and
clears — restoring the pre-growth contents of every layer they had just
written, permanently (residency schedules an upload on a miss, and the image
is not a miss any more). Ordering is therefore established by submitting the
copy on its own, ahead of the frame’s writes being issued at all.
That is a maintenance submit, not scene work: it carries one texture
copy, no pass and no draw, and it happens only on the rare frame that grows
the array. crate::renderer::EngineRenderer::encode’s contract that the
engine never submits the caller’s encoder, and records no scene work
anywhere else, is untouched — the caller’s encoder is neither read nor
finished here.
Clearing an evicted region writes transparent texels through the queue rather than drawing a scissored pass. Both reach the same result; the queue write needs no pipeline, no render pass and no bind group, and eviction is a once-in-sixty-frames event whose cost is a zeroed staging buffer the size of the region.
§Rendering into the atlas
Everything above writes the atlas from the host. A glyph is different: it
has no pixels until something rasterizes its outline, and glifo’s
AtlasCacher::Enabled path does not
rasterize one — it records the fills into a per-page
AtlasCommandRecorder and leaves the pixels to whoever owns the atlas.
AtlasRenderer is that owner on this tier: it replays each dirty page’s
commands into a strip pass whose colour attachment is that page’s own array
layer.
Three orderings make the difference between a correct glyph and a stale one, and all three are this type’s to keep.
- Clears before uploads. A rectangle an eviction freed can be handed straight back out to a different glyph on the same frame, so zeroing it after that glyph’s pixels landed would erase the glyph that just moved in. Both are queue writes, which execute in the order they are issued — so the order they are issued in is the whole guarantee.
- Both before the pass.
wgpuflushes the writes queued at a submit before that submit’s command buffers, so a page’s replay pass sees the clears and the bitmap uploads already applied to the layer it composites onto, without anything having to be said about it. - The pass before the scene’s. A glyph the scene pass samples out of
the atlas has to be in the atlas by then, and the scene pass lives in
an encoder this crate does not own and never submits. So the replay pass
goes into an encoder of
AtlasRenderer’s own and is submitted before it returns — the sanctioned exception tofrust_gpu::CommandBuffer’s single-submit borrowing contract, named there as the glyph-atlas upload carve-out and the same oneAtlasArray::ensure_layersalready takes for the growth copy.
One submit per dirty page rather than one for all of them: the coverage a page’s strips index is uploaded to a shared alpha texture, and a second queue write to that texture in the same submit would overwrite the first before either pass ran. Pages are dirty only on a frame that missed a glyph, and there is one page in the overwhelming case, so the extra submit is a per-miss cost rather than a per-frame one.
§What the replay does not lower
Turning a recorded command stream into strips is compiler work, and
crate::compile already depends on this module — so the lowering is a
closure the caller supplies (AtlasRenderer::render_pending) rather than
a dependency taken the other way. What this module contributes to it is
push_solid_strips, the pure expansion of one solid-painted strip run
into instances, which is the whole of an outline glyph’s lowering.
Structs§
- Atlas
Array - The atlas array texture, its view, and the layer count both were created at.
- Atlas
Page Buffers - One page’s lowered replay: the instances to draw and the coverage they index.
- Atlas
Render Report - What one call to
AtlasRenderer::render_pendingserviced. - Atlas
Renderer - The GPU home for glyph pixels: replays
glifo’s recorded atlas commands into the atlas array’s own layers, and services the two pixel drains that have to be ordered around them.
Constants§
- ATLAS_
FORMAT - The texture format the atlas array stores premultiplied image texels in.
- ATLAS_
USAGES - The usages the atlas array is created with.
- MAX_
ATLAS_ INDEX - The most atlas layers the encoded-image record’s
atlas_indexfield can name (eight bits).
Functions§
- atlas_
layer_ view_ descriptor - The single-layer
D2view descriptor a render pass attaches one atlas layer through. - atlas_
texture_ descriptor - The descriptor for an atlas array of
widthxheighttexels overlayersarray layers. - atlas_
view_ descriptor - The
D2Arrayview descriptor the strip shader’s atlas binding expects. - clear_
rect_ region - The atlas rectangle one of
glifo’s pending clear rects names. - extend_
mode - The shader’s extend-mode numbering.
- lower_
encoded_ image - Lower one encoded image paint into the record the strip shader samples.
- natural_
to_ dest - The affine mapping an image’s natural pixel rectangle
(0, 0, width, height)ontodest, composed undertransform. - pack_
image_ offset - Packs an image’s atlas offset into one word, x in the high half.
- pack_
image_ params - Packs sampling quality (bits 0-1), the two extend modes (bits 2-3 and 4-5), the atlas layer (bits 6-13) and the source kind (bit 14) into one word.
- pack_
image_ size - Packs an image’s width and height into one word, width in the high half.
- pack_
tint - The premultiplied colour and mode an optional tint packs to.
- push_
solid_ strips - Expands one solid-painted strip run into the instances that draw it,
appending to
out. - region_
byte_ len - The bytes a region’s texels occupy — the length
AtlasArray::write_regionrequires of its slice. - slot_
region - The atlas rectangle one pending bitmap upload’s slot occupies.
- x_
y_ advances - The per-pixel advances in image space an encoded image carries, derived from its already-inverted transform.