luv

Workshop wiki

tests.lisp

hal/shader/tests.lisp

system luvcraft/core/test · 90 definitions · on GitHub

defpackage#:luvcraft.tests
:use#:cl#:rove#:luv#:luvcraft#:luvcraft.world
:local-nicknames
#:shader#:luv.shader
#:spv#:luv.spir-v
#:shaders#:luvcraft.shaders
#:analytic#:luv.analytic
#:slug#:luv.slug
#:math#:luv.arithmetic
#:lang#:luv.arithmetic.language
#:msl#:luv.msl
#:wgsl#:luv.wgsl
#+darwin (#:objc #:luv.objective-c)#+darwin (#:metal #:luv.metal)
:import-from#:luv.arithmetic.lisp.vec3#:make-vec3#:vec3#:vec3-component#:vec3-cross#:vec3-dot#:vec3-length#:vec3-list#:vec3-normalize#:vec3-scale#:vec3-x#:vec3-y#:vec3-z

Shader operators are identified by symbol, so specification bodies written here must use the shader language's own words.

:import-from#:luv.shader#:dot#:sample#:sample-compare#:texel-load#:mix#:uint#:uvec2#:vec2#:vec4#:swizzle#:clamp#:smoothstep#:normalize#:quantity#:assume-quantity#:interpret#:representation#:convert-unit#:project-point#:project-sample#:counted-fold#:set-output
in-package#:luvcraft.tests
math:define-quantity:test-position:kind:dimensionless:components
:test-position-x:test-position-y:test-position-z
deftestshared-shader-vocabulary-has-neutral-symbol-homes
dolist
ok
eq
find-package'#:luv.shader
symbol-packagesymbol
multiple-value-bind
foundstatus
find-symbol
symbol-namesymbol
'#:luv.spir-v
ok
eqsymbolfound
ok
eq:inheritedstatus
ok
eq
find-package'#:luv.spir-v
symbol-package'spv:shader-lowering
ok
null
find-symbol"SHADER-LOWERING"'#:luv.shader
multiple-value-bind
instruction-dotstatus
find-symbol"DOT"'#:luv.spir-v
ok
eq:internalstatus
ok
eq
find-package'#:luv.spir-v
symbol-packageinstruction-dot
ok
not
eqinstruction-dot'shader:dot
ok
typep
find-classinstruction-dot
'spv:instruction-class
ok
null
find-class'shader:dotnil
let
foreign-instruction-namesnil
spir-v-package
find-package'#:luv.spir-v
do-symbols
symbolspir-v-package
let
class
find-classsymbolnil
when
and
not
eqspir-v-package
symbol-packagesymbol
pushsymbolforeign-instruction-names
ok
nullforeign-instruction-names
defunbinding-named
namespecification
findname
shader:shader-specification-bindingsspecification
:key#'shader:shader-object-name:test
lambda
leftright
string-equal
symbol-nameleft
symbol-nameright
defunform-names
form
cond
symbolpform
string-downcase
symbol-nameform
conspform
mapcar#'form-namesform
tform
defgenericshader-method-probe
rolestage
shader:define-shader-functiontyped-shader-function-probe
valuescale
"A lexical typed-function probe written without source-form construction."
let*
scaled
*shiftedscale
scaled
shader:define-shaderunsigned-texel-fold-probe
:stage:fragment:resources
band-data:uint-texture-2d:binding0
curve-data:texture-2d:binding1
:outputs
color:vec4:location0
let*
origin
header
texel-loadband-dataorigin
count
swizzleheader:x
offset
swizzleheader:y
seed
swizzle
texel-loadcurve-dataorigin
:x
total
counted-fold
indexcountsumseed
let*
address
+offsetindex
location
uvec2
modaddress
uint4096.0
/address
uint4096.0
word
swizzle
texel-loadband-datalocation
:x
+sum
floatword
set-outputcolor
vec4totaltotaltotal1.0
shader:define-task-payloadvulkan-task-mesh-payload
payload-site:uint64
payload-position
:array:vec432
shader:define-shadervulkan-task-probe
:stage:task:workgroup-size
3211
:payloadvulkan-task-mesh-payload:inputs
lane:uint:built-in:local-invocation-index
local-id:uvec3:built-in:local-invocation-id
group:uvec3:built-in:workgroup-id
group-count:uvec3:built-in:num-workgroups
threads:uvec3:built-in:workgroup-size
let*
when
shader:set-payloadpayload-site
shader:set-payload-elementpayload-positionlane
shader:vec40.00.00.01.0
shader:emit-mesh-workgroups
shader:define-shadervulkan-mesh-probe
:stage:mesh:workgroup-size
3211
:payloadvulkan-task-mesh-payload:inputs
lane:uint:built-in:local-invocation-index
group:uvec3:built-in:workgroup-id
:mesh-output
:topology:triangles:max-vertices32:max-primitives16:vertex
position:vec4:built-in:position
uv:vec2:location0
:primitive
primitive-color:vec4:location1
let*
vertex-count
shader:uintpayload-site
primitive-count
shader:set-mesh-output-countsvertex-countprimitive-count
when
<lanevertex-count
shader:set-mesh-vertexlane
position
shader:payload-elementpayload-positionlane
uv
when
shader:set-mesh-primitive
primitive-color
shader:vec41.01.01.01.0
lang:define-arithmetic-functionshared-fold-probe
count
counted-fold
indexcountsum0.0
+sumindex
lang:define-arithmetic-functionshared-conditional-fold-probe
count
limit
counted-fold
indexcountsum0.0
if
<indexlimit
+sumindex
sum
shader:define-shader-methodshader-method-probeshader-method-probe
role
eql:probe
stage
eql:fragment
:stage:fragment:outputs
color:vec4:location0
set-outputcolor
vec40.10.20.31.0
shader:define-shader-methodshader-abstraction-method-probeshader-abstraction-method-probe
role
eql:abstraction-probe
stage
eql:fragment
:stage:fragment:inputs
receiver:float:location0
depth:float:location1
bias:float:location2
:outputs
visibility:float:location0
let*
visible
test-shadow-rewritereceiverdepthbias
set-outputvisibilityvisible
deftestshader-method-redefinition-is-observable-and-coalesced
let*
generic-function
dependent
shader:make-shader-definition-dependentgeneric-function'
:probe:fragment
unwind-protect
progn
eval'
shader:define-shader-methodshader-method-probeshader-method-probe
role
eql:probe
stage
eql:fragment
:stage:fragment:outputs
color:vec4:location0
set-outputcolor
vec40.80.40.21.0
ok
=1
length
closer-mop:generic-function-methodsgeneric-function
multiple-value-bind
revisionevent

Replacement emits REMOVE-METHOD and ADD-METHOD on the pinned SBCL/Closer-MOP stack. Consumers see their coalesced revision.

ok
>=revision2
ok
eq
firstevent
'add-method
ok
equal
form-names
shader:shader-expression-form
shader:shader-assignment-value
first
shader:shader-specification-statements
shader-method-probe:probe:fragment
'
"vec4"0.80.40.21.0
deftestshader-functions-are-typed-calls-with-lexical-bindings
let*
specification
shader:parse-shader-specification'typed-shader-function-specification'
:stage:fragment:inputs
value:float:location0
scale:float:location1
:outputs
result:float:location0
'
call
shader:shader-assignment-value
first
shader:shader-specification-statementsspecification
ok
search"without source-form construction"

Two parameter aliases and two lexical let* bindings remain typed objects. Only computed locals need entry-block declarations.

