Skip to main content

Vello: GPU-Accelerated 2D Vector Graphics for Python

PyPI version License Python

Vello is a high-performance, GPU compute-centric 2D vector graphics engine for Python, powered by Linebender's Vello and wgpu.

Unlike traditional CPU renderers (like Cairo or CPU Skia) or traditional GPU renderers that rely on tessellation, Vello utilizes modern GPU Compute Shaders to perform sorting, path clipping, and antialiased rasterization in parallel on your graphics card.


✨ Features

  • ⚡ Pure GPU Compute Acceleration: Path flattening, clipping, and rasterization run completely on GPU Compute Shaders.
  • 🎨 Pythonic Canvas API: An intuitive, HTML5 Canvas-like API designed specifically for Python developers.
  • 🚀 Zero-Copy NumPy Integration: Stream rendered frames directly into NumPy (H, W, 4) uint8 arrays without copying memory.
  • ⚡ Vectorized Batch Drawing: Render tens of thousands to millions of circles, rectangles, lines, and complex polygons in a single native GPU dispatch via NumPy arrays.
  • 🔺 Direct Polygon & Polyline Batches: Pass binary NumPy coordinate buffers directly to fill_polygons_batch, stroke_polygons_batch, and draw_polylines_batch with compound path optimization, eliminating SVG string parsing and scene buffer overhead.
  • 🎥 Direct GPU Video Streaming: Stream raw RGBA buffers directly to hardware-accelerated video encoders (NVENC H.264/HEVC or libx264) via vello.VideoWriter and Canvas.save_video(), eliminating OpenCV and PCIe bus bottlenecks.
  • 🌈 Rich Shading & Gradients: Full support for Solid Colors, Linear Gradients, Radial Gradients, Angular / Conical Sweep Gradients, and Image Brushes.
  • 🎬 Built-in Animation & Video Export: Generate smooth animated GIF sequences or hardware-encoded MP4 videos directly.
  • 📐 Vector Shapes & SVG Paths: Native support for Polygons, Polylines, Rectangles, Rounded Rectangles, Circles, Ellipses, Lines, Bézier Curves, and complete SVG path d="..." strings.
  • 🔤 GPU Vector Typography: High-quality TrueType/OpenType font rendering with exact subpixel glyph positioning.
  • 🎭 Compositing & Blend Modes: Full W3C blend modes (Multiply, Screen, Overlay, etc.) and compositing operations.
  • 💡 Gaussian Drop Shadows: Accelerated blurred rounded rectangles for realistic UI drop shadows.
  • 🧵 Non-blocking & Thread-Safe: Releases the Python GIL during GPU execution for multi-threaded performance.
  • 🐧 Linux & Cloud Ready: Fully supports headless Linux servers, Docker containers, and Cloud GPU environments with NVIDIA GPUs (T4, V100, A100, H100, RTX) via Vulkan.

📦 Installation

pip install vello

🚀 Quickstart

1. Basic Drawing & PNG Export

import vello

# Create canvas with background color
canvas = vello.Canvas(800, 600, background="white")

# Fill and stroke shapes with CSS colors, hex, or RGB tuples
canvas.fill_circle(cx=400, cy=300, radius=120, fill="royalblue")
canvas.stroke_circle(cx=400, cy=300, radius=120, stroke="crimson", stroke_width=6.0)

# Draw rounded rectangle with GPU drop shadow
canvas.draw_shadow(x=50, y=50, width=200, height=100, radius=16, blur=20, color="#00000044")
canvas.fill_rounded_rect(x=50, y=50, width=200, height=100, radius=16, fill="#2ecc71")

# Draw an SVG path
canvas.fill_path("M 500 100 L 550 200 L 450 200 Z", fill="gold")

# Save directly to image
canvas.save("output.png")

2. High-Performance NumPy & Video / Game Pipelines

import vello

canvas = vello.Canvas(1920, 1080, background="black")

# Draw vector elements
canvas.fill_circle(960, 540, 200, fill="coral")

# Get a NumPy array with zero-copy buffer mapping (shape: 1080, 1920, 4)
frame = canvas.to_numpy()
print(frame.shape, frame.dtype)  # (1080, 1920, 4) uint8

3. Linear & Radial Gradients

import vello

canvas = vello.Canvas(400, 400, background="black")

