Donner SVG 0.8.0
0.8.0 ยท ebf353960.8.0 main
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
donner::geode::GeodeResidentSlot Struct Reference

GPU-resident geometry for one cached EncodedPath (a fill slot or a stroke slot). Owns a single combined-usage GPU buffer that holds the path's eight analytic dual-ray SSBO regions and per-draw uniform block, plus the cached fill bind group. Bounding vertices live in that uniform and are expanded from vertex_index, so the resident geometry needs no vertex buffer. The buffer and bind group are built once by GeoEncoder on first residence and reused every subsequent unchanged frame. More...

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

Classes

struct  Region
 A byte sub-range of buffer. size == 0 is never bound directly - empty SSBO regions reserve a zero-filled dummy slot wide enough for one element of the WGSL array they feed, so the shader's band-count gate keeps them un-dereferenced and the binding still passes WebGPU's minimum-size validation (matching the per-frame arena allocStorageOrDummy dummy). More...

Public Member Functions

bool reserveUniformMirror (uint64_t bytes)
 Replace the cached uniform's CPU-byte reservation.
bool reserveRecordMirror (uint64_t bytes)
 Replace the cached record's CPU-byte reservation.
bool reservePaintMirror (uint64_t bytes)
 Replace the cached paint's CPU-byte reservation.
 GeodeResidentSlot (const GeodeResidentSlot &)=delete
GeodeResidentSlot & operator= (const GeodeResidentSlot &)=delete
 GeodeResidentSlot (GeodeResidentSlot &&other) noexcept=default
 Transfer slab handles, cached bindings, and CPU reservations.
GeodeResidentSlot & operator= (GeodeResidentSlot &&other) noexcept
 Release current geometry residence and mirrors, then take ownership of another slot.
void reset ()
 Return the slab allocation and drop the bind group + borrowed handle. Safe to call on an empty slot. A geometry mutation can remove this component after a draw has referenced the buffer but before the frame's command encoder is submitted. Do not call Buffer::destroy() here: that makes the buffer unusable immediately, invalidating the already-recorded draw. Releasing our references is enough for the buffer, whose storage the slab owns; the bind group is handed to the slab instead of dropped, because draws recorded earlier this frame may still name it and have not reached the backend yet.

Public Attributes

