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

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.7
File Size Uploaded
vello-0.1.7.tar.gz 32.7 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for vello 0.1.7
File
vello-0.1.7-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
vello-0.1.7-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.7-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.7-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.7-cp310-cp310-win_amd64.whl CPython 3.10 CPython 3.10 Windows x86-64 Details
vello-0.1.7-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.4 MB

Release files / vello-0.1.7.tar.gz

Download URL vello-0.1.7.tar.gz
Size 32.7 MB
Tags Source
SHA-256 checksum
How to use checksums
fe49b586178db1ddeb119441a4d19a8cbec123c0913746d70ce219e47ebb8fcd
BLAKE2b-256 checksum
How to use checksums
30d7a105d7995e9178e4a8dd5d173195073c8c688d8d7f3602be5d214d1b6d67
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.7-cp313-cp313-win_amd64.whl

Download URL vello-0.1.7-cp313-cp313-win_amd64.whl
Size 7.9 MB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
391dd661017c4241ae482c437a050c77c49473f441a0372059d8b979e03814b5
BLAKE2b-256 checksum
How to use checksums
b45a0726f791a3e235ad0715966b68db47349a591ee91a667295fec69c30566b
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.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL vello-0.1.7-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
f9ea01e36a95b54b59836392d0ad3b2347ec33707f0bb091310d1c2b59dfb576
BLAKE2b-256 checksum
How to use checksums
720026f2cf72b31fcd43313280a023f56a438339255b5103cd8866ca5bb8117e
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.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL vello-0.1.7-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
71d709cccab0505ed72a051b8b468890f437743db6f7495b95f98b25a1e67ed1
BLAKE2b-256 checksum
How to use checksums
3e8a67568eab60515874606b811aac0c986eb2527d5817a505e12f060867a092
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.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL vello-0.1.7-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
ce17c81ca669f5706f188e2fbfe3e9b459d186428e6e64eadaf00493bee337db
BLAKE2b-256 checksum
How to use checksums
66592a7b2faecd01a0a2d7900dea6097df33d2e1f19989e988d37aaf8e3765b8
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.7-cp310-cp310-win_amd64.whl

Download URL vello-0.1.7-cp310-cp310-win_amd64.whl
Size 7.9 MB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
1c951be4bc3537dad9a4d5e50682f68b69740de6dc739d8a4750037ec750a45d
BLAKE2b-256 checksum
How to use checksums
c61a175264a4d3ad1ad86a1c80e17e9f50736f7ac396e91280130dbe58975edd
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.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL vello-0.1.7-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
9e111486d31d08889bf2986c0712595e70e96c03a961fd1423890ee66b8aee2e
BLAKE2b-256 checksum
How to use checksums
eee5d9c102f492e83c1dee72c79b9204d66b6ec45a0c95aae6db96bce2513f01
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

This release

0.1.7 This release

7 release files

0.1.6

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