2 Errors
dxtr edited this page 2026-10-18 19:28:17 +02:00

Errors

Every error clsl signals is a clsl-error, whose message, clsl-error-message, says what went wrong and what to do about it, in the terms of the shader code. A mistake in shader code is found when its definition is evaluated, not by a driver: the error names the definition and the form at fault, and the definition before it stays.

The conditions

Condition Is a Signalled for Readers
clsl-error error every error clsl signals clsl-error-message
shader-error clsl-error shader code clsl refuses, or stages that do not fit together shader-error-definition, shader-error-form
undefined-shader-function shader-error a call of a function neither built into the language nor defined, when a program is compiled undefined-shader-function-name
no-target-error clsl-error a target no system loaded has defined; the message names the system to load no-target-error-target
unsupported-error clsl-error what a target cannot express unsupported-error-feature, unsupported-error-form
internal-error clsl-error invalid IR or SPIR-V made of shaders clsl had accepted: a bug in clsl internal-error-ir
clsl/ir:ir-error clsl-error IR that breaks the IR's rules: by the verifier, the reader of the external form, or the builder clsl-error-message
clsl/spirv:spirv-error clsl-error SPIR-V that SPIR-V's grammar does not allow clsl-error-message
clsl/generator:grammar-error error a grammar file that is not well-formed JSON, or not of the grammar's format grammar-error-source, grammar-error-context, grammar-error-message

And the warnings:

Condition Is a Signalled for Readers
forward-reference-warning style-warning a definition that calls a shader function not defined yet; the definition is made forward-reference-warning-definition, forward-reference-warning-name
program-warning warning a redefinition after which a program define-program defined no longer compiles; the redefinition is made program-warning-program, program-warning-error
uniformity-warning warning a derivative or texture read, declared a warning, that may run where control flow is not uniform; compile-program signals it uniformity-warning-definition, uniformity-warning-form, uniformity-warning-message

Shader errors

A shader-error's report names the definition, gives the message, and quotes the form at fault; clsl-error-message is the message alone:

(handler-case (define-function half ((n :int))
                (/ n 2))
  (shader-error (error)
    (list (princ-to-string error)
          (clsl-error-message error)
          (shader-error-definition error)
          (shader-error-form error))))
;; => ("In HALF: / of integers is a ratio in Lisp, and clsl has no ratios: divide with TRUNCATE, FLOOR, CEILING or ROUND, which give integer quotients, or make the integers floats with FLOAT.
;;      in: (/ N 2)"
;;     "/ of integers is a ratio in Lisp, and clsl has no ratios: divide with TRUNCATE, FLOOR, CEILING or ROUND, which give integer quotients, or make the integers floats with FLOAT."
;;     HALF
;;     (/ N 2))

Some of what the language refuses, with each message, or the part of it that matters:

