Skip to main content

Python library for rapid GPU shader prototyping using Vulkan

Project description

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.
  • Automatic Barriers: Hazards between resources (dispatch → dispatch, compute-written buffer → vertex fetch) 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.
  • 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: 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)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

bazalt-0.7.0-cp313-cp313-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.13Windows x86-64

bazalt-0.7.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bazalt-0.7.0-cp312-cp312-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.12Windows x86-64

bazalt-0.7.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bazalt-0.7.0-cp311-cp311-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.11Windows x86-64

bazalt-0.7.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

bazalt-0.7.0-cp310-cp310-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.10Windows x86-64

bazalt-0.7.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (4.5 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

File details

Details for the file bazalt-0.7.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: bazalt-0.7.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for bazalt-0.7.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 ebad10e1bfb672c19f1913cd5d705a75d4487000af252c7cc5aafefb30597d98
MD5 0cf718d338386314356fe4140026200f
BLAKE2b-256 a7c3c084147932b4c0f874d55af6c0fc6b849b09ed14e0bc23b17a601d8fb245

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.7.0-cp313-cp313-win_amd64.whl:

Publisher: build.yml on SzamockiP/bazalt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bazalt-0.7.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bazalt-0.7.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 098f7350bae69ff55262ba54e0f376da361b3e8080d5c8c0e540b4242b2627e2
MD5 695ea0865265d8f9e83d24f12f476511
BLAKE2b-256 5d8c1bb61528ea50a12f05566a0a8927d44c799d995b1a67a1e4403375e7c1a6

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.7.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: build.yml on SzamockiP/bazalt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bazalt-0.7.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: bazalt-0.7.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for bazalt-0.7.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 fcf56e511889ee369e33d42e79cb067b2526f1e463d06f9430a137e9ad9b3d5d
MD5 a5b9e9dadf873670ec3f9662e3aafba4
BLAKE2b-256 2b0466508e0409a7b87397a3a0cf73c87d6b2211dcc6bff1761461c415818643

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.7.0-cp312-cp312-win_amd64.whl:

Publisher: build.yml on SzamockiP/bazalt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bazalt-0.7.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bazalt-0.7.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 54abed9c872e9ae39935cf6941e87de664b33d361bb2072a83d774a8f8ece2c3
MD5 f4c4bff7322ffe660709808df316a10b
BLAKE2b-256 e0581539ccc51ba65ba7fc5cc097a1390c7e5889fbda9d2912fd1e703a57e185

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.7.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: build.yml on SzamockiP/bazalt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bazalt-0.7.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: bazalt-0.7.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for bazalt-0.7.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 0f21392f6bf06035179dc564016ec2031d2aeefe2bb7ac8e18b27e2ae3b07f53
MD5 3d85a56546fc3813deb33e346265e8cd
BLAKE2b-256 ceebbc4dba48e8dc48e5070ed85cb1d3e71cb5dbdc298ea4e1201c5c0a09dd69

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.7.0-cp311-cp311-win_amd64.whl:

Publisher: build.yml on SzamockiP/bazalt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bazalt-0.7.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bazalt-0.7.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7a6a982852e38d69821b673b54e22d546bf143bea7d2e693f0ca90602ddec7e2
MD5 5c301289db6c3a077cf6488d29c31d2e
BLAKE2b-256 1531eb6075f1b42de036541092c4c267eb80068efc5f21ea4f1ae141d710d1a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.7.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: build.yml on SzamockiP/bazalt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bazalt-0.7.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: bazalt-0.7.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for bazalt-0.7.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 ce624d8a93f6b47202475886f6a5600b6ab2b7a530006f1daf97155dd7e24878
MD5 935c8212a53d53633e32673c95f646d3
BLAKE2b-256 6d48a5f5c41cf8c4d91dde1a8bf43330a439a1f6960cc3f8dc79296b287020f3

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.7.0-cp310-cp310-win_amd64.whl:

Publisher: build.yml on SzamockiP/bazalt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bazalt-0.7.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bazalt-0.7.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e68a88e2480f1333df0f8d161636c4c14fb387adefae65f548054e9c601c2dd0
MD5 91368acdbb15037d31a4424563e6cebf
BLAKE2b-256 f5d54576cb6bdc57749e781e3cc47ac4e921e3177c2acb01e19e9f0116bbc3e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.7.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: build.yml on SzamockiP/bazalt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page