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.6.0-cp313-cp313-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.13Windows x86-64

bazalt-0.6.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.6.0-cp312-cp312-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.12Windows x86-64

bazalt-0.6.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.6.0-cp311-cp311-win_amd64.whl (2.5 MB view details)

Uploaded CPython 3.11Windows x86-64

bazalt-0.6.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.6.0-cp310-cp310-win_amd64.whl (2.5 MB view details)

Uploaded CPython 3.10Windows x86-64

bazalt-0.6.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.6.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: bazalt-0.6.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.6.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 8935b710148965e915143b98aaa6336cb910fc5f01892c64bbebba91afc7f085
MD5 27677f8c97a82eaa0a4f92b595312088
BLAKE2b-256 8062c5759500707c81ddb5ace1ad0c2b779b5a48cce89b25263bbbab4610d8ea

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.6.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.6.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bazalt-0.6.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c69f089a931c4f6e043219095a4b31b0fe6c1a93a8d35c55970aac72b606b87e
MD5 f9ee5002a5900b10109cf8106035f368
BLAKE2b-256 0924445606f38f98e92353c96420c738d820d584cdb8b42be168f6fbadc26f75

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.6.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.6.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: bazalt-0.6.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.6.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 18e2a767150a43c2fd20c82fab84dc7f0c5dedbde8e7ab4303ec168c0cced9f3
MD5 5b3a01eac2921023c3fa5fc8d4359f8d
BLAKE2b-256 ec3a5341f62c1d6562af69e91486bbaaea99ed3ade3b306d87ffc627c4b9e6ee

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.6.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.6.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bazalt-0.6.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 bdda79dba9b63370dd75816fbe8bde38302bf0be7fb4785f0696b6278f2fa839
MD5 1ced3fa7bc71ecebe2f01b019cf9d085
BLAKE2b-256 9a47407819a92b0351738e5a692a277e30c16752979d372aa87aa2a7ad256efd

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.6.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.6.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: bazalt-0.6.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 2.5 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.6.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 d34d4306e583406fc22e8ad5fb9e2ce7d2e2668b2e85419bc2337238d5908f36
MD5 4b1d76f1e3d4ec23e5e8f720a850335a
BLAKE2b-256 4403ad8bf2fce1b8b44ddea29ab4937caefad3b55bcf2b97554dbd78bb7f220d

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.6.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.6.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bazalt-0.6.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 bce7cc3eec9f6902ae5341cfd575a0216ca0e0f19bf367073bfa879db6c05893
MD5 af351342cd61f1477a48beb04d8dbe81
BLAKE2b-256 fd7e2e3151df6ea68effee1cac3ff09b9e0282ac6e0fae68c6a258e0efea0068

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.6.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.6.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: bazalt-0.6.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 2.5 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.6.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 98f0e6089667ca44b214a3333f0728021ceba75e4c650ed3cb30c3cdf0b75f13
MD5 11b8bc8fd9593031bcbdb98b0e5c9e4f
BLAKE2b-256 6298bf75368e9e2aec17a9fc28d356cfa13c7d4732967a26ced4cee908be9992

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.6.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.6.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for bazalt-0.6.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 003f3d53047bbfca721fa40bd40a266d10fdb91eb70e81e91c87ca06022198ac
MD5 965e7eb8301be9703572af6c8ed447cb
BLAKE2b-256 c20b28c4788a169b8501e0576d58be3f6465d03ad18b9095fe997578561c7b51

See more details on using hashes here.

Provenance

The following attestation bundles were made for bazalt-0.6.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