Donner SVG 0.8.0-pre
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
donner::geode::GeodeResidentSlab Class Reference

Document-scoped suballocation slab for GPU residence. More...

#include "donner/svg/renderer/geode/GeodeResidentPathComponent.h"

Classes

struct  Allocation
 One sub-range of a slab chunk. More...

Public Member Functions

const gpu::BufferbufferForId (uint64_t bufferId) const
 The chunk buffer carrying bufferId, or a null handle when this slab does not own it. Uploads need the owning handle; Slot and Allocation only carry an identity view.
uint64_t chunkBytesForId (uint64_t bufferId) const
 Byte size of the chunk carrying bufferId, or 0 when this slab does not own it.
 GeodeResidentSlab (uint64_t deviceId, std::shared_ptr< GeodeDocumentGeometryBudget > budget=nullptr)
 Create an empty slab bound to deviceId (usually the current renderer's device). Chunks are allocated lazily on first use.
 GeodeResidentSlab (const GeodeResidentSlab &)=delete
GeodeResidentSlaboperator= (const GeodeResidentSlab &)=delete
uint64_t owningDeviceId () const
 Device this slab's chunks were created on.
const std::shared_ptr< GeodeDocumentGeometryBudget > & documentBudget () const
void beginFrame (uint64_t frameIndex)
 Merge the previous frame's freed ranges into the reusable free list. Gated on frameIndex (the renderer's frame counter) so the merge runs at most once per frame no matter how many times the renderer touches the slab: the accessor calls this on every slot lookup, which covers every draw entry point (full-document draws and multi-document tile/thumbnail frames alike) without trusting any single call site.
bool allocate (GeodeDevice &device, uint64_t size, uint64_t alignment, Allocation &out)
 Bump- or free-list-allocate size bytes aligned to alignment. Creates a new chunk (and counts it) when nothing fits. Returns false when the device cannot create a buffer.
void free (const Allocation &alloc)
 Return an allocation for reuse at the NEXT frame boundary. The range is not reusable within the current frame: see beginFrame().
void retireBindGroup (gpu::BindGroup bindGroup)
 Park a bind group a slot is dropping until the next frame boundary.

Detailed Description

Document-scoped suballocation slab for GPU residence.

Per-slot residence previously gave every cached path its own combined GPU buffer, so a first frame allocated one buffer per resident slot (Lion: 133). The slab replaces those with sub-ranges of a small number of growable chunk buffers owned by the document's registry context, cutting first-frame bufferCreates to one chunk per growth step (1 to 2 for typical documents).

Allocations are bump-placed and returned through a first-fit free list, so a geometry edit that re-uploads a slot reuses the freed range. Each chunk's bytes are accounted in the device's live-resident-bytes gauge on creation and released when the slab is destroyed with its registry. Note the gauge therefore reports slab CAPACITY, not live payload bytes: it grows when a chunk is created and never shrinks on slot reset, which is the right shape for leak detection but over-reads against the previous per-slot accounting.

The slab is bound to one device (GeodeDevice::deviceId()): a document rendered by a second device gets a fresh slab, and the old chunks are released without touching the old device's objects (WebGPU retains any still-referenced buffers through submitted command buffers).

Not thread-safe: allocate/free/beginFrame mutate the free list and bump cursors without locking. The renderer serializes one frame per device at a time, so a document's slab is only touched from one thread.


Class Documentation

◆ donner::geode::GeodeResidentSlab::Allocation

struct donner::geode::GeodeResidentSlab::Allocation

One sub-range of a slab chunk.

Class Members
BufferRef buffer
uint64_t bufferId = 0 Stable identity of buffer (see GeodeDevice::AllocateBufferId). Only allocation results carry it; free matches on the handle, which is unambiguous while the slab that owns the chunk is alive.
uint64_t offset = 0
uint64_t size = 0

Member Function Documentation

◆ beginFrame()

void donner::geode::GeodeResidentSlab::beginFrame ( uint64_t frameIndex)
inline

Merge the previous frame's freed ranges into the reusable free list. Gated on frameIndex (the renderer's frame counter) so the merge runs at most once per frame no matter how many times the renderer touches the slab: the accessor calls this on every slot lookup, which covers every draw entry point (full-document draws and multi-document tile/thumbnail frames alike) without trusting any single call site.

Freed ranges must NOT be reused within the frame that freed them: a re-upload that reuses its own just-freed range would overwrite the geometry before the already-recorded draws of the same frame read it (the resident slots hold one buffer range per slot, not one buffer per draw). Merging at the first touch of frame N is safe because ranges pending at that point were freed no later than frame N-1, whose command buffer was submitted at its endFrame; a second renderer on the same device has its own frame counter, and a stale-index skip only defers the merge (the safe direction). Frames on one device are serialized by contract, so no merge can run under another renderer's unsubmitted frame.

◆ bufferForId()

const gpu::Buffer & donner::geode::GeodeResidentSlab::bufferForId ( uint64_t bufferId) const
inline

The chunk buffer carrying bufferId, or a null handle when this slab does not own it. Uploads need the owning handle; Slot and Allocation only carry an identity view.

Parameters
bufferIdStable buffer id stamped on the slot or allocation.

◆ chunkBytesForId()

uint64_t donner::geode::GeodeResidentSlab::chunkBytesForId ( uint64_t bufferId) const
inline

Byte size of the chunk carrying bufferId, or 0 when this slab does not own it.

Parameters
bufferIdStable buffer id stamped on the slot or allocation.

◆ retireBindGroup()

void donner::geode::GeodeResidentSlab::retireBindGroup ( gpu::BindGroup bindGroup)
inline

Park a bind group a slot is dropping until the next frame boundary.

A slot's cached bind group can be dropped mid-frame (geometry re-upload, component removal, device change) while draws recorded earlier in the frame still name it and have not reached the backend yet. Destroying it there fails those draws closed, so it is held here and released at the next beginFrame, by which point the frame that recorded them has been submitted.

Parameters
bindGroupBind group to release at the next frame boundary.

The documentation for this class was generated from the following file: