cheatah
Module

plot::renderer

cheatah-plot v0.1.0-alpha — Biome Standard 0.6.3-alpha

Classes

Concepts

Functions

fn TileBins bin_prims(const std::vector< Prim > &prims, std::uint32_t width, std::uint32_t height) #

Bucket prims into the tile grid covering a width×height framebuffer.

Two passes over the primitive list (count, then fill) build the CSR layout with exactly-sized vectors; inside each tile the indices ascend, preserving paint order.

Parameters
prims

The primitive list, in paint order.

width

The framebuffer width in pixels (>= 1).

height

The framebuffer height in pixels (>= 1).

Returns

The per-tile index lists.

Complexity

O(prims · tiles-they-touch).

Allocation

the two returned vectors.

Unit testplot:binning
fn void push_seg(DrawList &dl, float x0, float y0, float x1, float y1, float half_width, std::uint32_t rgba, float dash_on=0.0f, float dash_off=0.0f) #

Append a stroked segment.

Parameters
dl

The list to append to.

x0

Start x (pixels).

y0

Start y.

x1

End x.

y1

End y.

half_width

Half the stroke width in pixels (>= 0.5 for a hairline).

rgba

The packed colour.

dash_on

Dash drawn-length in pixels (0 = solid).

dash_off

Dash gap-length in pixels.

Complexity

O(1) amortized.

Allocation

amortized vector growth.

Unit testplot:drawlist
fn void push_disc(DrawList &dl, float cx, float cy, float radius, std::uint32_t rgba) #

Append a filled disc (scatter/stem markers).

Parameters
dl

The list to append to.

cx

Center x (pixels).

cy

Center y.

radius

The disc radius in pixels.

rgba

The packed colour.

Complexity

O(1) amortized.

Allocation

amortized vector growth.

Unit testplot:drawlist
fn void push_rect(DrawList &dl, float x0, float y0, float x1, float y1, std::uint32_t rgba, float outline_half_width=0.0f) #

Append an axis-aligned rectangle — filled, or an outline when outline_half_width > 0 (bars, heatmap cells, legend swatches, square markers, gridline boxes).

Parameters
dl

The list to append to.

x0

Left.

y0

Top.

x1

Right.

y1

Bottom (x0<x1, y0<y1).

rgba

The packed colour.

outline_half_width

0 for a filled rect; else half the outline stroke width.

Complexity

O(1) amortized.

Allocation

amortized vector growth.

Unit testplot:drawlist
fn void push_tri(DrawList &dl, float x0, float y0, float x1, float y1, float x2, float y2, std::uint32_t rgba) #

Append a filled triangle (area fills are fan-triangulated into these).

Parameters
dl

The list to append to.

x0

Vertex 0 x.

y0

Vertex 0 y.

x1

Vertex 1 x.

y1

Vertex 1 y.

x2

Vertex 2 x.

y2

Vertex 2 y.

rgba

The packed colour.

Complexity

O(1) amortized.

Allocation

amortized vector growth.

Unit testplot:drawlist
fn void push_glyph(DrawList &dl, float x, float y, char c, std::uint32_t rgba) #

Append one 8×16 glyph at a pixel position — the glyph's bitmap rides IN the prim's aux lanes (4 bits-rows per lane), so the kernel needs no font atlas.

Parameters
dl

The list to append to.

x

Left edge (pixels).

y

Top edge.

c

The character (the font substitutes '?' outside printable ASCII).

rgba

The packed colour.

Complexity

O(1) amortized.

Allocation

amortized vector growth.

Unit testplot:drawlist
fn void push_text(DrawList &dl, float x, float y, const std::string &text, std::uint32_t rgba) #

Append a text run, left-aligned at (x, y) top-left, one glyph prim per character.

Parameters
dl

The list to append to.

x

Left edge of the first glyph (pixels).

y

Top edge.

text

The characters to draw.

rgba

The packed colour.

Complexity

O(len).

Allocation

amortized vector growth (len prims).

Unit testplot:drawlist
fn const std::array< std::uint8_t, 16 > & glyph(char c) #