ok
=2
length
shader:shader-specification-bindingsspecification
ok
gethashcall
spv:shader-lowering-expression-instructionslowering
ok
=#x07230203
deftestshader-function-redefinition-affects-only-fresh-parses
labels
install-addition
eval'
shader:define-shader-functionredefinable-shader-function
leftright
+leftright
install-subtraction
eval'
shader:define-shader-functionredefinable-shader-function
leftright
-leftright
parse-probe
shader:parse-shader-specification'redefinable-shader-function-specification'
:stage:fragment:inputs
left:float:location0
right:float:location1
:outputs
result:float:location0
'
set-outputresult
redefinable-shader-functionleftright
result-operator
specification
let
call
shader:shader-assignment-value
first
shader:shader-specification-statementsspecification
install-addition
let
addition
parse-probe
install-subtraction
let
subtraction
parse-probe
ok
eq'+
result-operatoraddition
ok
eq'-
result-operatorsubtraction
ok
signals
shader:parse-shader-specification'bad-shader-function-arity'
:stage:fragment:inputs
left:float:location0
:outputs
result:float:location0
'
set-outputresult
redefinable-shader-functionleft
'shader:shader-language-error
deftesttop-level-shader-redefinition-advances-the-live-source-revision
flet
definition
macronamered
`
,macro,name
:stage:fragment:outputs
color:vec4:location0
set-outputcolor
vec4,red0.00.01.0
dolist
case'
shader:define-shaderrevision-static-stage-probe
shader:define-live-shaderrevision-live-stage-probe
destructuring-bind
macroname
case
deftestshader-source-name-can-migrate-from-rewriter-to-typed-function
eval'
shader:define-shader-abstractionsource-kind-migration-probe
value
`
+,value1.0
ok
shader:shader-abstraction-p'source-kind-migration-probe
eval'
shader:define-shader-functionsource-kind-migration-probe
value
+value1.0
ok
not
shader:shader-abstraction-p'source-kind-migration-probe
ok
shader:shader-function-definition-for'source-kind-migration-probe
let*
specification
shader:parse-shader-specification'source-kind-migration-specification'
:stage:fragment:inputs
value:float:location0
:outputs
result:float:location0
'
set-outputresult
source-kind-migration-probevalue
call
shader:shader-assignment-value
first
shader:shader-specification-statementsspecification
deftestshader-source-is-a-typed-clos-graph
let*
sun-direction
binding-named'sun-directionspecification
sun-visibility
binding-named'sun-visibilityspecification
direct-shadow
binding-named'direct-shadowspecification
reflected
binding-named'reflectedspecification
radiance
binding-named'radiancespecification
fogged
binding-named'foggedspecification
ok
typepspecification'shader:shader-specification
ok
eq
shader:shader-specification-stagespecification
:fragment
ok
=
length
shader:shader-specification-inputsspecification
9
ok
=
length
shader:shader-specification-resourcesspecification
7
ok
eq:world-direction
ok
shader:shader-type=
shader:shader-expression-type
:vec3
ok
equal'
"smoothstep"
"quantity"0.9"quantity""sky-light-level""unit""one"
"quantity"1.0"quantity""sky-light-level""unit""one"
"sky-input"

The map's answer is taken only where the surface faces the light; a surface turned away is lit by nothing, so it is also shadowed by nothing. #0604PY