Code Message
(/ n 2) of an :int / of integers is a ratio in Lisp, and clsl has no ratios: divide with TRUNCATE, FLOOR, CEILING or ROUND, ...
(+ x i) of a :float and an :int + takes numbers of one type, :INT, :UINT, :FLOAT, :DOUBLE or :DFLOAT, ... not :FLOAT, :INT.
(* x 1d0) of a :float ... 1.0d0 is a double-float, so in Lisp the result would be a double: write 1.0 for a :FLOAT, or make the floats :DOUBLEs with (float x 1d0).
1/3 1/3 is a ratio, and clsl has no ratios, ... write 0.33333334, or (/ 1.0 3.0), ...
(+ 1 4294967296) 4294967297 does not fit in 32 bits, as clsl's integers do.
(vec3 i 0 0) of an :int VEC3 takes :FLOATs and vectors of them with 3 components in all, one :FLOAT, or a vector of more of them, not :INT, 0, 0.
(int x) of a :float INT takes integers. A float becomes an integer through a function that names its rounding: (truncate x), (floor x), (ceiling x) or (round x).
(sin d) of a :double SIN takes a :FLOAT, or a vector of them, or a :COMPLEX, not :DOUBLE. GPUs compute it of :FLOATs only: ...
(aref v 3) of a :vec3 :VEC3 has 3 components, from 0 to 2, and none at 3.
(floor a 0) FLOOR divides an integer by zero, whose quotient Lisp does not define: ...
(multiple-value-bind (a b c) (floor x) ...) MULTIPLE-VALUE-BIND takes 3 values, but (FLOOR X) gives 2 values: in Lisp the others would be NIL, which no type of a shader holds.
(return 1) outside a loop RETURN leaves the innermost DOTIMES or LOOP around it, and there is none here. A shader function gives the value of its last form.
(setf i 2) of a dotimes variable I counts the iterations of its DOTIMES, and Common Lisp leaves it to each implementation what assigning it does: bind a variable of your own with LET, and assign that.
a function that calls itself NO-RECURSION calls itself, through other functions or not, and shader code cannot recurse.
(x :vec5) in a parameter list :VEC5 is not a type of clsl's language. Types are keywords such as :FLOAT, :IVEC2, :VEC3, :MAT4 and :SAMPLER2D; ...
&uniform of a package that does not use clsl &UNIFORM is not CLSL:&UNIFORM, which starts the uniforms: write clsl:&uniform, or use the package CLSL.
a built-in of another stage FRAGMENT-COORD belongs to fragment shaders, and PIXEL-X, which uses it, is called by the vertex shader WRONG-STAGE.
stages that do not fit The vertex shader COLORED-VERTEX passes :VEC3 to the fragment shader MISFIT-FRAGMENT, which takes :VEC4: ...
a derivative in a branch (FWIDTH UV) computes a derivative, which the fragments of a quad compute together, so it needs uniform control flow; ...
an atomic of a float ATOMIC-INCF changes an :INT or a :UINT, and (AREF SUMS 0) is :FLOAT.
a write to :storage :read SUMS is a storage buffer of :STORAGE :READ, which shader code reads but never writes: give it :STORAGE :READ-WRITE to write it.
(compile-program 'no-such-program ...) There is no program called NO-SUCH-PROGRAM: define it with DEFINE-PROGRAM, or give COMPILE-PROGRAM its stages, ...

Most are shown in full, with their code, on the page of their topic.

Undefined functions and forward references

A call of a shader function not defined yet is no error when the definition is evaluated: the definition is made, and signals a forward-reference-warning, whose forward-reference-warning-definition calls its forward-reference-warning-name. Compiling a program that still calls it signals an undefined-shader-function:

(define-shader toned :fragment ((color :vec3))
  (vec4 (gamma-correct color) 1))

(handler-case (compile-program '(:fragment toned) :target :vulkan)
  (undefined-shader-function (error)
    (list (undefined-shader-function-name error) (shader-error-definition error)
          (shader-error-form error))))
;; => (GAMMA-CORRECT TONED (GAMMA-CORRECT COLOR))

Program and uniformity warnings

A program-warning says that a program no longer compiles after a redefinition, which is made, so that a change to several stages can be made a stage at a time. program-warning-program is the program's name, and program-warning-error the shader-error compiling it would signal. See Programs.

A uniformity-warning comes from compile-program, for a derivative or texture read in a body declared (derivative-uniformity :warning). The program is compiled, and its results are undefined where control flow is not uniform after all. See Uniform Control Flow.

Both are warnings: muffle-warning silences them in a handler-bind.

Targets

A no-target-error names the system that defines the target, or lists clsl's targets:

The target :VULKAN is not loaded: load the system clsl/vulkan, which defines it.

An unsupported-error says what a target cannot express: unsupported-error-feature names what the target lacks, such as "the capability Float64", and unsupported-error-form is the form that needs it, or nil where no one form does, as for a type. :vulkan allows the capabilities Vulkan 1.4 allows; Targets shows the error of a target that allows fewer.

An internal-error is a bug in clsl: clsl made invalid IR or SPIR-V of shaders it had accepted. internal-error-ir is the external form of the IR it was compiling, for the report: please report it with the shaders' definitions.

Packing and the program's readers

The functions that write uniform blocks and read programs signal a clsl-error for what does not fit. With

(define-shader tinted :fragment ((color :vec3) &uniform (tint :vec4))
  (* (vec4 color 1) tint))

(define-struct lamp
  (power :float))

and program the program (compile-program '(:fragment tinted) :target :vulkan):

Call Message
(pack-uniforms program :material :values '()) PACK-UNIFORMS has no value for the uniform TINT of the group :MATERIAL: give it in :VALUES, as (:TINT value).
(pack-uniforms program :material :values '(:tintt #(1.0 1.0 1.0 1.0))) PACK-UNIFORMS has a value for :TINTT, which is no uniform of the blocks of #<PROGRAM :fragment TINTED for :vulkan {120206BC33}>: their uniforms are :TINT.
(pack-uniforms program :material :values '(:tint 1.0)) 1.0 is not a value of :VEC4, which is a sequence of 4 components.
(pack-uniforms program :material :values '(:tint #(1.0 1.0 1.0 1.0)) :buffer (make-array 4 :element-type '(unsigned-byte 8))) The :MATERIAL block of #<PROGRAM :fragment TINTED for :vulkan {1201B736C3}> is 16 bytes, and the buffer has 4.
(program-spirv program :vertex) #<PROGRAM :fragment TINTED for :vulkan {1202391953}> has no vertex shader: its stages are :fragment.
(pack-value :vec3 #(1.0 2.0) (make-array 16 :element-type '(unsigned-byte 8))) #(1.0 2.0) is not a value of :VEC3, which is a sequence of 3 components.
(dfloat-parts 1d300) 1.0d300 is beyond the range of float pairs, whose high part is a :FLOAT, at most 3.4028235e38 in magnitude.
(remove-definition 'make-lamp) MAKE-LAMP is a function of the struct LAMP, which goes with it: remove the struct, LAMP.

Type errors

Every exported function declares the types of its arguments, which SBCL checks as the function is entered. An argument of the wrong type, or a keyword outside its documented choices, signals a standard type-error that names the argument and the type it takes. SBCL may list a type's choices in another order:

(pack-uniforms program group)       ; GROUP being :MATERAL
The value
  :MATERAL
is not of type
  (MEMBER :DRAW :MATERIAL :FRAME)
when binding CLSL/LANGUAGE::GROUP

Written as a constant, such an argument is caught sooner: SBCL warns as it compiles the call.

(pack-uniforms program :materal)
; caught WARNING:
;   Constant
;     :MATERAL conflicts with its asserted type
;     (MEMBER :DRAW :MATERIAL :FRAME).

The lower layers

The IR's verifier, its reader and its builder signal an ir-error, which names the function and the statement at fault, as the external form writes them, and what would fit:

In the function MAIN, (%1 (:ADD (:UINT 1) (:INT 2))): :add takes two operands
of one type, integers or floats, scalars or vectors; they are :uint and :int.

The SPIR-V layer signals a spirv-error for a name its grammar lacks, an operand its instruction does not take, or an instruction where SPIR-V's layout does not allow it:

SPIR-V has no instruction :FADD.  Did you mean :F-ADD?
OpTypeInt's operand 3, Signedness, should be an unsigned 32-bit integer, not
:SIGNED.

The generator signals a grammar-error, its own, which is no clsl-error. Its report is the file, where in the grammar, and what is wrong: grammar-error-source is the file read, or nil for a string, grammar-error-context where in the grammar the problem is, outermost first, and grammar-error-message what is wrong:

The JSON is not well-formed: End of input when reading object. Expecting comma
or object close, at line 1, column 26.

The IR, SPIR-V and Grammar and Generator say more.