# Linear gradient
gradient = vello.LinearGradient(
    start=(0, 0),
    end=(400, 400),
    stops=[
        vello.ColorStop(0.0, vello.Color.from_name("red")),
        vello.ColorStop(0.5, vello.Color.from_name("yellow")),
        vello.ColorStop(1.0, vello.Color.from_name("blue")),
    ]
)
canvas.fill_rect(0, 0, 400, 400, fill=gradient)
canvas.save("gradient.png")

4. Transformations & Layer Blending

import vello

canvas = vello.Canvas(500, 500, background="white")

# Context manager for local coordinate transforms
with canvas.transform(translate=(250, 250), rotate_deg=45):
    canvas.fill_rect(-50, -50, 100, 100, fill="teal")

# Blending and opacity layers
with canvas.layer(alpha=0.8, blend_mode="multiply"):
    canvas.fill_circle(200, 200, 80, fill="cyan")
    canvas.fill_circle(260, 200, 80, fill="magenta")

canvas.save("layers.png")

5. Vector Typography

import vello

canvas = vello.Canvas(600, 200, background="white")

# Load any TrueType or OpenType font
font = vello.Font.from_file("C:/Windows/Fonts/arial.ttf")

# Measure text bounds
width, height = font.measure_text("Vello on GPU", size=36.0)

# Draw vector text
canvas.draw_text("Vello on GPU", x=50, y=100, font=font, size=36.0, color="royalblue")
canvas.save("text.png")

6. Vectorized Batch Drawing (NumPy)

Render tens of thousands of shapes simultaneously without Python loop overhead:

import vello
import numpy as np

canvas = vello.Canvas(1000, 1000, background="black")

# 50,000 random circles [x, y, radius]
n = 50_000
data = np.zeros((n, 3), dtype=np.float32)
data[:, 0] = np.random.uniform(0, 1000, n)
data[:, 1] = np.random.uniform(0, 1000, n)
data[:, 2] = np.random.uniform(1, 5, n)

# Single native GPU call!
canvas.fill_circles_batch(data, fill="#00ffcc88")

# Rectangles batch [x0, y0, x1, y1] and Lines batch [x0, y0, x1, y1]
# Combined into a single compound path to eliminate scene buffer fragmentation:
canvas.fill_rects_batch([[10, 10, 50, 50], [60, 10, 100, 50]], fill="teal")
canvas.draw_lines_batch([[0, 0, 1000, 1000], [0, 1000, 1000, 0]], stroke="gray", stroke_width=1.0)
canvas.save("batch_primitives.png")

7. Complex Polygons & Polyline Batches (Zero-Copy NumPy)

Avoid CPU string formatting and SVG parsing bottlenecks (d="M x y L x y Z") by feeding binary coordinate buffers directly from NumPy. All polygons are automatically merged into a single compound BezPath for maximal GPU encoding efficiency:

import vello
import numpy as np

canvas = vello.Canvas(1000, 1000, background="#111118")

# Draw an arbitrary individual polygon or open polyline:
pts = np.array([[200, 100], [350, 200], [300, 400], [150, 350]], dtype=np.float64)
canvas.fill_polygon(pts, fill="gold")
canvas.stroke_polygon(pts, stroke="white", stroke_width=2.0)

# Batch rendering: List of 2D NumPy polygon arrays (varying vertex counts)
tri = np.array([[50, 50], [90, 50], [70, 90]])
quad = np.array([[120, 50], [160, 50], [170, 90], [110, 80]])
poly = np.array([[200, 50], [240, 60], [250, 90], [220, 110], [190, 80]])

canvas.fill_polygons_batch([tri, quad, poly], fill="cyan")

# Batch rendering: Uniform polygons via 3D array (e.g., 10,000 triangles of shape (10000, 3, 2))
triangles = np.random.uniform(50, 950, size=(10_000, 3, 2))
canvas.fill_polygons_batch(triangles, fill="#ff336644")

# Batch polylines (open paths, contours, GIS tracks):
lines = [np.random.uniform(0, 1000, size=(20, 2)) for _ in range(500)]
canvas.draw_polylines_batch(lines, stroke="lime", stroke_width=1.5)

canvas.save("batch_polygons.png")

8. Direct Hardware-Accelerated Video Streaming (vello.VideoWriter)