ok
equal'
"mix"1.0"shadow-sample""shadow-in-bounds"
ok
equal'
"mix"1.0"sampled-shadow""shadow-relevance"
ok
equal'
"interpret"
"*""albedo"
"+""sky-light""sun-light""local-light"
"quantity""linear-rgb""unit""one"
ok
equal'
"+""reflected""specular"
"interpret"
"*""albedo""emission-input"
"quantity""linear-rgb""unit""one"
ok
equal'
"mix""radiance""fog-color""fog-amount"
dolist
binding
listsky-lightreflectedradiancefogged
ok
eq:absolute
ok
>
length
shader:shader-specification-bindingsspecification
deftestblock-vertex-source-is-a-typed-clos-graph-with-an-explicit-abi
let*
resource
first
shader:shader-specification-resourcesspecification
clip-position
find'clip-position
shader:shader-specification-outputsspecification
:key#'shader:shader-object-name:test
lambda
leftright
string-equal
symbol-nameleft
symbol-nameright
relative
binding-named'relativespecification
view-z
binding-named'view-zspecification
shadow-projection
binding-named'shadow-projectionspecification
ok
typepspecification'shader:shader-specification
ok
eq
shader:shader-specification-stagespecification
:vertex
ok
=
length
shader:shader-specification-inputsspecification
5
ok
=
length
shader:shader-specification-outputsspecification
10
ok
eq
shader:shader-interface-built-inclip-position
:position
ok
=
shader:shader-resource-bindingresource
2
ok
equal
mapcar
lambda
member
string-downcase
symbol-name
shader:shader-uniform-block-membersresource
'
"camera-vector""right-vector""up-vector""forward-vector""projection-vector""fog-vector""sun-vector""sun-color-vector""zenith-vector""horizon-vector""ambient-vector""fog-color-vector""shadow-control-vector""shadow-filter-vector""atlas-vector""shadow-row-x""shadow-row-y""shadow-row-z""shadow-row-w"
ok
equal
mapcar#'shader:shader-uniform-member-offset
shader:shader-uniform-block-membersresource
'
0163248648096112128144160176192208224240256272288
let
ok
eq:world-position
math:quantity-specification-namerelative-quantity
ok
math:unit-expression=:cell
math:quantity-specification-unitrelative-quantity
ok
eq:view-distance
math:quantity-specification-nameview-z-quantity
ok
math:unit-expression=:cell
math:quantity-specification-unitview-z-quantity
deftestprojective-maps-are-semantic-objects-with-packed-products
let*
projection-binding
binding-named'shadow-projectionspecification
projection
application
shader:shader-map-projection-applicationprojection
domain
shader:shader-map-domain-quantity-specificationdefinition
layout
shader:shader-projective-map-sample-quantity-layoutdefinition
ok
eqdefinition
shader:shader-map-application-definitionapplication
ok
eqapplication
shader:shader-map-projection-applicationprojection
ok
shader:shader-type=:vec3
shader:shader-map-domain-typedefinition
ok
shader:shader-type=:vec4
shader:shader-projective-map-homogeneous-typedefinition
ok
shader:shader-type=:vec3
shader:shader-projective-map-sample-typedefinition
ok
eq:world-position
math:quantity-specification-namedomain
ok
math:unit-expression=:cell
math:quantity-specification-unitdomain
ok
eq:shadow-uv
math:quantity-specification-nameuv
ok
eq:shadow-depth
math:quantity-specification-namedepth
ok
equal'
1/21/21
shader:shader-projective-map-coordinate-scaledefinition
ok
equal'
1/21/20
shader:shader-projective-map-coordinate-offsetdefinition
ok
=4
length
shader:shader-map-application-rowsapplication
ok
every
shader:shader-map-application-rowsapplication
labels
contains-representation-p
expression
or
some#'contains-representation-p
ok
not
contains-representation-papplication
deftestprojective-map-applications-reject-undefined-or-wrong-semantics
flet
reason-for
point-declarationform&optionalannotated-row-p
handler-case
progn
shader:parse-shader-specification'invalid-projective-map-probe`
:stage:vertex:inputs
,point-declaration
row-x:vec4:location1,@
whenannotated-row-p'
:quantity:linear-rgba:unit:one
row-y:vec4:location2
row-z:vec4:location3
row-w:vec4:location4
:outputs
result:vec2:location0:quantity:shadow-uv:unit:one:affine-pt
`
set-outputresult
swizzle,form:xy
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
let
world'
position:vec3:location0:quantity:world-position:unit:cell:affine-pt
raw'
position:vec3:location0
direction'
position:vec3:location0:quantity:world-direction:unit:one
ok
eq:undefined-shader-map
reason-forworld'
project-point:missing-mappositionrow-xrow-yrow-zrow-w
ok
eq:projective-map-domain-mismatch
reason-forraw'
project-point:world-to-lightpositionrow-xrow-yrow-zrow-w
ok
eq:projective-map-domain-mismatch
reason-fordirection'
project-point:world-to-lightpositionrow-xrow-yrow-zrow-w
ok
eq:projective-map-row-count
reason-forworld'
project-point:world-to-lightpositionrow-xrow-yrow-z
ok
eq:invalid-projective-map-rows
reason-forworld'
project-point:world-to-lightpositionrow-xrow-yrow-zrow-w
t
ok
eq:sampling-projection-requires-map-application
handler-case
progn
shader:parse-shader-specification'invalid-sampling-projection-probe'
:stage:vertex:inputs
raw-clip:vec4:location0
:outputs
result:vec2:location0:quantity:shadow-uv:unit:one
'
set-outputresult
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
deftestblock-vertex-uniform-members-retain-access-chain-provenance
let*
specification
spv:shader-lowering-specificationlowering
camera
binding-named'cameraspecification
instructions
gethashreference
spv:shader-lowering-expression-instructionslowering
names
mapcarinstructions
ok
find"ACCESS-CHAIN"names:test#'string=
ok
find"LOAD"names:test#'string=
deftestblock-shadow-vertex-is-a-light-space-depth-shader
let*
resource
first
shader:shader-specification-resourcesspecification
clip
binding-named'clipspecification
clip-position
first
shader:shader-specification-statementsspecification
ok
eq
shader:shader-specification-stagespecification
:vertex
ok
=
length
shader:shader-specification-inputsspecification
1
ok
=
length
shader:shader-specification-outputsspecification
1
ok
=
shader:shader-resource-bindingresource
2
let
ok
eq
shader:shader-map-application-definitionapplication
ok
shader:shader-type=
shader:shader-expression-typeapplication
:vec4
ok
shader:shader-type=
shader:shader-expression-type
shader:shader-assignment-valueclip-position
:vec4
deftestuniform-blocks-do-not-pretend-to-implement-general-packing
ok
signals
shader:parse-shader-specification'test-uniform-layout'
:stage:vertex:resources
state:uniform-block:binding0:members
unsupported:float
:outputs
position:vec4:built-in:position
'
set-outputposition
vec40.00.00.01.0
'shader:shader-language-error
deftestlowering-retains-expression-to-ssa-provenance
let*
specification
spv:shader-lowering-specificationlowering
reflected-expression
instructions
gethashreflected-expression
spv:shader-lowering-expression-instructionslowering
ok
typep
spv:shader-lowering-modulelowering
'spv:spir-v-module
okinstructions
ok
everyinstructions
ok
find"F-MUL"instructions:key:test#'string=
ok
some
lambda
memberreflected-expression
gethashinstruction
spv:shader-lowering-instruction-expressionslowering
:test#'eq
instructions
deftestconstants-and-reused-loads-retain-occurrence-provenance
let*
specification
shader:parse-shader-specification'reuse-input'
:stage:fragment:inputs
value:float:location0
:outputs
color:float:location0
'
let*
twice
+valuevalue
set-outputcolortwice
left-instructions
gethash
firstreferences
spv:shader-lowering-expression-instructionslowering
right-instructions
gethash
secondreferences
spv:shader-lowering-expression-instructionslowering
torch-color
binding-named'torch-colorblock-specification
block-lowering
constant-instructions
gethashliteral
spv:shader-lowering-expression-instructionsblock-lowering
ok
=
lengthleft-instructions
1
ok
eq
firstleft-instructions
firstright-instructions
ok
=
lengthconstant-instructions
1
ok
string-equal
symbol-name
spv:instruction-name
firstconstant-instructions
"constant"
deftestvector-scalar-division-lowers-through-a-reciprocal
let*
specification
shader:parse-shader-specification'vector-division'
:stage:fragment:inputs
value:vec3:location0
scale:float:location1
:outputs
color:vec3:location0
'
let*
quotient
/valuescale
set-outputcolorquotient
instructions
spv:lower-spir-v
spv:shader-lowering-module
names
mapcarinstructions
ok
find"F-DIV"names:test#'string=
ok
find"VECTOR-TIMES-SCALAR"names:test#'string=
deftesta-first-use-vector-constructor-cannot-claim-its-type-id
let
specification
shader:parse-shader-specification'first-use-vector-constructor'
:stage:fragment:outputs
color:vec4:location0
'
let*
set-outputcolor

vec3 has no interface declaration to predeclare its type. Assembly is therefore the direct proof that the type and its first value received distinct result IDs.

ok
=#x07230203
deftestcanonical-shader-id-reservations-never-reuse-a-claimed-id
let*
ok
not
eqfirstsecond
ok
string="%PROBE"
symbol-namefirst
ok
string="%PROBE-2"
symbol-namesecond
deftestdepth-texture-sampling-feeds-ordinary-float-math
let*
specification
shader:parse-shader-specification'depth-sample'
:stage:fragment:inputs
uv:vec2:location0
receiver-depth:float:location1
:outputs
visibility:float:location0
:resources
shadow-map:depth-texture-2d:binding0
shadow-sampler:sampler:binding1
'
let*
stored-depth
sampleshadow-mapshadow-sampleruv
depth-lane
swizzlestored-depth:x
visible
shader:stepreceiver-depthdepth-lane
set-outputvisibilityvisible
stored-depth
binding-named'stored-depthspecification
depth-lane
binding-named'depth-lanespecification
visible
binding-named'visiblespecification
module
spv:shader-lowering-module
instructions
names
mapcarinstructions
ok
shader:shader-type=
shader:shader-expression-type
:vec4
ok
shader:shader-type=
shader:shader-expression-type
:float
ok
shader:shader-type=
shader:shader-expression-type
:float
ok
find"IMAGE-SAMPLE-IMPLICIT-LOD"names:test#'string=
ok
find"EXT-INST"names:test#'string=
deftestshader-arithmetic-carries-backend-neutral-quantity-specifications
flet
parse-depth-probe
annotated-p
shader:parse-shader-specification'semantic-depth-probe
ifannotated-p'
:stage:fragment:inputs
receiver-depth:float:location0:quantity:shadow-depth
bias:float:location1:quantity:shadow-depth:character:difference
:outputs
biased-depth:float:location0:quantity:shadow-depth
'
:stage:fragment:inputs
receiver-depth:float:location0
bias:float:location1
:outputs
biased-depth:float:location0
'
let*
biased
-receiver-depthbias
set-outputbiased-depthbiased
let*
annotated
parse-depth-probet
plain
parse-depth-probenil
receiver
first
shader:shader-specification-inputsannotated
biased
binding-named'biasedannotated
receiver-specification
shader:shader-declaration-quantity-specificationreceiver
ok
eq:shadow-depth
math:quantity-specification-namereceiver-specification
ok

Semantic checking is a source concern; it does not perturb the SPIR-V representation or the deterministic lowering of valid arithmetic.

deftestshader-arithmetic-rejects-dimensionally-or-affinely-invalid-forms
labels
reason-for
optionsbody
handler-case
progn
shader:parse-shader-specification'invalid-semantic-probeoptionsbody
nil
shader:shader-language-error
condition
list
shader:shader-language-error-reasoncondition
shader:shader-language-error-detailscondition
ok
equal'
:invalid-quantity-operation:cannot-add-points
reason-for'
:stage:fragment:inputs
left:float:location0:quantity:shadow-depth:affine-pt
right:float:location1:quantity:shadow-depth:affine-pt
:outputs
result:float:location0
'
let*
sum
+leftright
set-outputresultsum
ok
equal'
:invalid-quantity-operation:different-quantity-spaces
reason-for'
:stage:fragment:inputs
depth:float:location0:quantity:shadow-depth
distance:float:location1:quantity:distance:dimension:length
:outputs
result:float:location0
'
let*
sum
set-outputresultsum
deftestannotated-shader-arithmetic-is-total-and-unit-exact
labels
reason-for
inputsexpression
handler-case
progn
shader:parse-shader-specification'semantic-totality-probe`
:stage:fragment:inputs,inputs:outputs
result:float:location0
`
let*
value,expression
set-outputresultvalue
nil
shader:shader-language-error
condition
list
shader:shader-language-error-reasoncondition
shader:shader-language-error-detailscondition
let*
specification
shader:parse-shader-specification'semantic-max-probe'
:stage:fragment:inputs
left:float:location0:quantity:distance:dimension:length:unit:metre
right:float:location1:quantity:distance:dimension:length:unit:metre
:outputs
result:float:location0
'
let*
value
maxleftright
set-outputresultvalue
value
binding-named'valuespecification
ok
equal'
:invalid-quantity-operation:different-units
reason-for'
left:float:location0:quantity:distance:dimension:length:unit:metre
right:float:location1:quantity:distance:dimension:length:unit:kilometre
'
maxleftright
ok
equal'
:invalid-quantity-operation:unknown-operator
reason-for'
value:float:location0:quantity:distance:dimension:length:unit:metre
'
absvalue
ok
equal'
:missing-quantity-specification
right
reason-for'
left:float:location0:quantity:distance:dimension:length:unit:metre
right:float:location1
'
+leftright
deftestpacked-gpu-vectors-project-as-semantic-products
let*
specification
shader:parse-shader-specification'semantic-product-probe'
:stage:fragment:inputs
packed:vec3:location0:components
:xy:quantity:sample-position:affine-pt
:z:quantity:sample-value
:outputs
position-output:vec2:location0:quantity:sample-position:affine-pt
'
let*
sample-value
swizzlepacked:z
set-outputposition-outputposition
packed
first
shader:shader-specification-inputsspecification
layout
shader:shader-declaration-quantity-layoutpacked
sample-value
binding-named'sample-valuespecification
ok
null
shader:shader-declaration-quantity-specificationpacked
ok
=3
math:quantity-layout-extentlayout
ok
eq:sample-value
labels
reason-for
expression
handler-case
progn
shader:parse-shader-specification'invalid-semantic-product-probe'
:stage:fragment:inputs
packed:vec3:location0:components
:xy:quantity:sample-position
:z:quantity:sample-value
:outputs
result:vec3:location0
`
set-outputresult,expression
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
ok
eq:undeclared-quantity-projection
reason-for'
swizzlepacked:yz
ok
eq:missing-quantity-specification
reason-for'
+packedpacked
let*
specification
shader:parse-shader-specification'homogeneous-component-probe'
:stage:fragment:inputs
position:vec3:location0:quantity:test-position
:outputs
x-output:float:location0:quantity:test-position-x
'
set-outputx-output
x
shader:shader-assignment-value
first
shader:shader-specification-statementsspecification
ok
eq:test-position-x
math:quantity-specification-name
deftesttexture-samples-can-publish-semantic-channel-layouts
let*
specification
shader:parse-shader-specification'semantic-sample-probe'
:stage:fragment:inputs
uv:vec2:location0
:outputs
rgb-output:vec3:location0:quantity:linear-rgb
:resources
image:texture-2d:binding0:sample-transfer:srgb-to-linear:sample-components
:rgb:quantity:linear-rgb
:a:quantity:opacity
sampler:sampler:binding1
'
let*
texel
sampleimagesampleruv
rgb
swizzletexel:rgb
alpha
swizzletexel:a
set-outputrgb-outputrgb
image
first
shader:shader-specification-resourcesspecification
texel
binding-named'texelspecification
rgb
binding-named'rgbspecification
alpha
binding-named'alphaspecification
ok
eq:srgb-to-linear
shader:shader-resource-sample-transferimage
deftestsample-transfer-metadata-is-texture-only
flet
reason-for
resource
handler-case
progn
shader:parse-shader-specification'invalid-sample-transfer-probe`
:stage:fragment:outputs
result:float:location0
:resources
,resource
'
set-outputresult1.0
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
ok
eq:invalid-sample-transfer
reason-for'
image:texture-2d:binding0:sample-transfer:mystery-transfer
ok
eq:sample-semantics-on-non-texture
reason-for'
sampler:sampler:binding0:sample-transfer:srgb-to-linear
deftestsemantic-boundaries-are-distinct-checked-and-have-no-codegen-effect
flet
probe
annotated-p
shader:parse-shader-specification'semantic-boundary-probe'
:stage:fragment:inputs
left:float:location0
right:float:location1
:outputs
result:float:location0
ifannotated-p'
let*
typed-left
assume-quantityleft:quantity:left-factor
typed-right
assume-quantityright:quantity:right-factor
product
*typed-lefttyped-right
sum
interpretproduct:quantity:combined-factor
represented
recovered
assume-quantityrepresented:quantity:combined-factor
set-outputresultrecovered
'
let*
sum
*leftright
set-outputresultsum
flet
probe
constructed-p
shader:parse-shader-specification'quantity-construction-probe'
:stage:fragment:outputs
result:float:location0
`
set-outputresult,
ifconstructed-p'
quantity1.0:quantity:threshold
1.0
let*
constructed
probet
plain
probenil
expression
shader:shader-assignment-value
first
shader:shader-specification-statementsconstructed
flet
reason-for
form
handler-case
progn
shader:parse-shader-specification'invalid-semantic-boundary-probe'
:stage:fragment:inputs
value:float:location0
:outputs
result:float:location0
`
set-outputresult,form
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition

