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

Drawing API for the Geode GPU renderer. More...

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

Classes

struct  ScenePaint
 Paint carried by one cross-entity batch instance: a solid colour, or a resolved gradient whose parameters and stop ramp the encoder copies into the slot's persistent paint block. More...
struct  SceneRecordState
 The record fields a batched instance takes from encoder-side state rather than from its own arguments: the paint scalars published into its slot and the clip rectangle live at the time it was appended. More...
struct  SceneBatchBinding
 One cross-entity ordered batch: consecutive resident slots of one slab chunk plus a run of consecutive record-slab slots. More...
struct  PatternPaint
 Describes a pattern tile used as a paint source for fillPathPattern. More...

Public Member Functions

 GeoEncoder (GeodeDevice &device, const GeodePipeline &fillPipeline, const GeodeGradientPipeline &gradientPipeline, const GeodeImagePipeline &imagePipeline, const gpu::Texture &target, const gpu::Extent2d &targetSize)
 Create an encoder targeting the given texture.
 GeoEncoder (GeodeDevice &device, const GeodePipeline &fillPipeline, const GeodeGradientPipeline &gradientPipeline, const GeodeImagePipeline &imagePipeline, const gpu::Texture &target, const gpu::Extent2d &targetSize, gpu::CommandEncoder &sharedCommandEncoder)
 Shared-CommandEncoder constructor.
void setBufferPool (GeodeBufferPool *pool)
 Install a cross-frame buffer pool.
void setGeometryAdmission (GeometryAdmission *admission)
 Install the mandatory geometry admission gate for renderer-owned encoders.
std::size_t patternGpuPreparationsForTesting () const
 Number of pattern sampler/view preparation attempts made by this encoder.
std::size_t pendingSceneAdmissionsForTesting () const
 Number of admitted scene instances not yet consumed by a batch draw.
void injectScenePreparationFailureAfterForTesting (std::size_t successfulPreparations)
 Fail one scene preparation after successfulPreparations successful calls.
void recordGeometryDebugInstance (const EncodedPath &encoded, std::span< const float > instanceTransforms)
 Observe Slug draws recorded by this encoder.
void setGeometryDebugSink (GeometryDebugSink *sink, const Transform2d &rootFromTarget=Transform2d())
 GeoEncoder (const GeoEncoder &)=delete
GeoEncoderoperator= (const GeoEncoder &)=delete
 GeoEncoder (GeoEncoder &&) noexcept
 Move constructor.
GeoEncoderoperator= (GeoEncoder &&) noexcept
 Move assignment operator.
void clear (const css::RGBA &color)
 Clear the target texture to the given color.
void setLoadPreserve ()
 Switch the next render pass's load op from Clear to Load, preserving whatever the target texture already contains.
void setAntialias (bool antialias)
 Enable analytic edge anti-aliasing for subsequent path and mask draws. Disabled mode emits binary coverage at the pixel center.
bool hasActiveClipState () const
 True when a clip polygon or a clip mask is active. Batchable residence and cross-entity batching are only taken with no active clip state (the cached bind groups and shared batch uniform carry zero clip flags).
uint64_t clipStateVersion () const
 Monotonic clip-state version: every scissor, clip-polygon, and clip-mask mutation bumps it. The ordered batch machinery snapshots it per batch so a batch never spans a clip change.
bool hasOpenMaskPass () const
 True while a mask pass is open, i.e. draws are being recorded into a mask texture through the mask pipeline rather than into the main pass. Residency and the ordered batch gate both exclude these draws: a batch defers to flush time, by which point the mask pass has closed and the draw would land in the wrong target.
void setTransform (const Transform2d &transform)
 Set the model-view transform for subsequent draw calls.
void setScissorRect (int32_t x, int32_t y, int32_t w, int32_t h)
 Set a scissor rectangle in target-pixel coordinates.
void clearScissorRect ()
 Remove any active scissor, restoring full-target rasterization.
void setClipPolygon (const Vector2d corners[4])
 Activate a convex 4-vertex clip polygon.
void clearClipPolygon ()
 Clear any active clip polygon, restoring unclipped rasterisation (or falling back to just the scissor rect, if one is set).
void beginMaskPass (const gpu::Texture &mask)
 Open a new render pass that writes into the given mask texture.
void fillPathIntoMask (const Path &path, FillRule rule, const EncodedPath *precomputedEncoded=nullptr)
 Fill path into the currently open mask pass using the Slug mask pipeline.