When rendering high-resolution videos (1080p / 4K at 60 FPS), traditional approaches force you to read uncompressed frames across the PCIe bus into host RAM with canvas.to_numpy() and re-encode with OpenCV.

Vello provides a direct streaming pipeline that pipes raw GPU RGBA bytes straight into hardware-accelerated encoders (NVIDIA NVENC H.264/HEVC with automatic fallback to libx264):

import vello

WIDTH, HEIGHT, FPS = 1920, 1080, 60

# Option A: Pythonic context manager streaming directly to NVENC / FFmpeg:
with vello.VideoWriter("render.mp4", WIDTH, HEIGHT, fps=FPS, codec="auto") as video:
    for i in range(240):  # 4 seconds at 60 FPS
        canvas = vello.Canvas(WIDTH, HEIGHT, background="#0a0a14")
        canvas.fill_circle(960 + (i - 120) * 4, 540, 80, fill="deepskyblue")
        video.write(canvas)  # Direct GPU-to-pipe stream!

# Option B: Batch export an iterable of pre-rendered Canvases:
frames = [vello.Canvas(800, 600, background="black").fill_circle(100 + i * 5, 300, 40, fill="red") for i in range(60)]
vello.Canvas.save_video(frames, "output.mp4", fps=30)

9. Animation & GIF Export

import vello
import numpy as np

frames = []
for i in range(30):
    c = vello.Canvas(300, 300, background="black")
    angle = (i / 30.0) * 360.0
    with c.transform(translate=(150, 150), rotate_deg=angle):
        c.fill_rect(-40, -40, 80, 80, fill="cyan")
    frames.append(c)

# Save smooth animated GIF
vello.Canvas.save_animation(frames, "spin.gif", fps=30)

10. 🎥 Cinematic 2D & GIS Camera (vello.Camera)

The Camera system brings game-engine and professional GIS viewport controls to 2D vector graphics:

  • fit_bounds(minx, miny, maxx, maxy, padding=40, flip_y=True): Automatically fits any map, dataset, or scene in the center of the viewport with exact scaling and geographic projection (+Y North) alignment. Includes NaN validation.
  • look_at(x, y, zoom=None): Focuses camera at specific coordinates.
  • screen_stroke(screen_px=1.5): Automatically computes world-space stroke width to ensure strokes render at exactly screen_px pixels regardless of zoom level, preventing line vanishing or solid-blob pixel congestion!
  • world_to_screen(x, y) & screen_to_world(sx, sy): Bidirectional coordinate transformation.
  • interpolate(target_camera, t): Smooth cinematic camera flight between locations with logarithmic scale interpolation.
import vello
from vello.camera import Camera

canvas = vello.Canvas(1920, 1080, background="#050814")
camera = Camera(1920, 1080)

# 1. Fit Manhattan bounds perfectly in 1080p
camera.fit_bounds(-74.05, 40.68, -73.91, 40.88, padding=80, flip_y=True)

# 2. Render within camera coordinate space
with canvas.use_camera(camera):
    # Guaranteed 1.5 pixels wide on screen:
    w = camera.screen_stroke(1.5)
    canvas.fill_circle(-73.985, 40.748, 0.005, fill="cyan")  # Empire State Building

11. ⏱️ Keyframe Timeline & Animation (vello.Timeline, vello.Easing)

A multi-track animation engine that evaluates camera moves, numeric properties, and colors in pure Rust:

  • Comprehensive Easing Curves (vello.Easing): LINEAR, IN_OUT_CUBIC, SMOOTHSTEP, OUT_BOUNCE, OUT_ELASTIC, IN_OUT_QUART, etc.
  • Tracks: Animate numbers, bounding boxes, camera states, and colors across time.
  • render_video(output, render_fn): Renders and streams the entire animation directly to hardware-encoded MP4 without manual Python loops!
import vello
from vello.camera import Camera
from vello.animation import Timeline, Easing

# 3-second animation at 30 fps (90 frames)
tl = Timeline(duration=3.0, fps=30.0)

# Smooth camera flight from Manhattan to all of New York State
c_start = Camera(1920, 1080)
c_start.fit_bounds(-74.05, 40.68, -73.91, 40.88, padding=80, flip_y=True)

c_end = Camera(1920, 1080)
c_end.fit_bounds(-79.76, 40.49, -71.85, 45.01, padding=80, flip_y=True)

