Skip to main content

ImageResidency

Struct ImageResidency 

Source
pub struct ImageResidency { /* private fields */ }
Expand description

The images resident in the atlas array, keyed by blob identity.

One per compiler (and so one per surface). Its frame clock is advanced by begin_frame, which is also where the age-based reap runs — before any of the frame’s own resolutions, so a rectangle freed this frame is available to this frame’s allocations and its clear is ordered ahead of their uploads.

It also owns the atlas allocator the glyph policy packs into — see this module’s doc and allocator_mut.

Implementations§

Source§

impl ImageResidency

Source

pub fn new(budget: AtlasBudget) -> Self

A residency over budget’s atlas geometry.

FRUST_ENGINE_NO_ATLAS is consulted here, once, rather than per resolution: the switch is process-global and cached, so re-reading it on a hot path would buy nothing but a lock. A residency constructed with the switch set is exactly disabled.

Source

pub fn disabled(budget: AtlasBudget) -> Self

A residency that refuses every image, allocating no atlas at all.

What FRUST_ENGINE_NO_ATLAS selects, and what a caller wanting the same effect programmatically constructs. Every resolve answers ImageSkip::AtlasDisabled, so image draws are dropped with a logged reason rather than painted from an atlas that does not exist.

Source

pub fn for_caps(caps: &TierCaps) -> Self

A residency sized for caps’ adapter.

Source

pub fn budget(&self) -> AtlasBudget

The atlas geometry this residency allocates within.

Source

pub fn allocator(&self) -> &ImageCache

The single atlas allocator, for reading.

Enough to resolve a handle either side allocated (ImageCache::get) or to count the layers created so far, without the mutable borrow allocation needs.

Source

pub fn allocator_mut(&mut self) -> &mut ImageCache

The single atlas allocator, for allocating through.

This is the seam the glyph policy takes its slots from — see this module’s doc for why one cache rather than two is a correctness requirement. ImageIds and rectangles handed out through here and through resolve come from the same packer and the same id space, so a glyph and an image can never be given the same handle or overlapping texels.

The contract a borrower keeps: allocate what you like, and deallocate only handles you allocated yourself. This residency’s entry map records the rectangles it allocated and nothing re-checks them; freeing one of them from outside would leave an entry claiming a rectangle the packer has since handed to someone else. Nothing here enforces that, because the type the two sides must share is vello_common’s own and cannot carry an ownership tag — the glyph policy deallocates strictly inside glifo’s eviction, over the handles in its own entry map.

Source

pub fn is_disabled(&self) -> bool

Whether this residency refuses every image.

Source

pub fn entry_count(&self) -> usize

How many images are currently resident.

Source

pub fn frame(&self) -> u64

The frame clock entries age against.

Source

pub fn layers(&self) -> u32

How many atlas layers have been created so far.

The array texture must be at least this deep before the frame’s uploads are written.

Read off the shared allocator rather than accumulated from this residency’s own allocations, so a layer the glyph policy created counts too: the two classes pack into one array, and an array sized to the image half alone would refuse to hold the glyph half’s pages. The count only ever grows — MultiAtlasManager appends layers and never drops one — so a depth reported on an earlier frame stays valid.

Source

pub fn skipped(&self) -> u64

How many resolutions have been refused over this residency’s lifetime.

Counts only images that could not be uploaded at all — a format or extent the conversion refuses, a disabled atlas, or an atlas with no room left and nothing evictable to make room with. A source merely larger than one atlas layer is minified to fit, and one that displaced another image is counted by pressure_evictions instead; neither reaches this counter.

Source

pub fn pressure_evictions(&self) -> u64

How many resident images have been evicted to make room for another over this residency’s lifetime.

The price of never refusing a draw the atlas could hold something for: each one is an image that will re-upload the next frame it is drawn on. A steady screen leaves this at zero; a scroll through more distinct images than the atlas has rectangles for grows it once per displaced image, which is the signal that the budget — not the mechanism — is what a frame is paying for.

Source

pub fn frame_pressure_evictions(&self) -> u64

How many resident images the current frame has evicted to make room.

Zeroed by begin_frame, so a per-frame report reads this rather than differencing pressure_evictions itself.

Source

pub fn minified(&self) -> u64

How many sources have been downsampled to fit the atlas over this residency’s lifetime.

Observational, and the counter that makes “an image too large for the atlas is minified, not dropped” measurable rather than asserted.

Source

pub fn evictions(&self) -> &[AtlasRegion]

The regions whose texels must be cleared before the pending uploads.

Pending rather than per-frame: an entry freed on a frame nobody serviced is still waiting to be cleared on the next one. Both kinds of eviction land here — the age-based reap at the head of a frame and a rectangle taken back under pressure mid-frame — so the consumer’s clear-then-upload contract covers the second without knowing it exists.

Source

pub fn uploads(&self) -> &[ImageUpload]

The regions whose texels must be written after the pending evictions.

Pending rather than per-frame: an image made resident on a frame that was refused is still waiting to be written on the next one.

Source

pub fn plan(&self) -> (Vec<AtlasRegion>, Vec<ImageUpload>)

A copy of the pending clear-then-write plan, evictions first.

A copy, not a drain: the plan stays pending until acknowledge_plan says it was serviced against a live atlas, so a frame refused after compiling re-emits the same plan on the next frame rather than losing it (see the module doc). The upload pixels are behind an Arc, so a re-emitted plan copies handles rather than texels, and the steady-state plan is empty on both counts.

Source

pub fn has_pending_plan(&self) -> bool

Whether any part of the pending plan is still unserviced.

Source

pub fn acknowledge_plan(&mut self)

Record that the pending plan reached the atlas array, clearing it.

Call this only once every region it names has actually been written or cleared. Calling it on a frame that was refused, or whose writes the array declined, is exactly the defect the pending plan exists to prevent: the entry map would go on claiming an image is resident whose texels are whatever the atlas texture happened to hold.

Source

pub fn begin_frame(&mut self)

Advance the frame clock and reclaim everything unseen for MAX_UNSEEN_FRAMES.

Call once at the head of a frame, before any resolve. An unacknowledged plan deliberately survives this: the frame that was to service it may have been refused, and dropping it here is what would turn a refused frame into a permanently unwritten atlas region.

Source

pub fn resolve(&mut self, data: &ImageData) -> Result<ResidentImage, ImageSkip>

The atlas rectangle for data’s pixels, allocating and scheduling an upload on the first frame that asks for it.

§Errors

Returns the ImageSkip naming why the image was refused. Every refusal happens before any vello_common call that could assert on the same condition, so an image the renderer cannot hold is a skipped draw rather than a panicked frame (E17).

Trait Implementations§

Source§

impl Debug for ImageResidency

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,