void endMaskPass ()
 Close the mask render pass opened by beginMaskPass.
void setClipMask (const gpu::TextureView &maskView)
 Bind maskView as the clip mask texture for subsequent fill / gradient draws.
void setClipMask (const gpu::Texture &maskTexture, const gpu::TextureView &maskView)
 Preferred overload: sets both the view AND the parent texture so the encoder keeps the underlying Vulkan resource alive for as long as it's bound.
void clearClipMask ()
 Remove any active clip mask, restoring unclipped rasterisation.
void blitFullTarget (const gpu::Texture &src, double opacity)
 Blit an offscreen texture across the entire target with an alpha multiplier.
void blitFullTargetMasked (const gpu::Texture &content, const gpu::Texture &mask, svg::MaskType maskType, const std::optional< Box2d > &maskBounds)
 <mask> compositing.
void blitFullTargetBlended (const gpu::Texture &layer, const gpu::Texture &dstSnapshot, uint32_t blendMode, double opacity)
 mix-blend-mode compositing.
void drawImage (const svg::ImageResource &image, const Box2d &destRect, double opacity, svg::ImageRendering imageRendering)
 Draw a raster image into the given destination rectangle.
void drawImage (const svg::ImageResource &image, const Box2d &destRect, double opacity, bool pixelated)
 Source-compatible legacy overload. New callers pass the resolved image-rendering enum.
void drawTexture (const gpu::Texture &texture, const Box2d &destRect, const Box2d &sourceUv, double opacity, bool pixelated, bool sourceIsPremultiplied)
 Draw an already-GPU-resident RGBA texture into the destination rectangle.
void fillPath (const Path &path, const css::RGBA &color, FillRule rule, const EncodedPath *precomputedEncoded=nullptr)
 Fill a path with a solid color.
void fillPathResident (GeodeResidentSlot &slot, const EncodedPath &encoded, const css::RGBA &color, FillRule rule, uint64_t frameId)
 Solid fill of a cached path with persistent GPU residence.
void fillPathInstanced (const EncodedPath &encoded, const css::RGBA &color, FillRule rule, std::span< const float > instanceTransforms)
 Fill N copies of the same encoded path at N different affine transforms, in one GPU draw call.
bool ensureResidentSceneRecord (GeodeResidentSlot &slot, const EncodedPath &encoded, const ScenePaint &paint, FillRule rule, const Transform2d &recordTransform, const GeodeRecordSlab::Slot *recordSlotOverride=nullptr, std::vector< uint8_t > *overrideRecordCache=nullptr, SceneRecordState *recordState=nullptr, bool publishPaint=true)
 Ensure a resident slot's geometry is uploaded and its instance record (record-slab slot, chunk-relative bases, transform-bearing) is current WITHOUT drawing.
void releasePreparedSceneAdmission (const EncodedPath &encoded)
 Cancel one prepared scene instance before demoting it to a different draw path.
void fillPathSceneBatch (const css::RGBA &color, FillRule rule, const SceneBatchBinding &binding)
 Record ONE GPU draw covering a cross-entity batch of resident solid fills (ordered batching).
void fillPathLinearGradient (const Path &path, const LinearGradientParams &params, FillRule rule, const EncodedPath *precomputedEncoded=nullptr)
 Fill a path with a linear gradient.
void fillPathRadialGradient (const Path &path, const RadialGradientParams &params, FillRule rule, const EncodedPath *precomputedEncoded=nullptr)
 Fill a path with a radial gradient.
void fillPathLinearGradientResident (GeodeResidentGradientSlot &slot, const EncodedPath &encoded, const LinearGradientParams &params, FillRule rule, uint64_t frameId)
 Fill a path with a linear gradient through a persistent GPU residence slot.
void fillPathRadialGradientResident (GeodeResidentGradientSlot &slot, const EncodedPath &encoded, const RadialGradientParams &params, FillRule rule, uint64_t frameId)
 Radial variant of fillPathLinearGradientResident.
void fillPathPattern (const Path &path, FillRule rule, const PatternPaint &paint, const EncodedPath *precomputedEncoded=nullptr)
 Fill a path with a repeating pattern tile.
void finish ()
 Submit all encoded commands to the GPU queue.

Detailed Description

Drawing API for the Geode GPU renderer.