tl.animate_camera("cam", c_start, c_end, ease=Easing.IN_OUT_CUBIC)
tl.animate_number("stroke_px", from_val=1.5, to_val=0.4, ease=Easing.IN_OUT_CUBIC)

def render_frame(canvas, state):
    with canvas.use_camera(state.cam):
        canvas.stroke_circle(-73.985, 40.748, 0.01, stroke="cyan", stroke_width=state.cam.screen_stroke(state.stroke_px))

# One-call video export with direct GPU streaming and progress reporting:
tl.render_video("cinematic_zoom.mp4", render_frame, width=1920, height=1080)

12. 🌍 High-Performance GIS Engine (vello.GeoLayer)

Eliminates Python loops and data wrangling for GIS datasets:

  • GeoLayer.from_geodataframe(gdf): Instant ingestion from GeoPandas / Shapely in vectorized C.
  • Spatial Frustum Culling (clip_to_camera): Culls off-screen polygons in Rust in milliseconds, cutting millions of vertices down to visible geometries.
  • Dynamic Auto-LOD (simplify_to_screen): Automatically simplifies geometries based on screen pixel resolution, preventing GPU buffer overflow and visual clutter.
  • GPU Safe Batching: Internal chunking guarantees the GPU bump allocator will never overflow.
import geopandas as gpd
import vello
from vello.gis import GeoLayer

gdf = gpd.read_file("ny_census_blocks.shp")
layer = GeoLayer.from_geodataframe(gdf)

canvas = vello.Canvas(1920, 1080, background="#050814")
# Draw directly with automatic GPU protection:
canvas.draw_geolayer(layer, stroke="#00e5ff", stroke_width=1.0)

13. Headless Linux & Cloud GPU Setup (enable_vulkan_gpu)

In cloud container environments or headless Linux servers, NVIDIA drivers may not have Vulkan configured out of the box (defaulting to CPU software rendering).

Vello includes an automatic, one-line setup utility that detects your NVIDIA GPU and configures Vulkan acceleration automatically:

import vello

# Run once in your cloud notebook or script to enable 100% GPU acceleration:
vello.enable_vulkan_gpu()

# Verify active GPU hardware & physical limits:
gpu = vello.get_gpu_info()
print("Active GPU:", gpu["name"])           # e.g., 'Tesla T4' or 'RTX 4090'
print("Backend:", gpu["backend"])         # 'Vulkan'
print("Device Type:", gpu["device_type"]) # 'DiscreteGpu'
print("Max Buffer Binding:", gpu["max_storage_buffer_binding_size_mb"], "MB")

14. Millions of Vectors & GPU Buffer Scaling (gpu_buffer)

Vello automatically discovers and prioritizes your Discrete GPU (e.g. NVIDIA Tesla T4, RTX 3090/4090, AMD Radeon) over any integrated or software fallback adapters, maximizing the available hardware storage limits.

Furthermore, Vello features hardware-safe buffer clamping: it dynamically verifies your GPU's physical max_storage_buffer_binding_size so allocations never exceed your card's hardware capabilities.

By default, Vello allocates an ultra-safe 128 MB GPU bump allocator profile, ensuring smooth operation on low-power devices and integrated graphics.

When working with massive datasets (e.g. rendering 1,000,000+ vector shapes in 4K) on high-memory GPUs (such as an NVIDIA Tesla T4 with 16GB VRAM, RTX 3090/4090, or A100/H100), you can unlock large buffer capacities:

Per-Canvas Configuration:

import vello

# Allocate a high-capacity GPU bump buffer profile:
canvas = vello.Canvas(3840, 2160, background="#050510", gpu_buffer="2GB")

# Available profiles: "128MB" (default), "256MB", "512MB", "1GB", "2GB", "4GB"

Global Configuration (e.g. at the top of a Notebook):

import vello

# Check active buffer profile
print(vello.get_gpu_buffer())  # '128MB'

# Set high-capacity profile for all canvases
vello.set_gpu_buffer("2GB")

1,000,000 Vector Circles in 4K:

import vello
import numpy as np

WIDTH, HEIGHT = 3840, 2160
N = 1_000_000

# 1. Initialize canvas with 4GB buffer
canvas = vello.Canvas(WIDTH, HEIGHT, background="#050510", gpu_buffer="4GB")

