1 Systems
dxtr edited this page 2026-10-18 19:16:46 +02:00

Systems

The systems

System What it is Depends on
clsl The language, its definitions and programs, and clsl's conditions, in the package clsl; and the IR they compile through, clsl/ir. cl-threads, for the lock definitions are made under
clsl/spirv SPIR-V, clsl/spirv: the grammar's tables, the module builder, the reader and the disassembler; and the back end, clsl/spirv-back-end, which translates the IR into SPIR-V. clsl
clsl/vulkan The :vulkan target: SPIR-V 1.6 under Vulkan 1.4's rules. Programs load this system and use the package clsl. clsl, clsl/spirv
clsl/gmath cl-gmath's types and functions in shader code, meaning what they mean in Lisp. clsl, cl-gmath
clsl/generator A build-time tool that writes spirv/grammar.lisp from the grammar files in grammar/. jzon
clsl/test The test suite. all of the above, cl-gfx, cl-gfx/vulkan, cl-vk, cl-gmath and Parachute

clsl/glsl, which prints GLSL, and clsl/opengl, for OpenGL 4.5 and later, come later.

clsl is plain Common Lisp, for SBCL. Loading it needs no foreign library, no glslang and no JSON library, and nothing in it needs setting up again when a saved image starts. The grammar's tables, which clsl/generator writes, are committed in spirv/grammar.lisp, so only the generator itself needs jzon. The tests need SPIRV-Tools and a Vulkan driver beside, as Development and Testing says. The dependencies are pinned by commit in clsl's stiftfile, with stift.

The packages

Package Use
clsl Everything programs use: the definitions, programs, packing, conditions, and the language's own names. Use it beside common-lisp.
clsl/ir The IR, for back ends, targets, tools and tests. Programs never need it. See The IR.
clsl/spirv SPIR-V, which knows nothing of clsl's IR or language and may be used on its own. See SPIR-V.
clsl/spirv-back-end The back end, whose entry point is translate-module, and spirv-target. See Targets.
clsl/vulkan Exports vulkan-target alone, for back ends and tests; programs name the target :vulkan.
clsl/gmath Exports nothing. Loading clsl/gmath is enough.
clsl/generator The grammar generator. See Grammar and Generator.

clsl/language, the language's implementation, and clsl/sys, which holds the little code that is SBCL's own, the bits of floats and float arithmetic with its traps masked, are internal. clsl/test holds the tests.

The API Reference lists the exports of clsl, clsl/vulkan and clsl/gmath, and the IR and SPIR-V Reference those of the others.

cl-gmath in shader code

Loading clsl/gmath makes cl-gmath's types type aliases of clsl's, and its functions shader functions and shader macros of their names, which compute what they compute in Lisp:

(asdf:load-system :clsl/gmath)

(define-function lambert ((normal cl-gmath:vec3) (light cl-gmath:vec3))
  "How much LIGHT, a direction of length 1, falls on a surface facing NORMAL."
  (max (cl-gmath:vec3-dot (cl-gmath:vec3-normalize normal) light) 0))

(define-shader lit :fragment ((normal :vec3) &uniform (light :vec3) (rotation cl-gmath:quat))
  (let ((turned (cl-gmath:quat-rotate rotation light)))
    (vec4 (vec3 (lambert normal turned)) 1)))

(mapcar (lambda (uniform) (list (uniform-name uniform) (uniform-type uniform)))
        (program-uniforms (compile-program '(:fragment lit) :target :vulkan)))
;; => ((LIGHT :VEC3) (ROTATION :VEC4))
cl-gmath's type Is
vec2, vec3, vec4 :vec2, :vec3, :vec4
quat a :vec4 of x, y, z and w, the real part
mat3, mat4 :mat3, :mat4
mat3x2 a 2D affine transform: a :mat3x2, of 3 columns of 2, the x axis, the y axis and the origin
dvec2, dvec3, dvec4, dquat, dmat3, dmat4, dmat3x2 the same of doubles

A function takes the arguments it takes in Lisp, less result, as values are copied: (setf v (cl-gmath:vec3+ a b)) stores a sum. Its scalars are :float values, or :double values for the doubles' functions, and numbers written in the code fit them. The accessors, as cl-gmath:vec3-x and cl-gmath:mref, are places.

Shader code cannot signal an error: where cl-gmath signals a gmath-error for arguments that have no answer, as the inverse of a singular matrix or a zero quaternion normalised, shader code computes the same formulas, which give what the GPU gives. The doubles' functions that need trigonometry, such as cl-gmath:dquat-slerp, and the batch functions refuse to expand, saying why:

In SLERP: The macro CL-GMATH:DQUAT-SLERP could not expand (CL-GMATH:DQUAT-SLERP
A B 0.5d0): CL-GMATH:DQUAT-SLERP is refused in shader code: it takes the arc
cosine and sine of doubles, which GPUs compute of floats only: QUAT-SLERP of
the quaternions made floats, with (float q 1.0), computes them of floats.
  in: (CL-GMATH:DQUAT-SLERP A B 0.5d0)

shader-documentation of a function says what it computes:

(shader-documentation 'cl-gmath:vec3-angle)
;; => "The shader form of CL-GMATH:VEC3-ANGLE: the angle between A and B, from 0 to pi, by
;;    Kahan's formula, 2 atan2 (|A |B| - B |A||, |A |B| + B |A||); 0 if either is zero."

A package that uses both clsl and cl-gmath chooses between the names both export with :shadowing-import-from: vec2 to vec4, dvec2 to dvec4, mat3, mat3x2, mat4, dmat3, dmat3x2, dmat4, clamp, smoothstep, radians and degrees. With clsl/gmath loaded, either's means the same in shader code.