GeoEncoder is a per-frame command builder. Construct one against a target texture, issue draw calls (fillPath, clear, etc.), then call finish() to submit the command buffer to the GPU.

The encoder owns no GPU buffers itself - each draw call allocates fresh vertex / band / curve / uniform buffers. This is the simplest possible implementation; later phases will add buffer pooling and the ECS-backed GeodePathCacheComponent for paths whose geometry hasn't changed.

Typical usage:

GeoEncoder encoder(device, pipeline, targetTexture);
encoder.clear(css::RGBA::White);
encoder.setTransform(Transform2d::Scale(2.0));
encoder.fillPath(myPath, css::RGBA::Red, FillRule::NonZero);
encoder.finish();

Class Documentation

◆ donner::geode::GeoEncoder::SceneRecordState

struct donner::geode::GeoEncoder::SceneRecordState

The record fields a batched instance takes from encoder-side state rather than from its own arguments: the paint scalars published into its slot and the clip rectangle live at the time it was appended.

A batch re-derives every instance's record when it flushes, which can be arbitrarily far from the append: other draws of the same entity, and other clip changes, can happen in between. Reading these back off the slot or off the encoder at that point reads the LATEST state, not the appended one. The caller therefore captures them at append and hands the same values back at flush, which is what makes the re-derivation reproduce byte-identical bytes.

Class Members
float clipRect[4] = {0.0f, 0.0f, 0.0f, 0.0f}
uint32_t clipRectActive = 0
uint32_t gradientSpread = 0
uint32_t gradientStopCount = 0
uint32_t paintMode = 0

◆ donner::geode::GeoEncoder::SceneBatchBinding

struct donner::geode::GeoEncoder::SceneBatchBinding

One cross-entity ordered batch: consecutive resident slots of one slab chunk plus a run of consecutive record-slab slots.

Class Members
BufferRef chunkBuffer Slab chunk holding every instance's geometry.
uint64_t chunkBufferId = 0
uint64_t chunkBytes = 0 Byte size of chunkBuffer; scene batches bind the whole chunk.
uint64_t firstRecordOffset = 0 BYTE offset of the first instance's record inside recordBuffer. Record-slot indices are global across slab chunks, so an index is not a byte offset once the slab has grown; the caller passes the first slot's own buffer-relative offset instead.
uint32_t instanceCount = 1
BufferRef recordBuffer Record-slab buffer holding the records. Stable identities of chunkBuffer / recordBuffer (see GeodeDevice::AllocateBufferId). The bind-group cache outlives the document that owns these buffers, so it keys on these ids; the raw handle addresses are recycled once that document is destroyed.
uint64_t recordBufferId = 0
GeodeRecordSlab * recordSlab = nullptr
uint32_t vertexCount = 0 Max fan vertex count over the instances. Record slab the instances' records live in. Supplies the persistent batch-uniform buffer so a steady frame writes nothing; null falls back to the encoder's per-frame uniform arena.

◆ donner::geode::GeoEncoder::PatternPaint

struct donner::geode::GeoEncoder::PatternPaint

Describes a pattern tile used as a paint source for fillPathPattern.

The tile texture is expected to contain pre-rendered pattern content in premultiplied RGBA. The Slug fill shader samples it with the Repeat wrap mode (equivalent to SVG <pattern> default behaviour) using the provided transform to map path-space positions into tile-space.

Class Members
double opacity = 1.0 Multiplicative alpha applied to the sampled tile color. Usually fill-opacity * opacity.
Transform2d patternFromPath Transform from path space (where the path being filled lives) to pattern tile space. Typically inverse(targetFromPattern) composed with the current encoder transform - the RendererGeode layer builds the right composition.
const Texture * tile = nullptr Pre-rendered tile texture (RGBA8, premultiplied).
Vector2d tileSize Size of the tile rectangle in pattern space (width, height). The shader uses this to wrap sample positions via fract().

Constructor & Destructor Documentation

◆ GeoEncoder() [1/2]

donner::geode::GeoEncoder::GeoEncoder ( GeodeDevice & device,
const GeodePipeline & fillPipeline,
const GeodeGradientPipeline & gradientPipeline,
const GeodeImagePipeline & imagePipeline,
const gpu::Texture & target,
const gpu::Extent2d & targetSize )

Create an encoder targeting the given texture.