# 2. Generate 1,000,000 vector circles
data = np.zeros((N, 3), dtype=np.float32, order='C')
data[:, 0] = np.random.uniform(50, WIDTH - 50, N)
data[:, 1] = np.random.uniform(50, HEIGHT - 50, N)
data[:, 2] = np.random.uniform(2.0, 5.0, N)

# 3. Render all 1,000,000 shapes directly on GPU
canvas.fill_circles_batch(data, fill="#00ffcc")
canvas.save("galaxy_1m_4k.png")

📊 Performance

Vello parallelizes vector rendering on GPU compute shaders:

  • Instant scene builds: Adding thousands of vector commands takes just a few milliseconds.
  • Fast GPU rendering: 1080p full frame renders take ~5-10 ms on standard GPUs (~120-200 FPS).
  • GIL-free execution: Multi-threaded Python applications run concurrently without blocking.

📜 License

Licensed under either of:

at your option.

Metadata

Release files for vello 0.1.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vello 0.1.6
File Size Uploaded
vello-0.1.6.tar.gz 32.7 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for vello 0.1.6
File
vello-0.1.6-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
vello-0.1.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ x86-64 Details
vello-0.1.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64 Details
vello-0.1.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64 Details
vello-0.1.6-cp310-cp310-win_amd64.whl CPython 3.10 CPython 3.10 Windows x86-64 Details
vello-0.1.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ x86-64 Details

Total release size: 63.3 MB

Release files / vello-0.1.6.tar.gz

Download URL vello-0.1.6.tar.gz
Size 32.7 MB
Tags Source
SHA-256 checksum
How to use checksums
baad3654a22cfd796b40aa1ae0d622eacd0ea513901932180bebd781fb88123d
BLAKE2b-256 checksum
How to use checksums
72270cd9282742369d8407d366840a6db66d85861578d6621f233e51ae45238d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release files / vello-0.1.6-cp313-cp313-win_amd64.whl

Download URL vello-0.1.6-cp313-cp313-win_amd64.whl
Size 7.9 MB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
0c50a61f01c472c55a7ce7230dbf5dbe6edacb7c16bcfe47cd430c46e41a72d5
BLAKE2b-256 checksum
How to use checksums
065d1f1b6ca2bf2e87e574cc6986f9b9f228ebfad2c0355910b9cf1dde61e820
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release files / vello-0.1.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL vello-0.1.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.7 MB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
f76446d800704e29c0bfe10fb47169dac7dd8e292b977c9026b1cc027eddb250
BLAKE2b-256 checksum
How to use checksums
d7e9deea8d1a3bf575c347390e555f6cefeebaa896d1078b6f7221b928104c77
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release files / vello-0.1.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL vello-0.1.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.7 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
befb9815b8781eb1e68ddb65920920fd910a85b3563bd0e090e01630e7aec689
BLAKE2b-256 checksum
How to use checksums
630d067e5ef7eee47a1ee48e26f3d662a25f15ed2919424be29c8f2d32057f1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release files / vello-0.1.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL vello-0.1.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.7 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
cd5def4df4527c3e0641f33e2a64406b545469a90eb4cede8e904b9b7244a773
BLAKE2b-256 checksum
How to use checksums
9b043e4467850dc8dd545b85754f2ffa7e4cc41690729f7644e3f6839faeefa0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release files / vello-0.1.6-cp310-cp310-win_amd64.whl

Download URL vello-0.1.6-cp310-cp310-win_amd64.whl
Size 7.9 MB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
6a08e702ffb0bb80cb9b81b085d2fd5a2122248fbb0ef6d08a03a8e0aacbe490
BLAKE2b-256 checksum
How to use checksums
a1292435374a48fd18b8cebe55ca82b4d3ceaa0460d37d1f66e57bca31f30cb7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release files / vello-0.1.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL vello-0.1.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.7 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
e0faf6abd868f184aad4a60298a28ffd1ec4d891daaa71d23e2f6941ecc24bde
BLAKE2b-256 checksum
How to use checksums
6b9f7bfc97dc23d012b0812101687c0f96cfff3c6723d6d980a1f53f599d3b24
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release history Release notifications | RSS feed

0.1.7

7 release files

This release

0.1.6 This release

7 release files

0.1.5

7 release files

0.1.4

7 release files

0.1.3

7 release files

0.1.2

7 release files

0.1.1

7 release files

0.1.0

6 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page