gpu::BufferRef buffer
 Combined Storage|Uniform|CopyDst buffer, borrowed from the owning GeodeResidentSlab chunk. Region offsets are ABSOLUTE buffer offsets. Layout (each region offset satisfies the binding's alignment requirement): [ bands | curves | vBands | vCurves | hGrid | vGrid | hRefs | vRefs | uniform ] The four grid classes are placed adjacently on purpose: they share one storage binding, whose range spans them. The slot is padded out to the slab's allocation alignment so consecutive slots leave no unwritten bytes between them.
uint64_t bufferId = 0
 Stable identity of buffer (see GeodeDevice::AllocateBufferId). A cross-entity batch binds the whole chunk and caches the resulting bind group past the lifetime of the document that owns it, so the cache key has to name the chunk by this id rather than by the handle address, which the allocator recycles once the slab is destroyed.
std::shared_ptr< GeodeResidentSlab > slab
 Slab that owns buffer, this device's geometry slab for the document; null until residence is established. Held by shared_ptr so the slab outlives every slot allocated from it, whichever of the two the document lets go of first.
uint64_t allocationOffset = 0
 Whole-slot allocation inside the slab, returned via free on reset.
uint64_t allocationSize = 0
 Number of bytes occupied by this slot's allocation.
gpu::BindGroup bindGroup
 Cached fill bind group. All twelve bindings reference stable objects (this slot's buffer sub-ranges + device-owned dummy texture/sampler/identity-instance handles), so it survives frames and encoders. Rebuilt only when the geometry buffer is re-allocated.
Region bands
 Horizontal band SSBO (binding 1).
Region curves
 Horizontal curve SSBO (binding 2).
Region hRefs
 Horizontal curve-reference SSBO (binding 10).
Region vBands
 Vertical band SSBO (binding 8).
Region vCurves
 Vertical curve SSBO (binding 9).
Region vRefs
 Vertical curve-reference SSBO (binding 10).
Region hGrid
 Horizontal band grid (binding 10).
Region vGrid
 Vertical band grid (binding 10). Gradient paint block: transform rows, gradient geometry, and the stop ramp, as vec4 rows addressed by the record's paintBase (binding 11). Always reserved, so a fill that changes from solid to gradient paint rewrites this region rather than re-laying-out the slot; a solid fill leaves it zero-filled and its record never reads it.
Region paint
 Gradient paint block within the resident buffer.
Region uniform
 Batch-level uniform block (binding 0, 256-aligned).
GeodeRecordSlab::Slot recordSlot
 Document-scoped record slab slot for this entity's instance record (binding 7). Solo draws bind the slot's own range; cross-entity batches bind a span of consecutive slots and index by slot index.
std::shared_ptr< GeodeRecordSlab > recordSlab
 Record slab that owns recordSlot, this device's record slab for the document; held by shared_ptr for the same reason as slab.
uint32_t vertexCount = 0
 Triangle-fan draw count generated from vertex_index.
uint64_t lastResidentFrame = ~uint64_t{0}
 Frame index in which this slot was last drawn via the resident path. A slot's single uniform buffer + cached bind group can only serve ONE draw per frame (all draws recorded against a frame's command buffer read the buffer's final contents at submit time). When the same slot is drawn again in the same frame at a different transform/color (markers, non-adjacent repeated <use>), the second and later draws fall back to the per-frame arena path so each gets its own uniform. The steady-state win is unaffected for the common case of a path drawn once per frame (Tiger / Lion). Sentinel ~0 means "never drawn".
uint64_t owningDeviceId = 0
 Process-unique id (see GeodeDevice::deviceId()) of the device that created buffer / bindGroup. Every device keeps its own slots (see GeodeResidentPathComponent), so this always names the device drawing the slot. The draw path still checks it and treats a mismatch as non-resident, re-uploading, as a defensive cross-check: WebGPU rejects a bind group or buffer from one device inside another's render pass. 0 means "no device owns this slot yet".
uint64_t lastSceneFrame = ~uint64_t{0}
 Frame index in which this slot's record was last referenced by a recorded scene-batch draw. A record slot holds ONE record; an entity drawn again in the same frame (markers, repeated <use>) needs a fresh record slot so earlier recorded batches keep reading their own content at submit time. The scene batcher consults this to decide between the slot's primary record and a per-frame temporary one.
bool resident = false
 True once buffer + bindGroup hold the current encode. Cleared when the slot is reset or when a re-upload is required.
const void * encodedKey = nullptr
 Identity guard defending against any missed invalidation: the address of the EncodedPath last uploaded plus a cheap size fingerprint. If either differs at draw time the geometry is re-uploaded. Component removal is the primary invalidation; this is belt-and-suspenders for the in-place stroke-slot rebuild path.
uint64_t encodedFingerprint = 0
 Size-based fingerprint of the last uploaded encoded path.
std::vector< uint8_t > lastRecord
 Bytes last written to the instance-record region. A draw whose recomputed record matches this skips the writeBuffer entirely (steady-state frames write zero record bytes).
std::vector< uint8_t > lastPaint
 Bytes last written to the gradient paint region, with the same skip-when-unchanged contract as the record and the uniform.
uint32_t paintMode = 0
 Paint published by the last paint write: the record's paintMode and the two gradient scalars that go with it. They live on the slot rather than travelling with each draw because a batch re-derives an instance's record at flush time, after the caller's resolved gradient is gone, and must reproduce byte-identical bytes.
uint32_t gradientSpread = 0
 Last published gradient spread mode.
uint32_t gradientStopCount = 0
 Last published gradient stop count.
std::vector< uint8_t > lastUniform
 Bytes last written to the uniform region. A draw whose recomputed uniform matches this skips the writeBuffer entirely (steady-state static frame => zero buffer writes); a camera/color change rewrites only this 448-byte region and keeps the cached bind group.
GeodeGeometryCacheReservation cpuMirrorReservation
 Charged CPU mirror storage.
uint64_t cpuUniformBytes = 0
 Capacity bytes reserved for the cached uniform.
uint64_t cpuRecordBytes = 0
 Capacity bytes reserved for the cached record.
uint64_t cpuPaintBytes = 0
 Capacity bytes reserved for cached paint data.

Detailed Description

GPU-resident geometry for one cached EncodedPath (a fill slot or a stroke slot). Owns a single combined-usage GPU buffer that holds the path's eight analytic dual-ray SSBO regions and per-draw uniform block, plus the cached fill bind group. Bounding vertices live in that uniform and are expanded from vertex_index, so the resident geometry needs no vertex buffer. The buffer and bind group are built once by GeoEncoder on first residence and reused every subsequent unchanged frame.

Move-only (owns GPU runtime handles). Default-constructed slots are empty; GeoEncoder::fillPathResident populates them lazily.


Class Documentation

◆ donner::geode::GeodeResidentSlot::Region

struct donner::geode::GeodeResidentSlot::Region

A byte sub-range of buffer. size == 0 is never bound directly - empty SSBO regions reserve a zero-filled dummy slot wide enough for one element of the WGSL array they feed, so the shader's band-count gate keeps them un-dereferenced and the binding still passes WebGPU's minimum-size validation (matching the per-frame arena allocStorageOrDummy dummy).

Class Members
uint64_t offset = 0
uint64_t size = 0

Constructor & Destructor Documentation

◆ GeodeResidentSlot()

donner::geode::GeodeResidentSlot::GeodeResidentSlot ( GeodeResidentSlot && other)
defaultnoexcept

Transfer slab handles, cached bindings, and CPU reservations.

Parameters
otherSlot whose resource ownership is transferred.

Member Function Documentation

◆ operator=()

GeodeResidentSlot & donner::geode::GeodeResidentSlot::operator= ( GeodeResidentSlot && other)
inlinenoexcept

Release current geometry residence and mirrors, then take ownership of another slot.

Parameters
otherSlot whose resources are moved into this one.
Returns
This slot after the transfer.

◆ reservePaintMirror()

bool donner::geode::GeodeResidentSlot::reservePaintMirror ( uint64_t bytes)
inline

Replace the cached paint's CPU-byte reservation.

Parameters
bytesNew paint mirror capacity in bytes.
Returns
False if the document budget refuses the replacement charge.

◆ reserveRecordMirror()

bool donner::geode::GeodeResidentSlot::reserveRecordMirror ( uint64_t bytes)
inline

Replace the cached record's CPU-byte reservation.

Parameters
bytesNew record mirror capacity in bytes.
Returns
False if the document budget refuses the replacement charge.

◆ reserveUniformMirror()

bool donner::geode::GeodeResidentSlot::reserveUniformMirror ( uint64_t bytes)
inline

Replace the cached uniform's CPU-byte reservation.

Parameters
bytesNew uniform mirror capacity in bytes.
Returns
False if the document budget refuses the replacement charge.

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