Parameters
deviceThe Geode device owning the shared pipelines and counters.
fillPipelineThe Slug fill pipeline.
gradientPipelineThe Slug gradient-fill pipeline.
imagePipelineThe image-blit pipeline.
targetSingle-sample render target. Usage must include RenderAttachment; add TextureBinding or CopySrc when callers sample or read it after rendering. The texture must outlive finish().

◆ GeoEncoder() [2/2]

donner::geode::GeoEncoder::GeoEncoder ( GeodeDevice & device,
const GeodePipeline & fillPipeline,
const GeodeGradientPipeline & gradientPipeline,
const GeodeImagePipeline & imagePipeline,
const gpu::Texture & target,
const gpu::Extent2d & targetSize,
gpu::CommandEncoder & sharedCommandEncoder )

Shared-CommandEncoder constructor.

Uses the provided sharedCommandEncoder instead of creating its own. When this overload is used, finish() only ends any open render pass - it does NOT finish the CommandEncoder or submit to the queue. The caller (typically RendererGeode) owns the lifetime of the shared encoder and is responsible for calling sharedCommandEncoder.finish() + queue.submit() exactly once at the end of the frame.

Enables push/pop of isolated layers / filter layers / mask layers without forcing a queue submit per layer boundary - the whole frame's render passes batch into a single command buffer.

Member Function Documentation

◆ beginMaskPass()

void donner::geode::GeoEncoder::beginMaskPass ( const gpu::Texture & mask)

Open a new render pass that writes into the given mask texture.

Used by RendererGeode::pushClip to materialise a path-based clip into an RGBA8Unorm coverage texture that subsequent fill/gradient draws can sample.

The main render pass, if open, is closed first. Subsequent fillPathIntoMask calls add paths to the mask via the Slug mask pipeline. endMaskPass closes the mask pass and re-opens the main pass (with LoadOp::Load) when the next draw lands.

Parameters
maskSingle-sample RGBA8Unorm target. Sampled by setClipMask after endMaskPass.

◆ blitFullTarget()

void donner::geode::GeoEncoder::blitFullTarget ( const gpu::Texture & src,
double opacity )

Blit an offscreen texture across the entire target with an alpha multiplier.

