8 API Reference
dxtr edited this page 2026-10-18 16:56:34 +02:00

API Reference

Every symbol a program uses, exported from cl-gfx. Symbols for writing backends are on Backend Protocol; types and constants are on Formats and Types. Every function's docstring says the same in more detail: (describe 'gfx:create-texture).

Thread rules for everything here: a device and every object made from it belong to one thread, the render thread.

Devices

open-device

(open-device &key (backend :vulkan) present-to validation validation-checks
                  (frames-in-flight 2) (application-name ""))
=> device

Opens a GPU. See Devices and Frames. Signals no-backend-error or unsupported-error.

close-device

(close-device device) => (no values)

Waits for the GPU, destroys every object still alive, and closes the device. Signals an error during a frame.

with-device (macro)

(with-device (variable &rest open-device-options) &body body)

Binds variable to an opened device and closes it however body is left.

Device accessors

Function Returns
(device-backend device) The backend keyword, such as :vulkan.
(device-name device) The GPU's name, as its driver gives it.
(device-frames-in-flight device) How many frames may be in flight.
(device-features device) The device-features it has.

take-validation-messages

(take-validation-messages device &key (minimum-severity :verbose))
=> list of (severity . text)

Returns and forgets the validation messages since the last call, oldest first, keeping those at least as severe as minimum-severity, a validation-severity: what validation says of the program's use of the API, not the loader's notes on the machine. See Errors and Validation.

Objects

device-object (class)

The base class of surfaces, buffers, textures, samplers, shader modules, bind group layouts, bind groups, pipelines and render bundles.

Function Returns
(object-device object) The device it was made from.
(object-alive-p object) False once it has been destroyed.

Every destroy- function marks its object destroyed at once and releases it once no frame in flight uses it. Using a destroyed object signals destroyed-error.

Surfaces

create-surface

(create-surface device target &key (present-mode :fifo) (srgb t)) => surface

A surface presenting to target, such as a cl-windowing window. See Surfaces and Windows.

destroy-surface

(destroy-surface surface) => (no values)

Destroy surface at once, waiting first for the GPU to finish the frames in flight, so that what it presents to, such as a window, may be destroyed right after. Call it between frames: it signals gfx-error while a frame is recorded.

Surface accessors

Function Returns
(surface-format surface) The texture-format of its textures, for pipelines' :color-formats.
(surface-size surface) Two values: the width and height of its textures now.
(surface-target surface) What it presents to.

acquire-surface-texture

(acquire-surface-texture surface frame) => texture or nil

The texture to draw frame into, presented when the frame ends; nil when there is nothing to draw into, such as a window the window system has not given a size yet, or a minimised one. Allocates nothing in steady state.

Buffers

create-buffer

(create-buffer device &key size usage (memory :device)) => buffer

size in bytes; usage a non-empty list of :vertex, :index, :uniform, :storage, :uniform-texel, :storage-texel, :copy-src, :copy-dst; memory :device or :upload. See Buffers.

write-buffer

(write-buffer buffer data &key (offset 0) size) => (no values)

Writes data (a vector of single-floats, double-floats or 8-, 16- or 32-bit unsigned integers, or a foreign pointer with :size) at offset bytes. data may be reused when it returns.

read-buffer

