Backend-agnostic GPU and accelerated rendering core experiments for Python scene packages.
Project description
py_gpu
py_gpu is a small rendering-core package for Python scene libraries that need
to grow from simple CPU rendering toward modern GPU-style throughput.
The immediate companion project is py_3d, but this repository should stay
cleanly reusable: it owns backend detection, batching contracts, frame buffers,
and accelerated renderer experiments. Scene construction, physics, and high
level demos can live elsewhere.
Why This Exists
Game engines render huge scenes quickly because they avoid per-object Python
work in the hot path. They batch geometry, keep backend contracts stable, upload
large buffers once, reuse device resources, and let the GPU do deeply parallel
work. py_gpu is the place to build those ideas without making py_3d messy.
The target shape is:
Python scene package -> adapter -> render batch -> backend -> frame/output
Current status:
- Dependency-free
FrameBufferandDepthBuffer. - Screen-space
RasterBatch,ScreenTriangle, andScreenVertexcontracts. - A small CPU raster backend for correctness and fallback use.
- A real offscreen ModernGL backend for projected triangle batches when OpenGL is available.
- An optional NumPy raster backend selected by
select_backend("auto")when ModernGL is unavailable and NumPy is installed. - Optional backend detection for WebGPU, OpenGL, Vulkan, CuPy, Numba, and PyTorch packages.
- Optional
py_3dadapter that can return apy_3d.PixelBufferwith reference visual parity, while still exposing an experimental flat batch backend path.
This is not yet a full GPU renderer. The first goal is a clean, measurable contract that real GPU backends can implement without changing user scenes.
Preview
Lit 3D Shape Preview
View the GPU lit textured shapes MP4
Install
From PyPI after release:
python -m pip install py_gpu
Editable development install:
python -m pip install -e ".[dev]"
python -m pytest
Optional backend experiments:
python -m pip install -e ".[opengl]"
python -m pip install -e ".[webgpu]"
python -m pip install -e ".[numeric]"
Basic Use
Render projected triangles into a dependency-free frame buffer:
from py_gpu import RasterBatch, ScreenTriangle, ScreenVertex, select_backend
batch = RasterBatch([
ScreenTriangle(
ScreenVertex(80, 20, 1.0),
ScreenVertex(20, 120, 1.0),
ScreenVertex(140, 120, 1.0),
(220, 80, 40),
)
])
backend = select_backend("cpu")
frame = backend.render(batch, width=160, height=140, background=(8, 10, 14))
frame.to_png("triangle.png")
Use the fastest available backend:
backend = select_backend("auto")
Force the offscreen OpenGL backend:
backend = select_backend("moderngl")
Use the first py_3d bridge:
from py_3d import RenderEngine
from py_gpu.adapters.py3d import Py3DRasterRenderer
engine = RenderEngine(Py3DRasterRenderer())
buffer = engine.render(scene, camera, settings)
buffer.to_png("py3d-via-pygpu.png")
The adapter defaults to reference-compatible rendering so live py_3d windows
match the fully shaded CPU outputs. Use Py3DRasterRenderer(reference_compatible=False)
to exercise the current fast batch backend. Fast mode projects triangles,
applies simple per-face lighting, samples textured faces at the triangle center,
expands wireframe edges into thin GPU triangles, and returns packed RGB frames
through py_3d's lazy PixelBuffer path. Smooth vertex attributes, full
material parity, persistent static geometry uploads, and direct window
presentation should be added behind this same shape before the accelerated path
becomes the default for full scenes.
Benchmarks
Run the current screen-space raster benchmark:
python examples/benchmark_raster.py --backend auto --frames 60 --triangles 1000 --width 640 --height 360
python examples/benchmark_raster.py --backend moderngl --frames 60 --triangles 1000 --width 640 --height 360
python examples/benchmark_raster.py --backend cpu --frames 10 --triangles 1000 --width 640 --height 360
Write a visual benchmark frame:
python examples/benchmark_raster.py --triangles 1000 --output raster-benchmark.png
On one Windows development machine with an RTX 4090, the current 1000 triangle
640x360 benchmark measured about 131.6 fps through the ModernGL backend,
about 8.8 fps through the NumPy backend, and about 0.8 fps through the plain
Python CPU backend. Treat local benchmark numbers as machine-specific, not a
promise.
Through the py_3d adapter on the same machine, the fast ModernGL bridge
measured about 48 fps at 320x180 with 236 generated scene triangles and
about 63 fps at 480x270 with a lighter 132-triangle live setting. The gap
between raw raster speed and adapter speed is expected until persistent batches
and direct presentation remove more per-frame Python and readback work.
Generate README preview media:
python examples/render_preview.py --backend auto
python examples/render_lit_textured_shapes.py
Publishing
PyPI Trusted Publishing should use:
| Field | Value |
|---|---|
| PyPI Project Name | py_gpu |
| Owner | Daniel-J-Mueller |
| Repository name | py_gpu |
| Workflow name | publish.yml |
| Environment name | blank / any |
Publish by committing .github/workflows/publish.yml, pushing the branch, and
pushing a version tag:
git tag v0.0.1
git push origin v0.0.1
The workflow builds with python -m build and publishes with PyPI Trusted
Publishing through pypa/gh-action-pypi-publish.
Architecture
py_gpu should grow in layers:
buffers: frame and depth buffers that can be written to images or copied into external packages.geometry: compact projected batch contracts.backends: protocol, capabilities, and selection logic.raster: reference CPU rasterizer for correctness.numpy_raster: optional vectorized CPU rasterizer.moderngl_backend: optional offscreen OpenGL rasterizer.adapters: optional bridges from scene packages such aspy_3d.
Backends should expose capabilities rather than pretending every implementation supports every feature. A backend can start with flat color triangles, then add textures, vertex attributes, instancing, depth formats, or compute passes.
Direction
Near-term work:
- Add a world-space mesh batch format with positions, normals, UVs, material ids, and indices.
- Add a
py_3dadapter path that preserves lights, textures, and smooth vertex normals. - Add persistent batch handles so static geometry does not need to be rebuilt every frame.
- Prototype a WebGPU backend through
wgpuor an OpenGL backend throughmoderngl. - Keep the CPU raster backend as the correctness reference for small scenes.
- Add benchmark fixtures for thousands, tens of thousands, and hundreds of thousands of triangles.
Long-term work:
- Instancing and shared mesh buffers.
- Texture atlases and sampler modes.
- Depth, normal, object-id, and color attachments.
- Async frame readback for screenshots and offline video.
- Compute-friendly buffers for simulations that later feed rendering.
Design Rules
- Keep scene APIs out of this core package. Scene packages should adapt into
py_gpubatches. - Keep backend dependencies optional.
- Do not make a GPU backend mandatory for correctness tests.
- Prefer explicit capabilities and clear failure modes.
- Measure every performance claim with a reproducible benchmark.
- Keep Python per-frame work small; batching and resource reuse matter more than clever per-pixel Python.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file py_gpu-0.0.1.tar.gz.
File metadata
- Download URL: py_gpu-0.0.1.tar.gz
- Upload date:
- Size: 17.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
532253a6dae89030fe35bf7d9ab2f545e6aa7b8194f6a1a55c17f55e2edf540e
|
|
| MD5 |
e234f2a662648ffde5fe0051ad7d6c07
|
|
| BLAKE2b-256 |
081ea60b99866a87f377aa6c6f12c6d08eeba27d94bc536f6b36e1b2d0672e04
|
Provenance
The following attestation bundles were made for py_gpu-0.0.1.tar.gz:
Publisher:
publish.yml on Daniel-J-Mueller/py_gpu
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
py_gpu-0.0.1.tar.gz -
Subject digest:
532253a6dae89030fe35bf7d9ab2f545e6aa7b8194f6a1a55c17f55e2edf540e - Sigstore transparency entry: 1859205626
- Sigstore integration time:
-
Permalink:
Daniel-J-Mueller/py_gpu@123b804c4a949db072f7fd37df557045903aafa2 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/Daniel-J-Mueller
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@123b804c4a949db072f7fd37df557045903aafa2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file py_gpu-0.0.1-py3-none-any.whl.
File metadata
- Download URL: py_gpu-0.0.1-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f75c38d84b5716161e29a19af54bace28d0b1ed2ecaaddf587fb2632912ab5f
|
|
| MD5 |
600b4b4a06eb74eb1fe183c7bbb5b4db
|
|
| BLAKE2b-256 |
bf001f4be1118743723e899b54fb2c93f7d3dbf4049209cfc7c96230cb645b5c
|
Provenance
The following attestation bundles were made for py_gpu-0.0.1-py3-none-any.whl:
Publisher:
publish.yml on Daniel-J-Mueller/py_gpu
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
py_gpu-0.0.1-py3-none-any.whl -
Subject digest:
4f75c38d84b5716161e29a19af54bace28d0b1ed2ecaaddf587fb2632912ab5f - Sigstore transparency entry: 1859205708
- Sigstore integration time:
-
Permalink:
Daniel-J-Mueller/py_gpu@123b804c4a949db072f7fd37df557045903aafa2 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/Daniel-J-Mueller
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@123b804c4a949db072f7fd37df557045903aafa2 -
Trigger Event:
push
-
Statement type: