Donner SVG 0.8.0-pre
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)
bool reserveRecordMirror (uint64_t bytes)
bool reservePaintMirror (uint64_t bytes)
 GeodeResidentSlot (const GeodeResidentSlot &)=delete
GeodeResidentSlot & operator= (const GeodeResidentSlot &)=delete
 GeodeResidentSlot (GeodeResidentSlot &&) noexcept=default
GeodeResidentSlot & operator= (GeodeResidentSlot &&other) noexcept
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< GeodeResidentSlabslab
 Slab that owns buffer; null until residence is established. Held by shared_ptr so a device change (which swaps the registry's slab) cannot leave a slot referencing a destroyed slab: old slots keep the old slab alive until their own reset drops the reference.
uint64_t allocationOffset = 0
 Whole-slot allocation inside the slab, returned via free on reset.
uint64_t allocationSize = 0
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
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< GeodeRecordSlabrecordSlab
 Record slab that owns recordSlot; mirrors the geometry slab's device-change lifetime handling.
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. A document's ECS residence components can outlive the device that filled them and later be rendered by a second RendererGeode / GeodeDevice; WebGPU rejects a bind group or buffer from device A inside device B's render pass. When this id does not match the current device at draw time the slot is treated as non-resident and re-uploaded onto the current device (the stale handles are released without touching the old device). 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
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
uint32_t gradientStopCount = 0
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 416-byte region and keeps the cached bind group.
GeodeGeometryCacheReservation cpuMirrorReservation
uint64_t cpuUniformBytes = 0
uint64_t cpuRecordBytes = 0
uint64_t cpuPaintBytes = 0

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 wgpu 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

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