The 8×16 bitmap for character c — 16 rows top to bottom, one byte per row, bit 7 = leftmost pixel of the cell (matching the glyph prim's row packing in kernels.hpp).

Characters outside printable ASCII 32..126 (including negative char values) return the glyph for '?', so text drawing never branches on validity.

Parameters
c

The character to look up.

Returns

The glyph's 16 row bytes (a reference into the compile-time font table).

Complexity

O(1).

Allocation

none.

Unit testplot:font
fn int text_width(const std::string &s) #

The pixel width of s drawn in this font — the font is strictly monospace, so this is pure arithmetic on the length: kGlyphWidth * len.

The layout passes (tick-label centring, legend sizing) call this instead of measuring glyphs.

Parameters
s

The text to measure.

Returns

The width in pixels of the rendered run (0 for the empty string).

Complexity

O(1) — size() is constant time; no glyph is touched.

Allocation

none.

Unit testplot:font
fn bool gpu_available() noexcept #

Whether the default GPU lane can come up on this machine — a cached one-shot probe that NEVER throws.

This is the runtime "is there a GPU?" question: render() gates its GPU try on it instead of hand-rolling a try/catch around a first dispatch.

Returns

true when the default lane's context is (or can be) live; false when bring-up failed.

Complexity

O(1) after the first call (the probe result is cached).

Allocation

none after the first call. @gpualloc the lane's bring-up, once, on success.

Unit testplot:gpu_raster
fn std::uint32_t pack_rgba(double r, double g, double b, double a) #

Pack an RGBA colour (channels 0..1) into the kernel's byte order (r | g<<8 | b<<16 | a<<24), clamping each channel — the ONE quantization point between the float model layers and the integer raster.

Parameters
r

Red in [0, 1].

g

Green in [0, 1].

b

Blue in [0, 1].

a

Alpha in [0, 1].

Returns

The packed RGBA8 value.

Complexity

O(1).

Allocation

none.

Unit testplot:raster
fn std::vector< std::uint8_t > encode_png(const Image &img) #

Encode img as a complete PNG byte stream: the 8-byte signature; IHDR declaring 8-bit RGBA (colour type 6, no interlace); one IDAT whose zlib stream (header 0x78 0x01) carries the filtered pixel data as STORED deflate blocks of at most 65535 bytes each, followed by the Adler-32 of that raw data; then IEND.

Every scanline is prefixed with filter byte 0 (None), so the raw stream is exactly height * (1 + width * 4) bytes and any conforming PNG reader reproduces the input pixels bit for bit.

Parameters
img

The image to encode; img.rgba.size() must equal width * height * 4.

Returns

The PNG file bytes, ready to write to disk or stream to a viewer.

Parameters
std::runtime_error

when the pixel buffer size does not match the dimensions.

Complexity

O(width × height).

Allocation

the returned vector plus one transient filtered-scanline buffer of the same order.

Unit testplot:png
fn void save_png(const Image &img, const std::string &path) #

Encode img and write the PNG to path in binary mode — the renderer's standard save.

Parameters
img

The image to write; img.rgba.size() must equal width * height * 4.

path

The destination file path; its parent directory must already exist.

Parameters
std::runtime_error

when the pixel buffer size is wrong, the file cannot be opened, or a write fails.

Complexity

O(width × height).

Allocation

the transient encoded byte stream.

Unit testplot:png
fn void save_ppm(const Image &img, const std::string &path) #

Write img to path as a binary P6 PPM (24-bit RGB; the alpha channel is dropped) — the fallback format for tooling that predates PNG support, and a handy raw-bytes debug tap.

Parameters
img

The image to write; img.rgba.size() must equal width * height * 4.

path

The destination file path; its parent directory must already exist.

Parameters
std::runtime_error

when the pixel buffer size is wrong, the file cannot be opened, or a write fails.

Complexity

O(width × height).

Allocation

one transient RGB row buffer.

Unit testplot:png
fn std::vector< std::uint32_t > raster_cpu(const std::vector< Prim > &prims, const TileBins &bins, const RasterParams &params) #

Rasterize a binned draw list into an RGBA8 framebuffer (one uint32 per pixel, row-major) — the reference implementation of plot_clear + plot_raster.

Every pixel starts at the clear colour, then blends its tile's primitives in paint order with the integer src-over — the same loop the kernels run, one thread per pixel.

Parameters
prims

The draw list, in paint order.

bins

The tile bins for prims (from bin_prims, same width/height).

params

The framebuffer size, tile stride, and clear colour.

Returns

The framebuffer, params.width*params.height packed pixels.

Complexity

O(pixels + Σ per-tile prim work).

Allocation

the returned framebuffer.

Unit testplot:raster
fn DrawList reduce(cheatah::figure::Figure &fig, std::uint32_t width, std::uint32_t height) #

Reduce a Figure to the primitive list a rasterizer draws — layout, axes, ticks + labels, grid, every mark kind, and per-subplot legends, in paint order.

Parameters
fig

The figure model (subplots, axes, series, palette).

width

The framebuffer width in pixels.

height

The framebuffer height in pixels.

Returns

The draw list, ready for bin_prims + raster_cpu (or the GPU kernels).

Complexity

O(total data points + ticks + glyphs).

Allocation

the returned list (plus transient tick arrays).

Unit testplot:reduce
fn Image render(cheatah::figure::Figure &fig) #

Render a figure to RGBA8 pixels at the figure's own size — the readback form (the stream frame, the test surface, the encoder input).

A GPU-enabled build TRIES the default GPU lane first when gpu_available reports one and the environment does not say CHEATAH_PLOT_FORCE_CPU=1; any device failure falls back to raster_cpu with a one-time stderr notice, and further renders stay on the CPU. The two rasterizers share the reduce, the bins and the quantization, so the choice never changes what the figure MEANS — only which silicon fills the pixels.

Parameters
fig

The figure model to draw.

Returns

The rendered image (width/height from the figure, row-major RGBA).

Complexity

O(pixels + data); single-threaded by design.

Allocation

the returned image + the transient draw list, bins, and framebuffer. @gpualloc on the GPU path, the five transient buffers of raster_gpu.

Unit testplot:render
fn void save(cheatah::figure::Figure &fig, const std::string &path) #

Render a figure and write it to path as a PNG — the one-call "give me my plot" form.

Parameters
fig

The figure model to draw.

path

The output file path (.png).

Complexity

O(pixels + data).

Allocation

transient render buffers + the encoded byte stream.

Unit testplot:render
fn std::vector< std::uint32_t > raster_gpu(Ctx &ctx, const std::vector< Prim > &prims, const TileBins &bins, const RasterParams &params) #

Rasterize a binned draw list through the plot kernels on context ctx — the device mirror of raster_cpu: upload prims/offsets/indices/params, dispatch plot_clear then plot_raster (one thread per pixel), download the framebuffer.

Template parameters
Ctx

The device context lane (see RasterContext).

Parameters
ctx

The live context to dispatch on (see detail::ctx_of).

prims

The draw list, in paint order.

bins

The tile bins for prims (from bin_prims, same width/height).

params

The framebuffer size, tile stride, and clear colour.

Returns

The framebuffer, params.width*params.height packed pixels.

Complexity

O(pixels + Σ per-tile prim work) device-side; O(prims + tiles) transfer.

Allocation

the returned framebuffer. @gpualloc five transient device buffers (prims, offsets, indices, framebuffer, params), released before returning — also on the throw path.

Unit testplot:gpu_raster
fn Image render_gpu(cheatah::figure::Figure &fig) #

Render a figure to RGBA8 pixels on the default GPU lane — the device mirror of render: same reduce, same bins, same packed-pixel unpack; only the rasterizer differs.

Unlike render this does NOT fall back: a dead lane or missing kernel binary throws, so a caller that asked for the GPU explicitly hears exactly why it could not have it.

Parameters
fig

The figure model to draw.

Returns

The rendered image (width/height from the figure, row-major RGBA).

Complexity

O(pixels + data); single dispatch pair, blocking.

Allocation

the returned image + the transient draw list, bins, and framebuffer. @gpualloc the five transient buffers of raster_gpu (plus one-time lane bring-up).

Unit testplot:gpu_raster
fn bool try_gpu(const std::vector< Prim > &prims, const TileBins &bins, const RasterParams &params, std::vector< std::uint32_t > &out_fb) #

Attempt the default GPU lane for one raster: honours CHEATAH_PLOT_FORCE_CPU=1, the cached gpu_available probe, and a process-wide failure latch — the FIRST device failure prints a one-time stderr notice and every later render goes straight to the CPU reference (retrying a broken lane per frame would re-fail and re-allocate forever).

Parameters
prims

The draw list, in paint order.

bins

The tile bins for prims.

params

The framebuffer size, tile stride, and clear colour.

out_fb

Receives the device framebuffer on success; untouched on refusal/failure.

Returns

true when the GPU produced out_fb; false to take the CPU path.

Complexity

O(pixels + per-tile prim work) on the device.

Allocation

the returned framebuffer vector on success. @gpualloc the five transient buffers of raster_gpu, released either way.

Unit testplot:gpu

Constants & variables

var std::uint32_t kLocal2d #

Threads per workgroup axis of BOTH kernels — matches [numthreads(16, 16, 1)] in shaders/plot.slang.

Equal to kTile ON PURPOSE: one workgroup spans one raster tile, so every thread in a group walks the same tile bin.

var const char * kClearKernel #

The clear kernel's entry name — plot_clear in shaders/plot.slang (buffers: fb, params).

var const char * kRasterKernel #

The raster kernel's entry name — plot_raster in shaders/plot.slang (buffers: prims, tile_offsets, tile_prims, fb, params).

var std::uint32_t kTile #

The raster tile edge in pixels: binning buckets primitives into kTile×kTile screen tiles.

var int kGlyphWidth #

The glyph cell the kernel rasterizes: 8 pixels wide (a glyph prim's aux lanes carry the bitmap, one byte per row, bit 7 = leftmost pixel).

var int kGlyphHeight #

The glyph cell height in pixels (16 rows = the prim's four aux lanes, 4 rows per lane).

Types

enum std::uint32_t PrimType #

The primitive kinds the raster kernel draws. Values are the on-device codes — append-only.

type std::vector< Prim > DrawList #

The primitive list, in paint order. Push through the helpers below.