interpret can name checked arithmetic, but cannot smuggle meaning onto a raw input. assume-quantity is the deliberately loud boundary for it.

ok
eq:representation-requires-quantity
reason-for'
ok
eq:invalid-quantity-interpretation
reason-for'
interpretvalue:quantity:distance:dimension:length:unit:metre
ok
eq:invalid-quantity-interpretation
reason-for'
interpret
assume-quantityvalue:quantity:distance:dimension:length:unit:metre
:quantity:distance:dimension:length:unit:kilometre
ok
eq:invalid-quantity-interpretation
reason-for'
interpret
assume-quantityvalue:quantity:height:dimension:length:unit:metre
:quantity:width:dimension:length:unit:metre
deftestproduction-vertex-interfaces-carry-quantities-end-to-end
let*
inputs
shader:shader-specification-inputsspecification
outputs
shader:shader-specification-outputsspecification
position
firstinputs
uv-shade
secondinputs
normal
thirdinputs
light
fourthinputs
fog
fourthoutputs
shadow-uv
sixthoutputs
shadow-depth
seventhoutputs
tile-offset
tenthoutputs
position-quantity
shader:shader-declaration-quantity-specificationposition
ok
eq:world-position
math:quantity-specification-nameposition-quantity
ok
math:unit-expression=:cell
math:quantity-specification-unitposition-quantity
ok
shader:shader-declaration-quantity-layoutuv-shade
ok
eq:world-direction
math:quantity-specification-name
shader:shader-declaration-quantity-specificationnormal
ok
shader:shader-declaration-quantity-layoutlight
ok
eq:fog-amount
math:quantity-specification-name
shader:shader-declaration-quantity-specificationfog
ok
eq:shadow-uv
math:quantity-specification-name
shader:shader-declaration-quantity-specificationshadow-uv
ok
eq:shadow-depth
math:quantity-specification-name
shader:shader-declaration-quantity-specificationshadow-depth
ok
eq:flat
shader:shader-interface-interpolationtile-offset
ok
eq:atlas-tile-offset
math:quantity-specification-name
shader:shader-declaration-quantity-specificationtile-offset
ok
signals
shader:parse-shader-specification'invalid-production-unit-mix'
:stage:vertex:inputs
position:vec3:location0:quantity:world-position:unit:cell:affine-pt
direction:vec3:location1:quantity:world-direction:unit:one
:outputs
result:vec3:location0
'
set-outputresult
+positiondirection
'shader:shader-language-error
deftestexplicit-unit-conversion-preserves-meaning-and-scales-values
let*
specification
shader:parse-shader-specification'unit-conversion-probe'
:stage:fragment:outputs
result:float:location0
'
let*
opacity
quantity50.0:quantity:opacity:unit:percent
fraction
set-outputresultfraction
binding
binding-named'fractionspecification
instructions
spv:lower-spir-v
spv:shader-lowering-module
names
mapcarinstructions
ok
eq:opacity
math:quantity-specification-namequantity
ok
math:unitless-p
math:quantity-specification-unitquantity
ok
find"F-MUL"names:test#'string=
flet
reason-for
form
handler-case
progn
shader:parse-shader-specification'invalid-unit-conversion-probe'
:stage:fragment:inputs
value:float:location0
:outputs
result:float:location0
`
set-outputresult,form
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
ok
eq:unit-conversion-requires-quantity
reason-for'
convert-unitvalue:unit:metre
ok
eq:invalid-quantity-declaration
reason-for'
quantity1.0:quantity:opacity:unit:radian
ok
eq:invalid-quantity-declaration
reason-for'
quantity1.0:quantity:unregistered-distance:unit:metre
ok
eq:invalid-unit-conversion
reason-for'
convert-unit
quantity1.0:quantity:duration:unit:second
:unit:metre
ok
eq:undefined-unit
reason-for'
convert-unit
quantity1.0:quantity:distance:unit:metre
:unit:furlong
deftestproduction-shadow-material-carries-semantic-quantities
let
flet
let
coordinate
quantity'shadow-coordinate
receiver-depth
quantity'receiver-depth
bias
quantity'shadow-bias
world-span
quantity'shadow-world-span
blocker-separation
quantity'shadow-blocker-separation
ok
eq:shadow-uv
math:quantity-specification-namecoordinate
ok
eq:normalized-coordinate
math:quantity-specification-kindcoordinate
ok
eq:shadow-depth
math:quantity-specification-namereceiver-depth
ok
math:unit-expression=:cell
math:quantity-specification-unitworld-span
ok
eq:shadow-depth-gradient
math:quantity-specification-namegradient
ok
eq:shadow-depth
math:quantity-specification-nameblocker-separation
ok
eq:shadow-filter-radius
math:quantity-specification-namefilter-radius
ok
eq:sample-count
math:quantity-specification-kindfilter-radius
ok
eq:linear-rgba
math:quantity-specification-namergba
ok
eq:relative-color-signal
math:quantity-specification-kindrgba
deftestproduction-quantity-vocabulary-supplies-character-defaults
flet
specification
name&optional
unit:one
dolist
name'
:world-position:texture-uv:shadow-uv:shadow-depth:clip-coordinate
ok
math:quantity-specification-affine-p
specificationname
if
eqname:world-position
:cell:one
dolist
name'
:world-distance:linear-rgb:linear-rgba:opacity:ambient-occlusion:fog-amount:day-factor:sky-light-level:block-light-level:material-emission:shadow-filter-radius:view-distance
let
quantity
specificationname
if
membername'
:world-distance:view-distance
:cell:one
deftestproduction-points-and-amounts-reject-invalid-arithmetic
labels
failure-for
form
handler-case
progn
shader:parse-shader-specification'invalid-production-quantity-operation'
:stage:fragment:outputs
result:float:location0
`
set-outputresult,form
nil
let*
negation'
-
quantity1.0:quantity:opacity:unit:one
point-addition'
+
quantity0.0:quantity:world-x-position:unit:cell
quantity1.0:quantity:world-x-position:unit:cell
negation-error
failure-fornegation
point-error
failure-forpoint-addition
ok
eq:invalid-quantity-operation
shader:shader-language-error-reasonnegation-error
ok
eq:cannot-negate-amount
shader:shader-language-error-detailsnegation-error
ok
equalnegation
shader:shader-language-error-formnegation-error
ok
eq:invalid-quantity-operation
shader:shader-language-error-reasonpoint-error
ok
eq:cannot-add-points
shader:shader-language-error-detailspoint-error
ok
equalpoint-addition
shader:shader-language-error-formpoint-error
deftestproduction-crosshair-composes-linear-rgb-with-opacity
let*
ink
first
shader:shader-specification-inputsspecification
rgba
binding-named'rgbaspecification
ink-quantity
shader:shader-declaration-quantity-specificationink
ok
eq:linear-rgb
math:quantity-specification-nameink-quantity
ok
eq:opacity
math:quantity-specification-nameopaque-quantity
ok
eq:linear-rgba
math:quantity-specification-namergba-quantity
deftestshadow-visibility-is-a-source-abstraction-over-core-math
let*
specification
shader:parse-shader-specification'shadow-visibility-probe'
:stage:fragment:inputs
uv:vec2:location0:quantity:shadow-uv
receiver-depth:float:location1:quantity:shadow-depth
receiver-depth-gradient:vec2:location2:quantity:shadow-depth-gradient
texel-size:vec2:location3:quantity:shadow-uv:character:difference
bias:float:location4:quantity:shadow-depth:character:difference
radius:float:location5:quantity:shadow-filter-radius
:outputs
visibility:float:location0
:resources
shadow-map:depth-texture-2d:binding0
shadow-sampler:sampler:binding1
'
let*
coordinateuv
depthreceiver-depth
gradientreceiver-depth-gradient
texeltexel-size
depth-biasbias
filter-radiusradius
visible
shader:shadow-visibilityshadow-mapshadow-samplercoordinatedepthgradienttexeldepth-biasfilter-radius
set-outputvisibilityvisible
visible
binding-named'visiblespecification
module
spv:shader-lowering-module
instructions
names
mapcarinstructions
ok
typepexpression'shader:shader-call
ok
=17
count"IMAGE-SAMPLE-DREF-IMPLICIT-LOD"names:test#'string=
ok
=17
count"DOT"names:test#'string=
deftestshader-abstraction-redefinition-affects-fresh-parses
labels
install-subtraction
eval'
shader:define-shader-abstractiontest-shadow-rewrite
receiverdepthbias
`
shader:step
-,receiver,bias
,depth
install-addition
eval'
shader:define-shader-abstractiontest-shadow-rewrite
receiverdepthbias
`
shader:step
+,receiver,bias
,depth
install-bad-expansion
eval'
shader:define-shader-abstractiontest-shadow-rewrite
receiverdepthbias
`
shader:step,receiver,depth,bias
parse-probe
shader:parse-shader-specification'shadow-rewrite-probe'
:stage:fragment:inputs
receiver:float:location0
depth:float:location1
bias:float:location2
:outputs
visibility:float:location0
'
let*
visible
test-shadow-rewritereceiverdepthbias
set-outputvisibilityvisible
unwind-protect
progn
install-subtraction
let*
subtracted
parse-probe
subtracted-form
visible-formsubtracted
method-subtracted-form
visible-form
shader-abstraction-method-probe:abstraction-probe:fragment
install-addition
let
added
parse-probe
method-added
shader-abstraction-method-probe:abstraction-probe:fragment
ok
equal
form-namessubtracted-form
'
"step"
"-""receiver""bias"
"depth"
ok
equal
form-names
visible-formadded
'
"step"
"+""receiver""bias"
"depth"
ok
equal
form-namesmethod-subtracted-form
'
"step"
"-""receiver""bias"
"depth"
ok
equal
form-names
visible-formmethod-added
'
"step"
"+""receiver""bias"
"depth"
install-bad-expansion
ok
signals
parse-probe
'shader:shader-language-error
ok
equal
form-namessubtracted-form
'
"step"
"-""receiver""bias"
"depth"
install-subtraction
deftestevery-scene-stage-declares-the-same-frame-uniform-block

Identical member order and offsets at binding 2 are the ABI contract which lets one buffer feed the vertex and fragment halves of both the block material and the sky.

flet
frame-block
specification
find-if
lambda
resource
shader:shader-specification-resourcesspecification
member-layout
block
mapcar
lambda
member
list
string-downcase
symbol-name
shader:shader-uniform-member-offsetmember
shader:shader-uniform-block-membersblock
let*
ok
every
lambda
block
blocks
ok
every
lambda
block
=
shader:shader-resource-bindingblock
2
blocks
ok
every
lambda
block
equal
member-layoutblock
reference
restblocks
ok
everyblocks
deftestthe-sky-material-is-image-mathematics-over-environment-lanes
let*
ray
binding-named'rayvertex
direction
binding-named'directionfragment
cloud-density
binding-named'cloud-densityfragment
disc
binding-named'discfragment
ok
eq
shader:shader-specification-stagevertex
:vertex
ok
eq
shader:shader-specification-stagefragment
:fragment
ok
shader:shader-type=
shader:shader-expression-type
:vec3

The sky drops out of the checked-quantity world once, deliberately, and is ordinary image mathematics over a unit view ray thereafter.

ok
equal'
"normalize"
"representation""ray-input"

A deck is a coverage threshold over one noise field, and the width of that threshold is the only thing that softens toward the horizon.

ok
equal'
"*""deck-mask"
"smoothstep""coverage"
"+""coverage""softness"
"cloud-field"

The deck's own shadow is the same field sampled along the deck toward the sun, against the same threshold: a lit face and a dark underside from one extra tap.

ok
equal'
"smoothstep""coverage"
"+""coverage""softness"
"shadow-field"
ok
equal'
"smoothstep"
"-"1.0"disc-limb"
"-"1.0
"*"0.56"disc-limb"
"alignment"

All the fragment's extended mathematics shares one import.

ok
=1
length
spv:spir-v-module-extended-instruction-importsfragment-module
deftestthe-sky-and-the-block-surface-agree-on-what-distance-looks-like

Below the horizon the sky stands in for terrain too far off to be resident, so the two stages have to arrive at the same colour or the edge of the resident world draws itself as a line. They agree by calling the same function on the same lanes rather than by two expressions kept in step by hand.

let*
flet
operator
expression
ok
string="aerial-perspective-color"
ok
string="assume-quantity"
ok
equal'
"assume-quantity"
"aerial-perspective-color"
"representation"
"swizzle""fog-color-vector""xyz"
"look-direction"
"representation""sun-direction"
"low-sun"
"representation""day-factor"
"quantity""linear-rgb""unit""one"

And the fog it feeds is still an absolute colour, mixed by the same amount the vertex stage measured.

ok
equal'
"mix""radiance""fog-color""fog-amount"
ok
eq:absolute
deftestextended-math-lowers-through-one-shared-import-in-layout-order
let*
specification
shader:parse-shader-specification'extended-math'
:stage:fragment:inputs
direction:vec3:location0
level:float:location1
:outputs
color:vec4:location0
'
let*
unit
normalizedirection
glow
smoothstep0.91.0level
lit
max0.0
dotunit
shader:vec30.01.00.0
shaped
expt
clamp
+glowlit
0.01.0
2.2
softened
sqrt
absshaped
rgb
*unitsoftened
set-outputcolor
vec4rgb
min1.0softened
module
spv:shader-lowering-module
instructions
names
mapcarinstructions

Every extended operator in one module shares a single import, which sits in SPIR-V logical layout between capability and memory model.

ok
=1
length
spv:spir-v-module-extended-instruction-importsmodule
ok
=1
count"EXT-INST-IMPORT"names:test#'string=
ok
<
position"CAPABILITY"names:test#'string=
position"EXT-INST-IMPORT"names:test#'string=
position"MEMORY-MODEL"names:test#'string=
ok
=8
count"EXT-INST"names:test#'string=

Deterministic lowering, and no import where no extended math occurs.

flet
forms
mapcar#'spv:instruction-form
spv:lower-spir-v
spv:shader-lowering-module
ok
equal
forms
forms
ok
null
spv:spir-v-module-extended-instruction-imports
deftestslug-root-eligibility-is-the-eight-class-table
let
expected'
00
10
11
10
01
11
01
00
loopforcodebelow8forpairinexpectedfory1=
if
logbitp0code
1.0-1.0
fory2=
if
logbitp1code
1.0-1.0
fory3=
if
logbitp2code
1.0-1.0
do
ok
equalpair
multiple-value-list

Zero is deliberately in the non-positive class.

ok
equal'
00
multiple-value-list
defunslug-test-point
xy
slug:make-slug-point:xx:yy
defunslug-test-square
leftbottomrighttop&keyclockwise-p
let
points
ifclockwise-p
list
slug-test-pointleftbottom
slug-test-pointrightbottom
list
slug-test-pointleftbottom
slug-test-pointrightbottom
loopforstartinpointsforendin
append
restpoints
list
firstpoints
collect
defunslug-test-curve-min
curveaxis
let
reader
ecaseaxis
:x#'slug:slug-point-x
:y#'slug:slug-point-y
apply#'min
mapcarreader
list
slug:slug-quadratic-startcurve
slug:slug-quadratic-controlcurve
slug:slug-quadratic-endcurve
defunslug-test-curve-max
curveaxis
let
reader
ecaseaxis
:x#'slug:slug-point-x
:y#'slug:slug-point-y
apply#'max
mapcarreader
list
slug:slug-quadratic-startcurve
slug:slug-quadratic-controlcurve
slug:slug-quadratic-endcurve
deftestarbitrary-quadratic-contours-pack-into-sorted-slug-bands
let*
inner
slug-test-square1133:clockwise-pt
outline
slug:make-slug-outline:contours
listouterinner
packed
slug:pack-slug-outlineoutline:horizontal-band-count2:vertical-band-count2
curves
slug:slug-packed-outline-curvespacked
ok
eq:counterclockwise
ok
=8
lengthcurves
ok
=0
slug:slug-packed-outline-min-xpacked
ok
=4
slug:slug-packed-outline-max-ypacked
ok
every
lambda
band
let
indices
slug:slug-band-curve-indicesband
and

Horizontal ray bands omit horizontal curves.

every
lambda
index
let
curve
arefcurvesindex
not
=
slug:slug-point-y
slug:slug-quadratic-startcurve
slug:slug-point-y
slug:slug-quadratic-controlcurve
slug:slug-point-y
slug:slug-quadratic-endcurve
indices

Descending maximum x supports the shader's early exit.

apply#'>=
mapcar
lambda
index
slug-test-curve-max
arefcurvesindex
:x
indices
slug:slug-packed-outline-horizontal-bandspacked
ok
every
lambda
band
let
descending
slug:slug-band-curve-indicesband
ascending
slug:slug-band-ascending-curve-indicesband
and
every
lambda
index
descending
apply#'>=
mapcar
lambda
index
slug-test-curve-max
arefcurvesindex
:y
descending
apply#'<=
mapcar
lambda
index
slug-test-curve-min
arefcurvesindex
:y
ascending
slug:slug-packed-outline-vertical-bandspacked
let
line
firstouter
ok
equalp
slug:slug-quadratic-controlline
slug:slug-quadratic-endline
deftestmalformed-slug-contours-report-the-broken-junction
let*
outline
slug:make-slug-outline:contours
list
listfirstsecond
handler-case
progn
oknil
slug:slug-outline-error
condition
ok
eq:disconnected-contour
slug:slug-outline-error-reasoncondition
ok
equal'
00
slug:slug-outline-error-detailscondition
deftestslug-texture-serialization-repacks-the-actual-half-values
let*
contour
serialized
slug:serialize-slug-outline
slug:make-slug-outline:contours
listcontour
:horizontal-band-count2:vertical-band-count2
packed
slug:slug-serialized-outline-packed-outlineserialized
curve-words
slug:slug-serialized-outline-curve-half-wordsserialized
band-words
slug:slug-serialized-outline-band-uint16-wordsserialized
curve-upload
slug:slug-serialized-outline-curve-upload-dataserialized
band-upload
slug:slug-serialized-outline-band-upload-dataserialized
ok
=4096
slug:slug-serialized-outline-curve-widthserialized
ok
=4096
slug:slug-serialized-outline-band-widthserialized
ok
=5
slug:slug-serialized-outline-curve-texel-countserialized
ok
=20
lengthcurve-words

The first curve's p3 is the following curve texel's p1.

ok
equalp
subseqcurve-words24
subseqcurve-words46

Four headers, then the two vertical sides once (both horizontal bands hold exactly them, so the second points at the first's list) and the two horizontal sides once, likewise shared.

ok
=8
slug:slug-serialized-outline-band-texel-countserialized
ok
nth-value0
subtypep
array-element-typecurve-upload
'
unsigned-byte64
ok
nth-value0
subtypep
array-element-typeband-upload
'
unsigned-byte32
ok
=
row-major-arefcurve-upload0
loopforindexbelow4sum
ash
arefcurve-wordsindex
*index16
ok
=#x00040002
row-major-arefband-upload0
ok
equalp
24242626
subseqband-words08
ok
equalp
1030
subseqband-words812
ok
equalp
2000
subseqband-words1216
let
ok
=12
slug:slug-serialized-outline-band-texel-count
slug:serialize-slug-outline
slug:make-slug-outline:contours
listcontour
:horizontal-band-count2:vertical-band-count2
ok
not
=1/3
slug:slug-packed-outline-max-xpacked
ok
<
abs
-1/3
slug:slug-packed-outline-max-xpacked
1/1000
deftestslug-serialization-chooses-band-counts-by-load

A square's two vertical sides fall in every horizontal band however many there are, so one band per axis is as good as any and cheapest.

let
serialized
slug:serialize-slug-outline
slug:make-slug-outline:contours
ok
=1
slug:slug-serialized-outline-horizontal-band-countserialized
ok
=1
slug:slug-serialized-outline-vertical-band-countserialized
ok
=6
slug:slug-serialized-outline-band-texel-countserialized

Two squares stacked with a gap: two horizontal bands each hold one square's sides (a load of two) where one band would hold four.

let*
outline
slug:make-slug-outline:contours
listlowerupper
curves
slug:slug-packed-outline-curvespacked
ok
=2
length
slug:slug-packed-outline-horizontal-bandspacked
ok
every
lambda
band
=2
length
slug:slug-band-curve-indicesband
slug:slug-packed-outline-horizontal-bandspacked
deftestzpb-ttf-glyphs-enter-slug-before-software-rasterization
zpb-ttf:with-font-loader
font-loader
cl-dejavu:font-pathname"DejaVuSans.ttf"
let*
glyph
slug:load-slug-glyph#\Ofont-loader
outline
slug:slug-glyph-outlineglyph
contours
slug:slug-outline-contoursoutline
orientations
ok
char=#\O
slug:slug-glyph-characterglyph
ok
=2048
slug:slug-glyph-units-per-emglyph
ok
=1612
slug:slug-glyph-advance-widthglyph
ok
=2
lengthcontours
ok
=16
length
slug:slug-packed-outline-curvespacked
ok
member:clockwiseorientations
ok
member:counterclockwiseorientations
let*
normalized-packed
ok
=
slug:slug-packed-outline-min-xnormalized-packed
/
slug:slug-packed-outline-min-xpacked
2048
ok
=
slug:slug-packed-outline-max-xnormalized-packed
/
slug:slug-packed-outline-max-xpacked
2048
ok
=
slug:slug-packed-outline-min-ynormalized-packed
/
slug:slug-packed-outline-min-ypacked
2048
ok
=
slug:slug-packed-outline-max-ynormalized-packed
/
slug:slug-packed-outline-max-ypacked
2048
ok
every
lambda
contour
every
lambda
curve
not
equalp
slug:slug-quadratic-controlcurve
slug:slug-quadratic-endcurve
contour
contours
deftestshaders-consume-shared-arithmetic-functions-directly
let*
specification
shader:parse-shader-specification'shared-function-fragment'
:stage:fragment:inputs
value:float:location0
:outputs
result:float:location0
'
set-outputresult
call
shader:shader-assignment-value
first
shader:shader-specification-statementsspecification
ok
=#x07230203
deftestshared-source-retires-an-older-shader-only-definition
eval'
shader:define-shader-functionshared-source-migration-probe
value
+value1.0
ok
shader:shader-function-definition-for'shared-source-migration-probe
eval'
lang:define-arithmetic-functionshared-source-migration-probe
value
+value2.0
ok
null
shader:shader-function-definition-for'shared-source-migration-probe
ok
lang:arithmetic-function-definition-for'shared-source-migration-probe
deftesttask-and-mesh-lower-to-validated-vulkan-shaped-spir-v
let*
task-specification
mesh-specification
task-lowering
shader:lower-shader-specification:spir-vtask-specification
mesh-lowering
shader:lower-shader-specification:spir-vmesh-specification
task-module
spv:shader-lowering-moduletask-lowering
mesh-module
spv:shader-lowering-modulemesh-lowering
task-instructions
spv:lower-spir-vtask-module
mesh-instructions
spv:lower-spir-vmesh-module
task-names
mapcar#'spv:instruction-nametask-instructions
mesh-names
mapcar#'spv:instruction-namemesh-instructions
task-forms
write-to-string
mapcar#'spv:instruction-formtask-instructions
mesh-forms
write-to-string
mapcar#'spv:instruction-formmesh-instructions
payload-expression
find-if
lambda
expression
dolist
module
listtask-modulemesh-module
ok
=#x00010400
spv:spir-v-module-versionmodule
ok
member'spv::mesh-shading-ext
spv:spir-v-module-capabilitiesmodule
ok
member'spv::int64
spv:spir-v-module-capabilitiesmodule
ok
equal'
"SPV_EXT_mesh_shader"
spv:spir-v-module-extensionsmodule
ok
eq'spv::task-ext
spv:spir-v-entry-point-execution-model
first
spv:spir-v-module-entry-pointstask-module
ok
eq'spv::mesh-ext
spv:spir-v-entry-point-execution-model
first
spv:spir-v-module-entry-pointsmesh-module
ok
equal'
spv::local-size
mapcar#'spv:spir-v-execution-mode-name
spv:spir-v-module-execution-modestask-module
ok
equal'
spv::local-sizespv::output-triangles-extspv::output-verticesspv::output-primitives-ext
mapcar#'spv:spir-v-execution-mode-name
spv:spir-v-module-execution-modesmesh-module
dolist
ok
findnametask-names
ng
find'spv::returntask-names
ok
find'spv::returnmesh-names
ok
search"TASK-PAYLOAD-WORKGROUP-EXT"task-forms
ok
search"TASK-PAYLOAD-WORKGROUP-EXT"mesh-forms
ok
search"PER-PRIMITIVE-EXT"mesh-forms
ok
search"PRIMITIVE-TRIANGLE-INDICES-EXT"mesh-forms
okpayload-expression
ok
gethashpayload-expression
spv:shader-lowering-expression-instructionsmesh-lowering
dolist
specification
listtask-specificationmesh-specification
let
ok
=#x07230203
arefwords0
ok
=#x00010400
arefwords1
deftestshared-counted-fold-lowers-to-structured-spir-v
let*
specification
shader:parse-shader-specification'fold-fragment'
:stage:fragment:inputs
count:float:location0
:outputs
result:float:location0
'
set-outputresult
ok
find"PHI"names:key#'symbol-name:test#'string=
ok
find"LOOP-MERGE"names:key#'symbol-name:test#'string=
ok
find"BRANCH-CONDITIONAL"names:key#'symbol-name:test#'string=
ok
=#x07230203
deftestcounted-fold-until-guards-the-spir-v-loop-header
let*
specification
shader:parse-shader-specification'until-fold-fragment'
:stage:fragment:inputs
count:float:location0
:outputs
result:float:location0
'
set-outputresult
counted-fold
indexcountsum0.0:until
>sum10.0
+sumindex
ok
find"LOGICAL-NOT"names:key#'symbol-name:test#'string=
ok
find"LOGICAL-AND"names:key#'symbol-name:test#'string=
ok
find"LOOP-MERGE"names:key#'symbol-name:test#'string=
ok
=#x07230203

The test must be a boolean.

ok
signals
shader:parse-shader-specification'bad-until-fold-fragment'
:stage:fragment:inputs
count:float:location0
:outputs
result:float:location0
'
set-outputresult
counted-fold
indexcountsum0.0:untilsum
+sumindex
'shader:shader-language-error
deftestexact-unsigned-texel-loads-flow-through-shared-folds
let*
module
spv:shader-lowering-module
names
loopforfunctionin
spv:spir-v-module-function-definitionsmodule
append
loopforblockin
spv:spir-v-function-basic-blocksfunction
append
mapcar#'spv:instruction-name
spv:spir-v-basic-block-instructionsblock
ok
shader:shader-type=:uvec4
shader:shader-expression-type
dolist
name'
image-fetchu-modu-divi-addu-less-thanconvert-u-to-f
ok
findnamenames:test#'string-equal
ok
=#x07230203
deftestslug-atlas-uses-fragment-derivatives-and-selected-bands
let*
module
spv:shader-lowering-module
names
loopforfunctionin
spv:spir-v-module-function-definitionsmodule
append
loopforblockin
spv:spir-v-function-basic-blocksfunction
append
mapcar#'spv:instruction-name
spv:spir-v-basic-block-instructionsblock
dolist
name'
ok
findnamenames:test#'string-equal
ok
=#x07230203
deftestshared-conditionals-lower-inside-structured-spir-v-folds
let*
specification
shader:parse-shader-specification'conditional-fold-fragment'
:stage:fragment:inputs
count:float:location0
limit:float:location1
:outputs
result:float:location0
'
set-outputresult
ok
find"F-ORD-LESS-THAN"names:key#'symbol-name:test#'string=
ok
find"SELECT"names:key#'symbol-name:test#'string=
ok
=#x07230203
deftestanalytic-roundrect-distance-covers-the-fixed-shape-family
flet
near
leftright
<
abs
-leftright
1.0e-5

A two-by-one roundrect is one unit inside at its centre and exactly on its straight right edge.

ok
near-1.0
ok
near0.0

Radius equal to both half-extents is the ordinary circle distance.

ok
ok

Excessive and negative radii are normalized at the semantic boundary.

ok
ok
near0.0
deftestanalytic-roundrect-proof-shares-distance-and-derivative-coverage
let*
ok
eq:vertex
shader:shader-specification-stagevertex
ok
eq:fragment
shader:shader-specification-stagefragment
ok
=4
length
shader:shader-specification-inputsvertex
ok
=3
length
shader:shader-specification-inputsfragment
ok
search"D-PDX"forms
ok
search"D-PDY"forms
ok
search"SQRT"forms
ok
ok
=#x07230203
deftestslug-proof-is-a-pixel-shader-over-quadratic-roots
let*
fragment-value
shader:shader-assignment-value
first
shader:shader-specification-statementsfragment
forms
mapcar#'spv:instruction-form
spv:lower-spir-v
spv:shader-lowering-modulelowering
printed
write-to-stringforms
ok
eq:vertex
shader:shader-specification-stagevertex
ok
eq:fragment
shader:shader-specification-stagefragment
ok
=3
length
shader:shader-specification-inputsvertex
ok
=2
length
shader:shader-specification-inputsfragment
ok
typepfragment-value'shader:shader-function-call
ok
some
lambda
expression
ok
search"F-SIGN"printed
ok
search"SQRT"printed
ok
ok
=#x07230203
deftestslug-bands-are-two-data-driven-structured-traversals
let*
instructions
names
mapcar#'spv:instruction-nameinstructions
ok
=2
count"LOOP-MERGE"names:key#'symbol-name:test#'string=
ok
>=
count"IMAGE-FETCH"names:key#'symbol-name:test#'string=
6
ok
find"U-MOD"names:key#'symbol-name:test#'string=
ok
find"U-DIV"names:key#'symbol-name:test#'string=
ok
=#x07230203
deftestharfbuzz-shaping-selects-ligatures-and-preserves-clusters
let*
font
cl-dejavu:font-pathname"DejaVuSans.ttf"
shaped
glyphs
slug:slug-shaped-text-glyphsshaped
ok
=2048
slug:slug-shaped-text-units-per-emshaped

o, ffi, c, e: the three source characters at byte cluster 1 become one glyph selected by HarfBuzz rather than three cmap lookups.

ok
=4
lengthglyphs
ok
equal'
0145
loopforglyphacrossglyphscollect
slug:slug-shaped-glyph-clusterglyph
ok
=
slug:slug-shaped-text-x-advanceshaped
loopforglyphacrossglyphssum
slug:slug-shaped-glyph-x-advanceglyph
deftestextended-math-signatures-are-explicit-contracts
flet
failure-reason
body
handler-case
progn
shader:parse-shader-specification'bad-extended-math'
:stage:fragment:inputs
value:vec3:location0
scale:float:location1
word:uint:location2
uvalue:uvec2:location3
:outputs
color:vec3:location0
body
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition

Vector values with scalar bounds are not silently splatted.

ok
eq
failure-reason'
set-outputcolor
clampvalue0.01.0
:incompatible-arithmetic-types
ok
eq
failure-reason'
let*
set-outputcolor
*valueunit
:invalid-normalize
ok
eq
failure-reason'
set-outputcolor
minvalue
:wrong-operand-count
ok
eq
failure-reason'
set-outputcolor
exptvalue
:wrong-operand-count

Unsigned traversal values do not leak into float-only operations.

ok
eq
failure-reason'
set-outputcolor
*uvaluescale
:incompatible-product-types
ok
eq
failure-reason'
set-outputcolor
dotuvalueuvalue
:invalid-dot-product
ok
eq
failure-reason'
set-outputcolor
mixwordwordscale
:invalid-mix
ok
eq
failure-reason'
set-outputcolor
normalizeuvalue
:invalid-normalize
ok
eq
failure-reason'
set-outputcolor
minwordword
:invalid-extended-math-type
deftestextended-operations-retain-expression-provenance
let*
specification
shader:parse-shader-specification'clamped-level'
:stage:fragment:inputs
level:float:location0
:outputs
color:float:location0
'
let*
held
clamplevel0.01.0
set-outputcolorheld
instructions
gethashcall
spv:shader-lowering-expression-instructionslowering
okinstructions
ok
find"EXT-INST"instructions:key:test#'string=
ok
some
lambda
membercall
gethashinstruction
spv:shader-lowering-instruction-expressionslowering
:test#'eq
instructions
deftestshader-diagnostics-name-the-source-failure
let
unknown-reason
handler-case
progn
shader:parse-shader-specification'bad-shader'
:stage:fragment:outputs
color:vec4:location0
'
set-outputcolormissing-name
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
type-reason
handler-case
progn
shader:parse-shader-specification'bad-shader'
:stage:fragment:inputs
scalar:float:location0
:outputs
color:vec4:location0
'
set-outputcolorscalar
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
ok
equnknown-reason:unknown-name
ok
eqtype-reason:output-type-mismatch

Storage buffers and bit fields: the path a packed 64-bit site takes from a host array into a shader.

shader:define-shaderstorage-site-fragment-probe
:stage:fragment:resources
sites:storage-buffer:binding1:element:uint64
words:storage-buffer:binding2:element:uvec4
:outputs
color:vec4:location0
let*
extent
uint
ldb
byte40
term
x
uint
ldb
byte244
term
z
uint
ldb
byte852
term
high
ldb
byte1616
word
whole
ldb
byte320
word
shade
/
float
+xzhighwhole
255.0
set-outputcolor
vec4shadeshadeshade1.0
defunstorage-probe-error-reason
resourcesbody
handler-case
progn
shader:parse-shader-specification'storage-probe`
:stage:fragment:resources,resources:outputs
color:vec4:location0
body
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
defteststorage-buffers-declare-typed-elements-and-index-them
let*
sites
find'sites
shader:shader-specification-resourcesspecification
:key#'shader:shader-object-name:test#'string-equal
words
find'words
shader:shader-specification-resourcesspecification
:key#'shader:shader-object-name:test#'string-equal
term
binding-named'termspecification
ok
eq
shader:shader-storage-buffer-element-typesites
ok
eq
shader:shader-expression-type
defteststorage-buffers-and-bit-fields-reject-ill-typed-source
ok
eq:invalid-storage-buffer-element
storage-probe-error-reason'
sites:storage-buffer:binding1
'
set-outputcolor
vec41.01.01.01.0
ok
eq:invalid-storage-buffer-element
storage-probe-error-reason'
sites:storage-buffer:binding1:element:uvec3
'
set-outputcolor
vec41.01.01.01.0
ok
eq:element-on-non-storage-buffer
storage-probe-error-reason'
sites:texture-2d:binding1:element:uint
'
set-outputcolor
vec41.01.01.01.0
ok
eq:storage-buffer-requires-element
storage-probe-error-reason'
sites:storage-buffer:binding1:element:vec4
'
set-outputcolorsites
ok
eq:buffer-index-type
storage-probe-error-reason'
sites:storage-buffer:binding1:element:vec4
'
set-outputcolor
ok
eq:byte-specifier-exceeds-width
storage-probe-error-reason'
sites:storage-buffer:binding1:element:uint
'
let*
field
float
ldb
byte828
word
set-outputcolor
vec4fieldfieldfield1.0
ok
eq:invalid-byte-specifier
storage-probe-error-reason'
sites:storage-buffer:binding1:element:uint
'
let*
field
float
ldb
byte04
word
set-outputcolor
vec4fieldfieldfield1.0
ok
eq:invalid-bit-field-operand
storage-probe-error-reason'
sites:storage-buffer:binding1:element:float
'
let*
field
ldb
byte84
word
set-outputcolor
vec4fieldfieldfield1.0
defteststorage-buffers-lower-to-storage-class-runtime-arrays
let*
module
spv:shader-modulespecification
instructions
names
mapcar#'spv:instruction-nameinstructions
forms
write-to-string
mapcar#'spv:instruction-forminstructions
ok
equal'
"SPV_KHR_storage_buffer_storage_class"
spv:spir-v-module-extensionsmodule
ok
member'spv::int64
spv:spir-v-module-capabilitiesmodule
dolist
name'
spv::type-runtime-arrayspv::access-chainspv::loadspv::shift-left-logicalspv::shift-right-logical
ok
findnamenames

Bit fields never lower to bit-field instructions, which Vulkan limits to 32-bit operands, nor to 64-bit mask constants.

ng
find'spv::bitwise-andnames
ok
search"STORAGE-BUFFER"forms
ok
search"ARRAY-STRIDE 8"forms
ok
search"ARRAY-STRIDE 16"forms
ok
search"NON-WRITABLE"forms
ok
=#x07230203
arefwords0