(read-buffer buffer &key (offset 0) size (element-type '(unsigned-byte 8)))
=> vector of element-type

Waits for the GPU and returns the contents as a vector of element-type, a data-element-type: single-float, double-float, or (unsigned-byte 8), 16 or 32. Between frames only; needs :copy-src.

destroy-buffer

(destroy-buffer buffer) => (no values)

Buffer accessors

buffer-size, buffer-usage, buffer-memory.

Textures

create-texture

(create-texture device &key width (height 1) (depth 1) (array-layers 1) (dimension :2d)
                            (mip-levels 1) (samples 1) format usage)
=> texture

:width, :format and :usage are required. See Textures and Samplers.

write-texture

(write-texture texture data &key (x 0) (y 0) (z 0) width height depth (level 0))
=> (no values)

Writes texels from a vector, as write-buffer takes it, or a foreign pointer into a region of a mip level, by default all of it. Needs :copy-dst.

read-texture

(read-texture texture &key (level 0) (element-type '(unsigned-byte 8)))
=> vector of element-type

Waits for the GPU and returns every texel of a mip level, as read-buffer returns them. Between frames only; needs :copy-src.

generate-mipmaps

(generate-mipmaps texture) => (no values)

Fills every mip level after the first from the first.

destroy-texture

(destroy-texture texture) => (no values)

Texture accessors

Function Returns
texture-width, texture-height, texture-depth Size in texels. Depth is 1 except for :3d.
texture-array-layers Layers of an array texture, else 1.
texture-layer-count Layers as write-texture's :z and a pass's :layer count them: 6 per cube.
texture-dimension Its texture-dimension.
texture-mip-levels Number of mip levels.
texture-samples Samples per texel.
texture-format Its texture-format.
texture-usage Its usage list.

Samplers

create-sampler

(create-sampler device &key (filter :linear) (address-mode :clamp-to-edge)
                            (mipmap-filter :nearest) compare (max-anisotropy 1))
=> sampler

destroy-sampler

(destroy-sampler sampler) => (no values)

Sampler accessors

sampler-filter, sampler-address-mode, sampler-mipmap-filter, sampler-compare, sampler-max-anisotropy.

Bind groups

create-bind-group-layout

(create-bind-group-layout device entries) => bind-group-layout

Each entry is (binding kind &key visibility), visibility by default every stage the device runs. See Bind Groups.

destroy-bind-group-layout

(destroy-bind-group-layout layout) => (no values)

bind-group-layout-entries

(bind-group-layout-entries layout) => list of (binding kind visibility)

create-bind-group

(create-bind-group device layout entries) => bind-group

One entry per binding: (binding buffer &key offset size), (binding buffer :format format &key offset size), (binding texture sampler) or (binding texture). The layout and the resources must come from device.

destroy-bind-group

(destroy-bind-group group) => (no values)

Bind group accessors

Function Returns
(bind-group-layout group) The layout it was made for.
(bind-group-textures group) A simple vector of the textures it holds.

Shaders and pipelines

create-shader-module

(create-shader-module device spirv) => shader-module

spirv is a pathname or namestring of a .spv file, or a vector of 32-bit words or of bytes.

destroy-shader-module

(destroy-shader-module module) => (no values)

create-render-pipeline

(create-render-pipeline device &key vertex tessellation-control tessellation-evaluation
                                    geometry fragment
                                    (vertex-entry "main") (tessellation-control-entry "main")
                                    (tessellation-evaluation-entry "main")
                                    (geometry-entry "main") (fragment-entry "main")
                                    vertex-buffers (topology :triangle-list) patch-size
                                    color-formats depth-format
                                    (depth-compare :less) (depth-write t) (samples 1)
                                    (cull-mode :none) (front-face :counter-clockwise)
                                    (blend :replace) bind-group-layouts)
=> render-pipeline

blend is :replace, :alpha or :premultiplied-alpha. See Shaders and Pipelines.

create-compute-pipeline

(create-compute-pipeline device &key module (entry "main") bind-group-layouts)
=> compute-pipeline

destroy-render-pipeline, destroy-compute-pipeline

(destroy-render-pipeline pipeline) => (no values)
(destroy-compute-pipeline pipeline) => (no values)

Frames

begin-frame, end-frame

(begin-frame device) => frame
(end-frame frame) => (no values)

begin-frame waits for the frame that last used this slot. end-frame submits and presents. Both allocate nothing in steady state.

with-frame (macro)

(with-frame (frame device) &body body)

Ends the frame however body is left.

frame-number, frame-slot

(frame-number frame) => integer
(frame-slot frame) => integer

frame-number counts the frames of the device from 0, as begin-frame numbers them; it has no writer. frame-slot is the frame's slot among the frames in flight, from 0 below device-frames-in-flight, for per-frame regions of :upload buffers.

Render passes

with-render-pass (macro)

(with-render-pass (pass frame &key color depth) &body body)

color is a list of (texture &key clear level layer resolve); depth is (texture &key clear level layer). Written out at macroexpansion time, so it allocates nothing. Ends the pass however body is left.

begin-render-pass, end-render-pass

(begin-render-pass frame &key color depth) => render-pass
(end-render-pass pass) => (no values)

The same, with attachment lists evaluated at run time.

Draw commands

(set-pipeline pass pipeline)
(set-bind-group pass index group)
(set-vertex-buffer pass slot buffer &optional (offset 0))
(set-index-buffer pass buffer format &optional (offset 0))
(set-viewport pass x y width height &key (min-depth 0.0) (max-depth 1.0))
(set-scissor pass x y width height)
(draw pass vertex-count &key (instance-count 1) (first-vertex 0) (first-instance 0))
(draw-indexed pass index-count &key (instance-count 1) (first-index 0)
                                    (base-vertex 0) (first-instance 0))
(execute-render-bundle pass bundle)

Each returns no values and allocates nothing. index is a bind-group-index; slots, counts, firsts and the scissor's size are 32-bit unsigned integers, the scissor's x and y below 2³¹ and base-vertex a signed 32-bit integer; offsets are 64-bit; min-depth and max-depth are from 0 to 1. See Render Passes and Bundles.

Render bundles

create-render-bundle

(create-render-bundle device) => render-bundle

destroy-render-bundle

(destroy-render-bundle bundle) => (no values)

record-render-bundle (macro)

(record-render-bundle (encoder bundle) &body body)

Binds encoder, which takes draw commands, and replaces the bundle's contents with what body records.

Compute passes

with-compute-pass (macro)

(with-compute-pass (pass frame) &body body)

begin-compute-pass, end-compute-pass

(begin-compute-pass frame) => compute-pass
(end-compute-pass pass) => (no values)

dispatch

(dispatch pass x &optional (y 1) (z 1)) => (no values)

x, y and z are 32-bit unsigned integers. Plus set-pipeline and set-bind-group, as for render passes. See Compute.

Surface target protocol

Generic functions a surface target implements. See Surfaces and Windows.

(surface-target-size target) => width, height
(surface-target-pending-size target) => width, height  or  nil, nil
(surface-target-adopt-size target) => width, height

surface-target-size returns 0 and 0 while nothing may be drawn into the target, and acquire-surface-texture then returns nil.

Conditions

Condition Readers
gfx-error gfx-error-message
no-backend-error no-backend-error-backend
unsupported-error
destroyed-error destroyed-error-object

See Errors and Validation.

Classes

device, device-object, surface, buffer, texture, sampler, shader-module, bind-group-layout, bind-group, render-pipeline, compute-pipeline, render-bundle, frame, render-pass, compute-pass. Each backend makes subclasses of these; don't make instances yourself.