Used by RendererGeode::popIsolatedLayer to composite a sub-layer's content back onto the outer target. The source texture must be the SAME SIZE as this encoder's target - the blit takes the full texture and maps it 1:1 onto the full target. The current setTransform does NOT affect the blit (it's a device-pixel-space operation, not a model-space draw).

Parameters
srcSource texture (RGBA8, premultiplied).
opacityOverall alpha multiplier in [0, 1].

◆ blitFullTargetBlended()

void donner::geode::GeoEncoder::blitFullTargetBlended ( const gpu::Texture & layer,
const gpu::Texture & dstSnapshot,
uint32_t blendMode,
double opacity )

mix-blend-mode compositing.

Blits layer across the entire target using one of the 16 W3C Compositing Level 1 blend formulas, reading the backdrop from dstSnapshot (which the caller has already copied from the parent target because the shader cannot read the render pass's own color attachment).

Both textures must be the SAME SIZE as this encoder's target and already stored in premultiplied alpha. The encoder's pass must be in a LoadOp::Clear state - the blend shader writes the final pixel directly and relies on the render target being zeroed before the draw.

Parameters
layerOffscreen RGBA8 layer texture (premultiplied).
dstSnapshotFrozen copy of the parent target's current state (premultiplied) - the blend's backdrop.
blendModeValue in 1..=16 matching the donner::svg::MixBlendMode enumeration. A value of 0 silently falls through to no-op.
opacityGroup opacity in [0, 1]. Applied to the layer BEFORE the blend formula so an opacity + mix-blend-mode combo on the same element composes correctly - the source colour that enters the blend is layer * opacity.

◆ blitFullTargetMasked()

void donner::geode::GeoEncoder::blitFullTargetMasked ( const gpu::Texture & content,
const gpu::Texture & mask,
svg::MaskType maskType,
const std::optional< Box2d > & maskBounds )

<mask> compositing.

Same as blitFullTarget but additionally samples a mask texture and derives coverage according to maskType. When maskBounds is provided, pixels outside the rect are discarded so the <mask> element's x/y/width/height are honoured.

Parameters
contentOffscreen RGBA8 content texture, premultiplied, same size as this encoder's target.
maskOffscreen RGBA8 mask texture, premultiplied, same size as content.
maskTypeWhether mask coverage comes from luminance or alpha.
maskBoundsOptional clip rect in target-pixel space.

◆ clear()

void donner::geode::GeoEncoder::clear ( const css::RGBA & color)

Clear the target texture to the given color.

Must be called before any draw calls - clear is implemented as the load op of the first render pass, so calling it after a draw is a no-op. Subsequent calls override the previous clear color.

◆ drawImage()

void donner::geode::GeoEncoder::drawImage ( const svg::ImageResource & image,
const Box2d & destRect,
double opacity,
svg::ImageRendering imageRendering )

Draw a raster image into the given destination rectangle.

The image's straight-alpha RGBA8 pixels are uploaded to a fresh GPU texture and sampled through the image-blit pipeline. The current transform is applied via the MVP matrix, and the destination rectangle is specified in local (pre-transform) coordinates - i.e., the transform and the rect compose the same way as any other draw call against this encoder.

Parameters
imageDecoded RGBA8 image resource. No-op if empty or zero-size.
destRectDestination rectangle in local (pre-transform) space.
opacityOverall opacity in [0, 1], combined with the sampled texel's alpha in the fragment shader.
imageRenderingResolved smooth, crisp, or two-stage pixelated sampling policy.

◆ drawTexture()

void donner::geode::GeoEncoder::drawTexture ( const gpu::Texture & texture,
const Box2d & destRect,
const Box2d & sourceUv,
double opacity,
bool pixelated,
bool sourceIsPremultiplied )

Draw an already-GPU-resident RGBA texture into the destination rectangle.

The current transform is applied exactly like drawImage, but the texture is sampled directly without a CPU upload.

Parameters
textureGPU-resident RGBA texture.
destRectDestination rectangle in local (pre-transform) space.
sourceUvSource UV rectangle in [0,1] x [0,1]. Producers that keep an oversized backing allocation pass the sub-rect that holds the valid content.
opacityOverall opacity in [0, 1].
pixelatedIf true, use nearest-neighbor filtering. Otherwise, bilinear.
sourceIsPremultipliedTrue when the texels are premultiplied, as Geode render-target snapshots are. CPU bitmaps uploaded by host presentation code are straight-alpha and must pass false.

◆ ensureResidentSceneRecord()

bool donner::geode::GeoEncoder::ensureResidentSceneRecord ( GeodeResidentSlot & slot,
const EncodedPath & encoded,
const ScenePaint & paint,
FillRule rule,
const Transform2d & recordTransform,
const GeodeRecordSlab::Slot * recordSlotOverride = nullptr,
std::vector< uint8_t > * overrideRecordCache = nullptr,
SceneRecordState * recordState = nullptr,
bool publishPaint = true )

Ensure a resident slot's geometry is uploaded and its instance record (record-slab slot, chunk-relative bases, transform-bearing) is current WITHOUT drawing.

Used by the cross-entity ordered-batch path, which draws many slots in one GPU call; solo draws call fillPathResident instead, which performs the same work and then records the draw.

Parameters
slotResident slot (geometry + record slab wiring installed by the renderer).
encodedPrecomputed EncodedPath shared with the cache.
colorSolid fill color (NOT premultiplied).
ruleFill rule.
recordTransformThe full deviceFromLocal transform to bake into the record (the batch uniform is orthographic-only).
recordSlotOverrideWhen non-null, write the record into this slot instead of the entity's primary slot (same-frame repeat draws need one record per draw, and per-occurrence text records live outside the shared glyph slot entirely).
overrideRecordCacheOptional caller-owned copy of the override slot's last contents. Supplying it turns the override write into the same skip-when-unchanged write the primary record gets, which is what lets a persistent per-occurrence record reach a zero-write steady state. Null means the override slot is per-frame scratch and is always written. Ignored when recordSlotOverride is null.
recordStateCarries the record fields that come from encoder-side state. When publishPaint is true this is an OUT parameter: paint is published into the slot and the resulting scalars, plus the live clip rectangle, are written here. When it is false this is an IN parameter: the record takes these exact values and neither the slot's paint nor the encoder's current clip is consulted. Null on either side falls back to the slot's and the encoder's current state.
publishPaintTrue to publish paint into the slot's paint block and paint scalars; false to replay recordState instead. A batch's flush-time re-ensure passes false, because by then the slot's paint may belong to a later draw and the encoder's clip may have moved on.
Returns
True when the slot is resident and current.

◆ fillPath()

void donner::geode::GeoEncoder::fillPath ( const Path & path,
const css::RGBA & color,
FillRule rule,
const EncodedPath * precomputedEncoded = nullptr )

Fill a path with a solid color.

The path is encoded into Slug band data on the CPU, uploaded to GPU buffers, and a draw call is recorded. The fill is applied with the current transform.

Parameters
pathThe path to fill.
colorSolid fill color (NOT premultiplied - the encoder handles premultiplication for the blend pipeline).
ruleFill rule (NonZero or EvenOdd).
precomputedEncodedOptional cache-hit payload - see GeodePathCacheComponent. When non-null, skips encode + counter bump.

◆ fillPathInstanced()

void donner::geode::GeoEncoder::fillPathInstanced ( const EncodedPath & encoded,
const css::RGBA & color,
FillRule rule,
std::span< const float > instanceTransforms )

Fill N copies of the same encoded path at N different affine transforms, in one GPU draw call.

The caller has already packed each transform into the wire format the shader expects: two vec4f rows per instance (row-major affine, 32 bytes per entry). See donner/svg/renderer/geode/shaders/slug_fill.wgsl struct InstanceTransform for the exact layout.

The vertex shader composes each instance's transform with the currently-bound uniforms.mvp, so encoder.setTransform(...) still applies an outer world transform; per-instance data is the delta relative to that. Pass Transform2d::Identity to setTransform if instance transforms already encode the full path→clip-space mapping (the common case for <use> batching, where each instance's transform is the full worldFromEntity).

If instanceTransforms is empty the call is a no-op. If instanceTransforms.size() == 1 this is equivalent to a single fillPath with the given transform folded in - the caller can still prefer it when bouncing through the batcher.

Parameters
encodedPrecomputed EncodedPath shared across all instances. Required (non-null) - there's no "encode inline" path here; the whole point is to amortize one encode across many draws.
colorSolid fill color (NOT premultiplied).
ruleFill rule.
instanceTransformsSpan of {row0, row1} vec4f pairs, two consecutive vec4f per instance (32 bytes each). The span must contain exactly 8 * instanceCount floats.

◆ fillPathIntoMask()

void donner::geode::GeoEncoder::fillPathIntoMask ( const Path & path,
FillRule rule,
const EncodedPath * precomputedEncoded = nullptr )

Fill path into the currently open mask pass using the Slug mask pipeline.

Must be called between beginMaskPass and endMaskPass. The current encoder transform applies (so clip paths use the same device-pixel mapping as the content being clipped).

Parameters
precomputedEncodedOptional cache-hit payload. When non-null, the encoder skips GeodePathEncoder::encode and the pathEncodes counter bump. Used by RendererGeode to plumb a cached GeodePathCacheComponent::strokeSlot result.

◆ fillPathLinearGradient()

void donner::geode::GeoEncoder::fillPathLinearGradient ( const Path & path,
const LinearGradientParams & params,
FillRule rule,
const EncodedPath * precomputedEncoded = nullptr )

Fill a path with a linear gradient.

Same CPU-side Slug band encoding as fillPath, but the shading stage uses the linear-gradient pipeline - each pixel inside the path is colored by sampling the stop list at a per-pixel parameter t computed from params.gradientFromPath, params.startGrad, and params.endGrad, then folded through params.spreadMode.

If the path encodes to zero bands or the stop list is empty, the call is a no-op.

Parameters
pathThe path to fill.
paramsLinear gradient parameters. Colors are straight alpha in 0..1 per channel; the encoder premultiplies before upload. Up to 16 stops are honored; excess are silently truncated with a one-shot verbose warning at the call site in RendererGeode.
ruleFill rule (NonZero or EvenOdd).

◆ fillPathLinearGradientResident()

void donner::geode::GeoEncoder::fillPathLinearGradientResident ( GeodeResidentGradientSlot & slot,
const EncodedPath & encoded,
const LinearGradientParams & params,
FillRule rule,
uint64_t frameId )

Fill a path with a linear gradient through a persistent GPU residence slot.

The slot's combined buffer holds the encoded band/curve/grid data and the 672-byte gradient uniform block; on an unchanged frame the draw rewrites nothing and reuses the cached 11-binding bind group. Falls back to the per-frame arena path internally when a clip mask, clip polygon, or mask pass is active (the cached bind group binds dummy clip-mask resources, which is only stable when no clip is active).

Parameters
slotResident gradient slot for this entity's fill.
encodedPrecomputed encode from the cached-path encode cache.
paramsResolved linear gradient parameters.
ruleFill rule (NonZero or EvenOdd).
frameIdCurrent frame index (drives the once-per-frame gate).

◆ fillPathPattern()

void donner::geode::GeoEncoder::fillPathPattern ( const Path & path,
FillRule rule,
const PatternPaint & paint,
const EncodedPath * precomputedEncoded = nullptr )

Fill a path with a repeating pattern tile.

The pattern texture must have been rendered earlier (e.g., by a nested GeoEncoder) and contains premultiplied RGBA. The shader applies the Slug winding-number coverage test identically to fillPath, and samples the tile for pixels inside the path.

◆ fillPathRadialGradient()

void donner::geode::GeoEncoder::fillPathRadialGradient ( const Path & path,
const RadialGradientParams & params,
FillRule rule,
const EncodedPath * precomputedEncoded = nullptr )

Fill a path with a radial gradient.

Same CPU encoding and GPU-dispatch machinery as fillPathLinearGradient, but the gradient parameter t is derived from a two-circle radial construction in the shader (see radial_t() in shaders/slug_gradient.wgsl).

If the path encodes to zero bands, the stop list is empty, or params.radius <= 0, the call is a no-op.

Parameters
pathThe path to fill.
paramsRadial gradient parameters (center + radius, optional focal point + radius, shared transform and stops).
ruleFill rule (NonZero or EvenOdd).

◆ fillPathRadialGradientResident()

void donner::geode::GeoEncoder::fillPathRadialGradientResident ( GeodeResidentGradientSlot & slot,
const EncodedPath & encoded,
const RadialGradientParams & params,
FillRule rule,
uint64_t frameId )

Radial variant of fillPathLinearGradientResident.

Same residence contract and arena fallback.

◆ fillPathResident()

void donner::geode::GeoEncoder::fillPathResident ( GeodeResidentSlot & slot,
const EncodedPath & encoded,
const css::RGBA & color,
FillRule rule,
uint64_t frameId )

Solid fill of a cached path with persistent GPU residence.

slot is a per-entity GeodeResidentSlot (owned by GeodeResidentPathComponent, invalidated by the same ComputedPathComponent listener that clears the CPU encode cache). On first use the encoder uploads encoded into a persistent combined Vertex|Storage|Uniform buffer and builds a cached bind group; on every subsequent unchanged frame it re-uses both and writes zero geometry bytes. Only the 288-byte per-draw uniform is rewritten, and only when it actually changed (camera/color move), so a static document's steady-state frame writes ~zero bytes and creates zero bind groups.

Residency is taken ONLY for the fast, cacheable case: no active clip mask, no clip polygon, no open mask pass. When any of those hold the call transparently falls back to the per-frame arena path (a fresh per-draw bind group) so clipped / masked draws stay bit-exact.

Parameters
slotPersistent residence for this entity's fill or stroke encode. Must outlive the frame's submit (it does: the ECS component is only removed on geometry change, after the prior frame submitted).
encodedCached encode (stable across frames). Must be non-empty for a draw to land.
colorSolid fill color (NOT premultiplied - premultiplied here, identically to fillPath).
ruleFill rule.
frameIdMonotonic frame index. A slot serves at most one resident draw per frame (its single uniform buffer cannot hold distinct per-instance uniforms); repeat draws in the same frame fall back to the arena path.

◆ fillPathSceneBatch()

void donner::geode::GeoEncoder::fillPathSceneBatch ( const css::RGBA & color,
FillRule rule,
const SceneBatchBinding & binding )

Record ONE GPU draw covering a cross-entity batch of resident solid fills (ordered batching).

The caller has already ensured each instance's record via ensureResidentSceneRecord. The bind group binds the whole slab chunk for every geometry class (the records carry chunk-relative element bases) and the record span for binding 7. The draw issues firstInstance = binding.firstInstance and the maximum fan vertex count; the vertex shader folds extra triangles of smaller instances into a degenerate position.

The encoder transform must be identity when this is called (the batch uniform carries the orthographic mapping only).

Parameters
colorSolid fill color shared by every instance.
ruleFill rule shared by every instance.
bindingBatch binding (chunk + record span + counts).

◆ finish()

void donner::geode::GeoEncoder::finish ( )

Submit all encoded commands to the GPU queue.

After this call, the encoder is in a "finished" state and no further draws can be issued. The caller is responsible for any synchronization (e.g., MapAsync + Tick loop) needed to actually use the rendered output.

◆ recordGeometryDebugInstance()

void donner::geode::GeoEncoder::recordGeometryDebugInstance ( const EncodedPath & encoded,
std::span< const float > instanceTransforms )

Observe Slug draws recorded by this encoder.

rootFromTarget maps this encoder's target pixels to the owning renderer's final target. Pass null to disable observation. The default path stores one pointer and one branch per actual Slug submission. Record one scene-batch instance's geometry into the debug-overlay sink (no-op without a sink). Ordered batches issue a single GPU draw, so the caller reports each batched instance here in paint order, passing the instance's transform in the same packed 8-float wire format instanced draws use. The encoder transform must already be identity, matching the batch draw's uniform.

◆ setAntialias()

void donner::geode::GeoEncoder::setAntialias ( bool antialias)

Enable analytic edge anti-aliasing for subsequent path and mask draws. Disabled mode emits binary coverage at the pixel center.

Parameters
antialiasTrue to retain analytic edge coverage.

◆ setBufferPool()

void donner::geode::GeoEncoder::setBufferPool ( GeodeBufferPool * pool)

Install a cross-frame buffer pool.

When set, arena buffer growth prefers recycled buffers from the pool and the destructor returns the fully-grown arena buffers to it instead of destroying them, driving steady-state per-frame bufferCreates toward zero.

Call before the first draw. The pool (typically owned by RendererGeode::Impl) must outlive this encoder. Pass nullptr to disable (default).

◆ setClipMask() [1/2]

void donner::geode::GeoEncoder::setClipMask ( const gpu::Texture & maskTexture,
const gpu::TextureView & maskView )

Preferred overload: sets both the view AND the parent texture so the encoder keeps the underlying Vulkan resource alive for as long as it's bound.

The 1-arg overload is kept only for call sites that guarantee the parent's lifetime by other means.

See the activeClipMaskTexture field comment (and issue #551) for the bug this addresses - without the parent keepalive, popping the clip stack can free a VkImage while the encoder's createBindGroup still references its view.

◆ setClipMask() [2/2]

void donner::geode::GeoEncoder::setClipMask ( const gpu::TextureView & maskView)

Bind maskView as the clip mask texture for subsequent fill / gradient draws.

The view must reference a 1-sample RGBA8Unorm texture the same size as the encoder's target - typically the resolve texture produced by beginMaskPass + endMaskPass.

The shader samples .r at the pixel center and multiplies it into fragment coverage, so the mask represents a pre-rendered clip region in [0, 1].

◆ setClipPolygon()

void donner::geode::GeoEncoder::setClipPolygon ( const Vector2d corners[4])

Activate a convex 4-vertex clip polygon.

Unlike setScissorRect, this clips to the exact parallelogram described by the 4 corners - used for <symbol> / <svg> / <use> viewports that have a non-axis-aligned ancestor transform where WebGPU's rectangular scissor can only express the AABB of the transformed rect, not the true polygon. The fragment shader tests each of 4 edge half-planes at the fragment position and discards fragments outside the polygon.

Parameters
corners4 polygon vertices in target-pixel space, given in consistent (clockwise OR counter-clockwise) winding order. The encoder normalises edge normals so a fragment strictly INSIDE the polygon satisfies every half-plane test.

◆ setLoadPreserve()

void donner::geode::GeoEncoder::setLoadPreserve ( )

Switch the next render pass's load op from Clear to Load, preserving whatever the target texture already contains.

Useful when the encoder is being reused to append draws on top of previously submitted content (e.g., resuming outer-frame drawing after a nested pattern-tile pass).

Must be called before any draws - once a render pass is open it's too late to change its load op.

◆ setScissorRect()

void donner::geode::GeoEncoder::setScissorRect ( int32_t x,
int32_t y,
int32_t w,
int32_t h )

Set a scissor rectangle in target-pixel coordinates.

Subsequent draws are clipped to the intersection of (0,0,targetWidth,targetHeight) and this rectangle. Used by RendererGeode::pushClip to implement SVG viewport rect clipping (nested <svg> clip, overflow: hidden, etc.).

The scissor persists across setTransform, fillPath, and friends until explicitly cleared via clearScissorRect.

Negative x/y and widths/heights that extend past the target are clamped internally; the caller can pass any AABB in pixel space without bounds-checking.


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