Skip to main content

Bazalt

Bazalt is a modern Python library for rapid prototyping and building graphical applications using the Vulkan API. It provides a clean, intuitive interface over a high-performance C++ core, allowing developers to create rendering applications quickly without the typical boilerplate.

Installation

You can install bazalt easily via pip:

pip install bazalt

Prebuilt wheels are provided for Windows and Linux. Building from source requires a C++23 compiler — GCC 14+ or MSVC 19.36+ (Visual Studio 17.6) — and the Vulkan SDK.

Key Features

  • Modern Graphics API: Built on top of Vulkan for optimal hardware utilization.
  • Easy to Use Interface: Write clear and concise code with an intuitive API.
  • Automatic Shader Compilation: Compile GLSL shaders (Vertex/Fragment/Compute) directly from your code.
  • Compute Pipelines: ctx.compute_pipeline() + cmd.dispatch() — run GPU compute with results straight back into NumPy, no images required.
  • Storage Images: compute shaders write images too — .storage_image(binding) + set_storage_image() bind a read/write image for imageStore/imageLoad (post-processing, procedural textures). The barriers and layout transitions between the dispatch and a later sample are recorded for you.
  • Cubemaps & Texture Arrays: pass a list of layers (ctx.create_image([...], cube=True) or ctx.load_image([...6 paths...], cube=True)) for a cubemap, or without cube= for a texture array — one mechanism, sampled as samplerCube / sampler2DArray. Empty layered images can be filled in compute (procedural skyboxes). See examples/14_skybox.
  • Automatic Barriers: Hazards between resources (dispatch → dispatch, compute-written buffer → vertex fetch, compute-written image → sample) get their barriers computed at record time. Context(auto_barriers=False) hands you full manual control via cmd.barrier().
  • Pipeline & Buffer Management: Easy builder pattern for graphics pipelines and unified buffer creation.
  • Command Buffers: Explicit, yet simple command recording — calls chain (cmd.bind_pipeline(p).draw(3)), and with cmd.rendering(target): closes the pass for you.
  • Asynchronous Texture Streaming: ctx.load_image() returns immediately while the decode and GPU copy run in the background; anything that samples the image waits for it automatically. ctx.upload_progress gives you a loading bar for free.
  • Hot Reload: Context(hot_reload=True) watches the shaders (and their #includes) and images you loaded and applies edits live — shaders recompile and rebuild their pipelines in place, images re-upload into the same handle. A typo or a bad file is logged and the last good version keeps rendering, so a mistake never takes the app down. See examples/12_hot_reload.
  • Frame Timing & Debug Names: Context(gpu_timing=True) makes frame.gpu_time_ms report the GPU time of a recent frame (opt-in — off by default it costs nothing); t = cmd.timer() … t.stop() … t.ms times any slice of a recording (handle-based, no with required) and reads back headless; name= / .name() label buffers, images and pipelines so validation messages name the culprit.
  • Headless Rendering: Draw into an offscreen RenderTarget and read the pixels back as a NumPy array — no window, no display required.
  • Render-to-Texture, MRT & Shadow Maps: Target attachments are ordinary Image objects in any supported Format — sample target.color[0] or a depth-only target's target.depth like any texture.
  • Runs Widely: Vulkan 1.2 baseline with 1.3 used where available, so bazalt runs on older integrated GPUs too. Capabilities are requested by name, never by version or extension.
  • Decoupled Architecture: Clean separation of concerns between Windowing (GLFW), Vulkan Context (GPU initialization), and render targets — a window is one target among others.

Quick Start: Rendering Without a Window

Everything below works with no display attached, which makes it usable from CI and tests:

import bazalt as bz

ctx = bz.Context()
target = bz.RenderTarget(ctx, 800, 600, depth=bz.Format.D32F)

pipeline = (ctx.graphics_pipeline()
    .vertex_shader(ctx.compile_shader("triangle.vert", bz.ShaderStage.VERTEX))
    .fragment_shader(ctx.compile_shader("triangle.frag", bz.ShaderStage.FRAGMENT))
    .vertex_format([bz.VertexFormat.FLOAT3, bz.VertexFormat.FLOAT3])
    .build(target))

# Interleaved position (x,y,z) and color (r,g,b)
vbuf = ctx.create_buffer([
     0.0, -0.5, 0.0,   1.0, 0.0, 0.0,
    -0.5,  0.5, 0.0,   0.0, 1.0, 0.0,
     0.5,  0.5, 0.0,   0.0, 0.0, 1.0,
], bz.BufferType.VERTEX, bz.MemoryUsage.STATIC, bz.DataType.FLOAT)

cmd = ctx.create_command_buffer()
cmd.begin()
with cmd.rendering(target, clear_color=[0.1, 0.2, 0.3, 1.0]) as c:
    c.bind_pipeline(pipeline).bind_vertex_buffer(vbuf).draw(3)

ctx.submit(cmd)

pixels = target.read_pixels()   # numpy (600, 800, 4) uint8

Quick Start: GPU Compute

Compute needs no window and no images — dispatch, then read the storage buffer back as a NumPy array:

import numpy as np
import bazalt as bz

ctx = bz.Context()

# double.comp: values[i] *= 2.0 over a std430 float array, local_size_x = 64
sim = (ctx.compute_pipeline()
    .shader(ctx.compile_shader("double.comp", bz.ShaderStage.COMPUTE))
    .storage_buffer(0)      # no stage argument — compute has exactly one stage
    .build())               # no target — compute has no attachments

data = np.arange(128, dtype=np.float32)
sbuf = ctx.create_buffer(data, bz.BufferType.STORAGE, bz.MemoryUsage.STATIC)

pool = ctx.create_descriptor_pool(max_sets=4, storage_buffers=4)
dset = pool.allocate_set(sim, set=0)
dset.set_buffer(0, sbuf)

cmd = ctx.create_command_buffer()
cmd.begin()
cmd.bind_pipeline(sim).bind_descriptor_set(dset, sim, set=0).dispatch(128 // 64)
ctx.submit(cmd)

assert np.allclose(sbuf.read(np.float32), data * 2)

Compute mixes freely with rendering in one command buffer — a dispatch that writes vertices and a draw that consumes them need no ceremony; the barrier between them is recorded automatically (see examples/11_particles).

Quick Start: Hot Reload

Add one keyword and bazalt watches the files it loaded — shaders (and their #includes) and images — recompiling and re-uploading on save:

ctx = bz.Context(logger, hot_reload=True)

vert = ctx.compile_shader("shader.vert", bz.ShaderStage.VERTEX)
frag = ctx.compile_shader("shader.frag", bz.ShaderStage.FRAGMENT)
tex  = ctx.load_image("wall.png")
pipeline = ctx.graphics_pipeline().vertex_shader(vert).fragment_shader(frag)...build(renderer)

while window.is_open():
    window.poll_events()
    if frame := renderer.begin_frame():   # edits are applied here (and at ctx.submit)
        frame.submit(cmd)                 # ...frame.gpu_time_ms (with gpu_timing=True) gives GPU frame timing

Editing shader.frag rebuilds the pipeline in place; re-saving wall.png (same size and format) re-uploads into the same handle, so descriptor sets need no rewrite. A shader typo logs a ShaderError and the last good pipeline keeps rendering — a mistake never crashes the app. Full demo: examples/12_hot_reload.

Quick Start: Drawing a Triangle

Here is a minimal example demonstrating how to initialize the window, Vulkan Context, and SwapchainRenderer, compile shaders, create a pipeline, and draw a colorful triangle.

import bazalt as bz

# 1. Initialize Logger and register a callback.
#    Each message carries its severity and source as data, so you can filter
#    without parsing strings. This is optional: a Context created without one
#    reports warnings on stderr by default.
logger = bz.Logger(min_severity=bz.Severity.WARNING)
@logger.on_message
def on_message(msg):
    print(f"[{msg.severity}] {msg.text}")

# 2. Create the window, Vulkan Context, and SwapchainRenderer
window = bz.Window(1024, 720, "Bazalt Demo - Triangle", logger=logger)
ctx = bz.Context(logger)
renderer = bz.SwapchainRenderer(window, ctx)

if __name__ == "__main__":
    # Load and compile shaders. The vertex shader processes our geometry,
    # and the fragment shader determines the final color of the pixels.
    # Shaders are compiled through the Context.
    vert_spv = ctx.compile_shader("triangle.vert", bz.ShaderStage.VERTEX)
    frag_spv = ctx.compile_shader("triangle.frag", bz.ShaderStage.FRAGMENT)

    # The pipeline is a baked state object that tells the GPU how to interpret our data.
    # It is built against a render target, which supplies the color/depth formats.
    # A SwapchainRenderer is one, so is an offscreen RenderTarget — same call.
    pipeline = (ctx.graphics_pipeline()
        .vertex_shader(vert_spv)
        .fragment_shader(frag_spv)
        .vertex_format([bz.VertexFormat.FLOAT3, bz.VertexFormat.FLOAT3]) # Position + Color
        .build(renderer))

    # We interleave Position (x,y,z) and Color (r,g,b) in a single flat array.
    # Vulkan's Normalized Device Coordinates (NDC) range from -1 to 1,
    # where Y points downwards and X points to the right.
    vertices = [
         0.0, -0.5, 0.0,   1.0, 0.0, 0.0, # Top / Red
        -0.5,  0.5, 0.0,   0.0, 1.0, 0.0, # Bottom-Left / Green
         0.5,  0.5, 0.0,   0.0, 0.0, 1.0, # Bottom-Right / Blue
    ]
    
    # Create Vertex Buffer through the Context
    vbuf = ctx.create_buffer(vertices, bz.BufferType.VERTEX, bz.MemoryUsage.STATIC, bz.DataType.FLOAT)
    
    # Create Index Buffer through the Context
    ibuf = ctx.create_buffer([0, 1, 2], bz.BufferType.INDEX, bz.MemoryUsage.STATIC, bz.DataType.UINT32)

    # Command buffers store a sequence of commands for the GPU.
    # For a static triangle, we can record this buffer once during initialization 
    # and submit the same pre-recorded buffer every frame to save CPU time.
    cmd = ctx.create_command_buffer()

    cmd.begin()

    # begin_rendering names the target you are drawing into, clears it, and sets
    # a viewport and scissor covering it. Naming the target is what lets the same
    # code render to a window or to an offscreen image.
    cmd.begin_rendering(renderer, clear_color=[0.1, 0.2, 0.3, 1.0])

    # Bind the baked pipeline and the geometry buffers
    cmd.bind_pipeline(pipeline)
    cmd.bind_vertex_buffer(vbuf)
    cmd.bind_index_buffer(ibuf)

    # Draw 3 indices (1 triangle)
    cmd.draw_indexed(3)
    cmd.end_rendering(renderer)

    # Main game/rendering loop
    while window.is_open():
        window.poll_events()
        
        # begin_frame returns a Frame, or None when this frame should be
        # skipped (window minimized, mid-resize)
        if frame := renderer.begin_frame():
            frame.submit(cmd)

Metadata

Release files for bazalt 0.10.0

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

Built distributions (wheels)

Table of built distributions (wheels) for bazalt 0.10.0
File
bazalt-0.10.0-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
bazalt-0.10.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64, Linux glibc 2.27+ x86-64 Details
bazalt-0.10.0-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
bazalt-0.10.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details
bazalt-0.10.0-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
bazalt-0.10.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details
bazalt-0.10.0-cp310-cp310-win_amd64.whl CPython 3.10 CPython 3.10 Windows x86-64 Details
bazalt-0.10.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.27+ x86-64, Linux glibc 2.28+ x86-64 Details

Total release size: 28.5 MB

Release files / bazalt-0.10.0-cp313-cp313-win_amd64.whl

Download URL bazalt-0.10.0-cp313-cp313-win_amd64.whl
Size 2.6 MB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
1647753a957c0edaf43103cdf26d02c4cc50acf8b968ab5afa93a2ef25428843
BLAKE2b-256 checksum
How to use checksums
3f808334153b25f651f4b1763aa27befd495f5ce6c84cb13867aa7b7994bfe2b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release files / bazalt-0.10.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL bazalt-0.10.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 4.5 MB
Tags CPython 3.13 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
cce345d429f0bd68f1f683fecb4aebe2e8a11b509f84993e78bd808023009825
BLAKE2b-256 checksum
How to use checksums
2b971490c175b73ced25dccb78356f7ee304febe796ba579c0c372f1ab436357
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release files / bazalt-0.10.0-cp312-cp312-win_amd64.whl

Download URL bazalt-0.10.0-cp312-cp312-win_amd64.whl
Size 2.6 MB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
7611b31e23b8c04f7970b3e9fe988117d23b531308f97c0d71f2986e6aa0ec38
BLAKE2b-256 checksum
How to use checksums
fdc99d7460fa70a03804ed9fd2f0e1281a2f829475aa8b8fca4375d31e3942bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release files / bazalt-0.10.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL bazalt-0.10.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 4.5 MB
Tags CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
a157fe0cb20cf6ac2ad1f1cbd66890acf461b46e996e7f8c1e0c717228e8ddd7
BLAKE2b-256 checksum
How to use checksums
98376026ab41058616f6aac0c39bf560fc2c0dcca63cfc4313c7ab42d7c1bebf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release files / bazalt-0.10.0-cp311-cp311-win_amd64.whl

Download URL bazalt-0.10.0-cp311-cp311-win_amd64.whl
Size 2.6 MB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
800d033ccaff38ff04ce3f3eb1b9f052ba87309da21143e3b6b124070224e4c7
BLAKE2b-256 checksum
How to use checksums
aeb11667a40c35c517ffe47fb24a33fe9c1ba174f47af2469d2c9eb7a74086d9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release files / bazalt-0.10.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL bazalt-0.10.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 4.5 MB
Tags CPython 3.11 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
17a42e6e0f0135b13fdb9ea92dfd561c7a5b197632df69de66fa08b59dab6ce4
BLAKE2b-256 checksum
How to use checksums
0b29eaef41c6b4b53db5e44a4562e4875e176c9e034e5c2e7b3d358bb581ebfe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release files / bazalt-0.10.0-cp310-cp310-win_amd64.whl

Download URL bazalt-0.10.0-cp310-cp310-win_amd64.whl
Size 2.6 MB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
f5d72d83952463846e5246d174c144fe4f8e9de4420e6c9c98a520998e93ec5e
BLAKE2b-256 checksum
How to use checksums
9c841d08e0ff6ed3d1ccbc7c082be318cf26abf673a47358856a6c167e607cca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Release files / bazalt-0.10.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Download URL bazalt-0.10.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Size 4.5 MB
Tags CPython 3.10 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
d9f8dd9d5c7282d118396d2e1a358d30665e0e8a861ec36f8834bcb90d0fa513
BLAKE2b-256 checksum
How to use checksums
2c66a6325d765a5ae9b0cc945f3bbf46dbcfea6412247cf7694691b5f3500e7d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

Security for bazalt 0.10.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 8 files in this release have been uploaded with provenance metadata.

Select from 8 files

Attestation for bazalt-0.10.0-cp313-cp313-win_amd64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.10.0 This release

8 release files Full provenance

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