luv

Workshop wiki

language.lisp

hal/shader/language.lisp

system luv/shader · 445 definitions · on GitHub

Typed mathematical shader expressions and their backend-neutral protocols.

This is the pleasant source language: declarations, bindings, and every expression are CLOS objects which retain their source forms. Sibling lowering systems implement the protocols at the bottom of this file while keeping their target products and construction state backend-owned.

The language itself is a small compiled subset of Common Lisp plus a vector library. Operators are named by ordinary symbols — CL's own where CL has the word, this package's where it does not — and each operator's parsing and typing are EQL-specialized methods. Backend implementations add lowering methods to the shared protocol without entering this package.

in-package#:luv.shader
define-conditionshader-language-error
error
form:initarg:form:initformnil:readershader-language-error-form
reason:initarg:reason:readershader-language-error-reason
details:initarg:details:initformnil:readershader-language-error-details
:report
lambda
conditionstream
formatstream"Cannot understand shader expression ~S: ~A~@[ (~S)~]."
shader-language-error-formcondition
shader-language-error-reasoncondition
shader-language-error-detailscondition
defmacrowith-shader-quantity-errors
source-formreason
&bodybody

Translate backend-neutral quantity failures into shader source errors.

`
handler-case
progn,@body
math:undefined-unit
condition
error'shader-language-error:form,source-form:reason:undefined-unit:details
math:undefined-unit-namecondition
math:quantity-operation-error
condition
error'shader-language-error:form,source-form:reason,reason:details
math:quantity-operation-error-reasoncondition
defclassshader-type
name:initarg:name:readershader-type-name
component-count:initarg:component-count:initformnil:readershader-type-component-count
scalar-kind:initarg:scalar-kind:initformnil:readershader-type-scalar-kind
bit-width:initarg:bit-width:initformnil:readershader-type-bit-width
opaque-kind:initarg:opaque-kind:initformnil:readershader-type-opaque-kind
sample-result-type:initarg:sample-result-type:initformnil:readershader-type-sample-result-type
image-depth-p:initarg:image-depth-p:initformnil:readershader-type-image-depth-p
defmethodprint-object
print-unreadable-object
typestream:typet
prin1
shader-type-nametype
stream
defparameter*shader-types*
make-hash-table:test#'eq
defunregister-shader-type
name&keycomponent-countscalar-kindbit-widthopaque-kindsample-result-typeimage-depth-p
setf
gethashname*shader-types*
make-instance'shader-type:namename:component-countcomponent-count:scalar-kindscalar-kind:bit-widthbit-width:opaque-kindopaque-kind:sample-result-typesample-result-type:image-depth-pimage-depth-p
register-shader-type:float:component-count1:scalar-kind:float:bit-width32
register-shader-type:vec2:component-count2:scalar-kind:float:bit-width32
register-shader-type:vec3:component-count3:scalar-kind:float:bit-width32
register-shader-type:vec4:component-count4:scalar-kind:float:bit-width32
register-shader-type:uint:component-count1:scalar-kind:uint:bit-width32
register-shader-type:uint64:component-count1:scalar-kind:uint:bit-width64
register-shader-type:uvec2:component-count2:scalar-kind:uint:bit-width32
register-shader-type:uvec3:component-count3:scalar-kind:uint:bit-width32
register-shader-type:uvec4:component-count4:scalar-kind:uint:bit-width32
register-shader-type:texture-2d:opaque-kind:texture-2d:sample-result-type:vec4
register-shader-type:depth-texture-2d:opaque-kind:texture-2d:sample-result-type:vec4:image-depth-pt
register-shader-type:uint-texture-2d:opaque-kind:texture-2d:sample-result-type:uvec4
register-shader-type:sampler:opaque-kind:sampler
register-shader-type:uniform-block:opaque-kind:uniform-block
register-shader-type:storage-buffer:opaque-kind:storage-buffer
defunfind-shader-type
designator&optionalsource-form
or
and
typepdesignator'shader-type
designator
and
symbolpdesignator
loopfortypebeingthehash-valuesof*shader-types*when
string-equal
symbol-namedesignator
symbol-name
shader-type-nametype
returntype
error'shader-language-error:formsource-form:reason:unknown-type:detailsdesignator
defunshader-float-type-p
let
and
eq
shader-type-scalar-kindtype
:float
=
shader-type-component-counttype
1
defunshader-unsigned-type-p
let
and
eq
shader-type-scalar-kindtype
:uint
=
shader-type-component-counttype
1
defunshader-vector-type-p
let
count
shader-type-component-count
andcount
>count1
defgenericshader-object-name
object
defmethodshader-object-name
lang:arithmetic-object-nameobject
defmethodshader-object-name
lang:arithmetic-object-nameobject
defmethodshader-object-source-form
lang:arithmetic-object-source-formobject
defmethodshader-object-source-form
lang:arithmetic-object-source-formobject
defclassshader-variable-declaration
type:initarg:type:readershader-declaration-type
quantity-specification:initarg:quantity-specification:initformnil:readershader-declaration-quantity-specification
quantity-layout:initarg:quantity-layout:initformnil:readershader-declaration-quantity-layout
:documentation

A represented shader value with optional backend-neutral semantic meaning.

defclassshader-interface-variable
direction:initarg:direction:readershader-interface-direction
location:initarg:location:initformnil:readershader-interface-location
built-in:initarg:built-in:initformnil:readershader-interface-built-in
interpolation:initarg:interpolation:initformnil:readershader-interface-interpolation
defclassshader-resource
descriptor-set:initarg:descriptor-set:initform0:readershader-resource-descriptor-set
binding:initarg:binding:readershader-resource-binding
sample-quantity-specification:initarg:sample-quantity-specification:initformnil:readershader-resource-sample-quantity-specification
sample-quantity-layout:initarg:sample-quantity-layout:initformnil:readershader-resource-sample-quantity-layout
sample-transfer:initarg:sample-transfer:initformnil:readershader-resource-sample-transfer
:documentation

A descriptor resource and, for textures, the represented meaning and colour transfer of the value returned by sampling.

defclassshader-uniform-block
members:initarg:members:initformnil:accessorshader-uniform-block-members
:documentation

One descriptor-backed uniform block with ordered, inspectable members.

defclassshader-uniform-member
block:initarg:block:readershader-uniform-member-block
index:initarg:index:readershader-uniform-member-index
offset:initarg:offset:readershader-uniform-member-offset
:documentation

A named value inside a shader-uniform-block, not a separate resource.

defclassshader-storage-buffer
element-type:initarg:element-type:readershader-storage-buffer-element-type
:documentation

One descriptor-backed read-only array of uniformly typed elements.

The array has no declared length: a shader indexes it with buffer-element and the host decides how many elements it uploads. #HFX2LI

defunshader-storage-buffer-element-stride
buffer

Return the byte distance between consecutive elements of buffer.

let
type
shader-storage-buffer-element-typebuffer
*
shader-type-component-counttype
floor
shader-type-bit-widthtype
8
defclassshader-task-payload
fields:initarg:fields:initformnil:accessorshader-task-payload-fields
:documentation

The named ABI shared by one task shader and its mesh shader consumers.

defclassshader-task-payload-field
payload:initarg:payload:readershader-task-payload-field-payload
index:initarg:index:readershader-task-payload-field-index
element-count:initarg:element-count:initformnil:readershader-task-payload-field-element-count
:documentation

One scalar/vector field or fixed array in a task payload ABI.

defgenerictask-payload-definition-for
name
:documentation

Return the task-payload ABI named by name, or NIL.

defmethodtask-payload-definition-for
name
declare
ignorename
nil
defunparse-task-payload-field-type
form
let
designator
secondform
if
and
conspdesignator
shader-symbol=
firstdesignator
:array
=
lengthdesignator
3
destructuring-bind
arrayelement-typeelement-count
designator
declare
ignorearray
unless
typepelement-count'
integer1*
error'shader-language-error:formform:reason:invalid-payload-array-size:detailselement-count
values
find-shader-typeelement-typeform
element-count
values
find-shader-typedesignatorform
nil
defunmake-task-payload-definition
namefield-formssource-form
unless
and
listpfield-forms
field-forms
error'shader-language-error:formsource-form:reason:empty-task-payload
let
payload
make-instance'shader-task-payload:namename:source-formsource-form
setf
shader-task-payload-fieldspayload
loopwithnames=nilforfield-forminfield-formsforindexfrom0collect
destructuring-bind
field-namefield-type&keyquantitydimensionunitaffine-pcharactercomponents
field-form
declare
ignorefield-type
when
findfield-namenames:test#'shader-symbol=
error'shader-language-error:formfield-form:reason:duplicate-payload-field:detailsfield-name
pushfield-namenames
multiple-value-bind
typeelement-count
let
make-instance'shader-task-payload-field:namefield-name:typetype:quantity-specificationspecification:quantity-layout
parse-declaration-quantity-layoutcomponentstypefield-formspecification
:payloadpayload:indexindex:element-countelement-count:source-formfield-form
payload
defmacrodefine-task-payload
name&bodyfields

Define a durable, inspectable task-to-mesh payload ABI.

let*
package
or
symbol-packagename
*package*
variable
intern
formatnil"*~A-TASK-PAYLOAD*"
symbol-namename
package
`
progn
defparameter,variable
defmethodtask-payload-definition-for
payload-name
eql',name
declare
ignorepayload-name
,variable
',name
defclassshader-map-definition
domain-type:initarg:domain-type:readershader-map-domain-type
domain-quantity-specification:initarg:domain-quantity-specification:readershader-map-domain-quantity-specification
:documentation

An inspectable semantic map whose dense representation is supplied at use.

defclassshader-projective-map-definition
homogeneous-type:initarg:homogeneous-type:readershader-projective-map-homogeneous-type
sample-type:initarg:sample-type:readershader-projective-map-sample-type
sample-quantity-layout:initarg:sample-quantity-layout:readershader-projective-map-sample-quantity-layout
coordinate-scale:initarg:coordinate-scale:readershader-projective-map-coordinate-scale
coordinate-offset:initarg:coordinate-offset:readershader-projective-map-coordinate-offset
:documentation

A four-row homogeneous map with a separately checked sampling projection.

defgenericshader-map-definition-for
name
:documentation

Return the shader semantic map named by name, or NIL.

defmethodshader-map-definition-for
name
declare
ignorename
nil
defunshader-uniform-block-byte-size
block

The host byte size implied by block's shader-visible vec4-lane layout.

Hosts allocating a backing buffer should derive their size here rather than repeating the lane arithmetic as a literal.

let
members
shader-uniform-block-membersblock
ifmembers
+
shader-uniform-member-offset
car
lastmembers
16
0
defclassshader-function-parameter-binding
:documentation

A lexical alias for one already parsed shader-function argument.

defgenericshader-binding-expression
binding
defmethodshader-binding-expression
lang:arithmetic-binding-expressionbinding
defclassshader-expression
type:initarg:type:readershader-expression-type
defmethodshader-expression-quantity-specification
lang:arithmetic-expression-quantity-specificationexpression
defmethodshader-expression-quantity-layout
lang:arithmetic-expression-quantity-layoutexpression
defgenericshader-expression-source-form
expression
defmethodshader-expression-source-form
lang:arithmetic-expression-source-formexpression
defgenericshader-expression-name
expression
defmethodshader-expression-name
lang:arithmetic-expression-nameexpression
defgeneric
nameexpression
defmethod
name
setf
lang:arithmetic-expression-nameexpression
name
defgenericshader-expression-quantity-checked-p
expression
:documentation

Whether semantic quantity checking is active at expression.

Annotations enter checked arithmetic; an explicit representation boundary leaves it again while retaining the semantic operand in the expression graph.

defgenericshader-expression-materialized-p
expression
:documentation

Whether expression directly denotes one lowerable represented value.

defmethodshader-expression-materialized-p
declare
ignoreexpression
t
defgenericshader-literal-value
literal
defmethodshader-literal-value
lang:arithmetic-literal-valueliteral
defgenericshader-reference-target
reference
defmethodshader-reference-target
lang:arithmetic-reference-targetreference
defgenericshader-call-operator
call
defmethodshader-call-operator
lang:arithmetic-call-operatorcall
defgenericshader-call-operands
call
defmethodshader-call-operands
lang:arithmetic-call-operandscall
defmethodshader-call-parameters
lang:arithmetic-call-parameterscall
defclassshader-function-definition
:documentation

Reusable shader source parsed into the typed graph at each call site.

defclassshader-function-call
:documentation

An inspectable typed call whose body is inlined during backend lowering.

defclassshader-conditional
:documentation

A typed value conditional from the shared language.

defclassshader-counted-fold
:documentation

A typed bounded fold lowered as structured target control flow.

defmethodshader-function-call-definition
lang:arithmetic-function-call-definitioncall
defmethodshader-function-call-arguments
lang:arithmetic-function-call-argumentscall
defmethodshader-function-call-bindings
lang:arithmetic-function-call-bindingscall
defmethodshader-function-call-result
lang:arithmetic-function-call-resultcall
defclassshader-map-application
definition:initarg:definition:readershader-map-application-definition
point:initarg:point:readershader-map-application-point
rows:initarg:rows:readershader-map-application-rows
:documentation

The homogeneous result of applying a represented semantic map.

defclassshader-map-projection
application:initarg:application:readershader-map-projection-application
:documentation

A virtual sampling product projected from a homogeneous map application.

defmethodshader-quantity-boundary-operand
lang:arithmetic-quantity-boundary-operandexpression
defclassshader-interpretation
:documentation

A checked semantic name for a represented value, with no codegen effect.

defclassshader-quantity-construction
:documentation

An explicitly meaningful value constructed from semantically raw source.

defclassshader-quantity-assumption
:documentation

An explicit assumption that an opaque represented value has a meaning.

defclassshader-representation
:documentation

An explicit exposure of a semantic value's raw machine representation.

defclassshader-unit-conversion
:documentation

An explicit linear unit conversion that may emit numerical scaling.

defgenericshader-unit-conversion-operand
expression
defmethodshader-unit-conversion-operand
lang:arithmetic-unit-conversion-operandexpression
defgenericshader-unit-conversion-factor
expression
defmethodshader-unit-conversion-factor
lang:arithmetic-unit-conversion-factorexpression
defmethodlang:arithmetic-reference-target-quantity-checked-p
or
shader-declaration-quantity-specificationtarget
shader-declaration-quantity-layouttarget
defmethodlang:arithmetic-reference-target-quantity-specification
shader-declaration-quantity-specificationtarget
defmethodlang:arithmetic-reference-target-quantity-layout
shader-declaration-quantity-layouttarget
defmethodlang:arithmetic-expression-quantity-checked-p
declare
ignoreexpression
nil
defmethodshader-expression-quantity-checked-p
shader-expression-quantity-checked-p
lang:arithmetic-counted-fold-initialexpression
defmethodshader-expression-materialized-p

Exact fields lower directly from cached components; no intermediate vec3 exists solely for compiler convenience.

declare
ignoreexpression
nil
defmethodshader-expression-quantity-checked-p

This boundary is deliberately the one way for checked source to enter an opaque representation-level calculation. Its operand remains visible in the graph, but arithmetic above the node is raw until meaning is assumed again at another explicit boundary.

defclassshader-statement
source-form:initarg:source-form:readershader-statement-source-form
:documentation

One ordered shader effect or structured group of shader effects.

defclassshader-output-assignment
output:initarg:output:readershader-assignment-output
value:initarg:value:readershader-assignment-value
defmethodshader-assignment-source-form
shader-statement-source-formassignment
defclassshader-conditional-statement
condition:initarg:condition:readershader-conditional-statement-condition
statements:initarg:statements:readershader-conditional-statement-statements
defclassshader-mesh-output-counts
vertex-count:initarg:vertex-count:readershader-mesh-output-vertex-count
primitive-count:initarg:primitive-count:readershader-mesh-output-primitive-count
defclassshader-mesh-vertex-store
index:initarg:index:readershader-mesh-vertex-store-index
values:initarg:values:readershader-mesh-vertex-store-values
defclassshader-mesh-primitive-store
index:initarg:index:readershader-mesh-primitive-store-index
indices:initarg:indices:readershader-mesh-primitive-store-indices
values:initarg:values:readershader-mesh-primitive-store-values
defclassshader-task-payload-store
field:initarg:field:readershader-task-payload-store-field
index:initarg:index:initformnil:readershader-task-payload-store-index
value:initarg:value:readershader-task-payload-store-value
defclassshader-emit-mesh-workgroups
workgroups:initarg:workgroups:readershader-emit-mesh-workgroups-counts
defclassshader-mesh-output
topology:initarg:topology:readershader-mesh-output-topology
max-vertices:initarg:max-vertices:readershader-mesh-output-max-vertices
max-primitives:initarg:max-primitives:readershader-mesh-output-max-primitives
vertex-outputs:initarg:vertex-outputs:readershader-mesh-output-vertex-outputs
primitive-outputs:initarg:primitive-outputs:readershader-mesh-output-primitive-outputs
source-form:initarg:source-form:readershader-mesh-output-source-form
defclassshader-payload-element
field:initarg:field:readershader-payload-element-field
index:initarg:index:readershader-payload-element-index
defclassshader-buffer-element
buffer:initarg:buffer:readershader-buffer-element-buffer
index:initarg:index:readershader-buffer-element-index
defclassshader-bit-field-call
size:initarg:size:readershader-bit-field-size
position:initarg:position:readershader-bit-field-position
:documentation

An ldb call whose byte specifier is part of the operator, not an operand.

defmethodshader-expression-quantity-checked-p
or
shader-declaration-quantity-specification
shader-payload-element-fieldexpression
shader-declaration-quantity-layout
shader-payload-element-fieldexpression
defmethodshader-expression-quantity-checked-p

Buffer elements are raw representations until a shader interprets them.

declare
ignoreexpression
nil
defclassshader-specification
stage:initarg:stage:readershader-specification-stage
inputs:initarg:inputs:initformnil:readershader-specification-inputs
outputs:initarg:outputs:initformnil:readershader-specification-outputs
resources:initarg:resources:initformnil:readershader-specification-resources
workgroup-size:initarg:workgroup-size:initformnil:readershader-specification-workgroup-size
task-payload:initarg:task-payload:initformnil:readershader-specification-task-payload
mesh-output:initarg:mesh-output:initformnil:readershader-specification-mesh-output
bindings:initarg:bindings:initformnil:readershader-specification-bindings
statements:initarg:statements:initformnil:readershader-specification-statements
defgenericshader-expression-form
expression
:documentation

Reconstruct the compact mathematical form of expression.

defmethodprint-object
stream
print-unreadable-object
expressionstream:typet
prin1stream
formatstream" : ~A"
shader-type-name
shader-expression-typeexpression
defgenericshader-expression-children
expression
:documentation

The immediate subexpressions expression computes from.

defmethodshader-expression-children
list
shader-payload-element-indexexpression
defmethodshader-expression-children
list
shader-buffer-element-indexexpression
defmethodlang:arithmetic-expression-children
cons
shader-map-application-pointexpression
shader-map-application-rowsexpression
defmethodlang:arithmetic-expression-children
list
shader-map-projection-applicationexpression

Virtual projective-map values retain their semantic source relationships even when a backend chooses not to materialize intermediate vectors.

defgenericshader-map-application-for-projection
expression
:documentation

Return the virtual map application denoted by expression, or NIL.

defmethodshader-map-application-for-projection
expression
declare
ignoreexpression
nil
defgenericshader-map-application-from-target
target
:documentation

Return a virtual map application carried by reference target, or NIL.

defmethodshader-map-application-from-target
target
declare
ignoretarget
nil
defgenericshader-map-projection-for-swizzle
expression
:documentation

Return the virtual sampling projection denoted by expression, or NIL.

defmethodshader-map-projection-for-swizzle
expression
declare
ignoreexpression
nil
defmethodshader-map-projection-from-target
target
declare
ignoretarget
nil
defgenericshader-statement-expressions
statement
:documentation

Return the expressions directly or recursively owned by statement.

defmethodshader-statement-expressions
list
shader-assignment-valuestatement
defmethodshader-statement-expressions
cons
shader-conditional-statement-conditionstatement
mapcan#'shader-statement-expressions
shader-conditional-statement-statementsstatement
defmethodshader-statement-expressions
list
shader-mesh-output-vertex-countstatement
shader-mesh-output-primitive-countstatement
defmethodshader-statement-expressions
cons
shader-mesh-vertex-store-indexstatement
mapcar#'cdr
shader-mesh-vertex-store-valuesstatement
defmethodshader-statement-expressions
list*
shader-mesh-primitive-store-indexstatement
shader-mesh-primitive-store-indicesstatement
mapcar#'cdr
shader-mesh-primitive-store-valuesstatement
defmethodshader-statement-expressions
removenil
list
shader-task-payload-store-indexstatement
shader-task-payload-store-valuestatement
defmethodshader-statement-expressions
list
shader-emit-mesh-workgroups-countsstatement
defunshader-specification-expressions
specification

Return the expression graph in source order, without duplicate objects.

let
seen
make-hash-table:test#'eq
expressionsnil
labels
visit
expression
unless
gethashexpressionseen
setf
gethashexpressionseen
t
pushexpressionexpressions
mapc#'visit
dolist
binding
shader-specification-bindingsspecification
dolist
statement
shader-specification-statementsspecification
mapc#'visit
nreverseexpressions
defgenericshader-expression-uniformity
expression
:documentation

Return :WORKGROUP or :INVOCATION for the expression's finest variation.

defuncombine-shader-uniformities
&restuniformities
if
member:invocationuniformities
:invocation:workgroup
defmethodshader-expression-uniformity
expressionshader-literal
declare
ignoreexpression
:workgroup
defmethodshader-expression-uniformity
let
target
typecasetarget
shader-resource:workgroup
shader-interface-variable
if
member
shader-interface-built-intarget
'
:workgroup-id:num-workgroups:workgroup-size
:workgroup:invocation
t:invocation
defunshader-symbol=
leftright
and
symbolpleft
symbolpright
string-equal
symbol-nameleft
symbol-nameright
defunfind-shader-environment-value
nameenvironment
loopfor
candidate.value
inenvironmentwhen
shader-symbol=namecandidate
returnvalue
defunshader-environment-value
nameenvironmentsource-form
or
error'shader-language-error:formsource-form:reason:unknown-name:detailsname
defunmake-shader-reference
nameenvironmentsource-form
let
target
shader-environment-valuenameenvironmentsource-form
when
and
shader-task-payload-field-element-counttarget
error'shader-language-error:formsource-form:reason:payload-array-requires-element:detailsname
when
error'shader-language-error:formsource-form:reason:storage-buffer-requires-element:detailsname
make-instance'shader-reference:targettarget:type
etypecasetarget
shader-variable-declaration
shader-declaration-typetarget
shader-binding
shader-expression-type
:quantity-specification:quantity-layout:source-formsource-form
defunshader-numeric-type-p
not
null
shader-type-component-counttype
defunrequire-shader-types
predicateoperandssource-formreason
unless
funcallpredicate
mapcar#'shader-expression-typeoperands
error'shader-language-error:formsource-form:reasonreason:details
mapcar
lambda
operand
shader-type-name
shader-expression-typeoperand
operands
defgenericinfer-shader-call-type
operatoroperandssource-form
:documentation

Check operands against operator's contract and return the call's type.

defgenericinfer-shader-call-quantity-specification
operatoroperandssource-form
:documentation

Derive semantic meaning for one shader call once annotations enter it.

defgenericinfer-shader-call-quantity-layout
operatoroperandssource-form
:documentation

Derive a packed semantic layout for one shader call, or return NIL.

defmethodinfer-shader-call-quantity-layout
operatoroperandssource-form
declare
ignoreoperatoroperandssource-form
nil
defmethodinfer-shader-call-quantity-specification
operatoroperandssource-form

Derive semantics totally once any operand descends from an annotation.

An entirely unannotated graph remains valid legacy shader source. Once an annotation enters a calculation, however, a missing operand specification or an operator without a backend-neutral rule is a source error rather than a silent loss of meaning.

handler-case
lang:arithmetic-language-error
condition
error'shader-language-error:form
lang:arithmetic-language-error-formcondition
:reason
lang:arithmetic-language-error-reasoncondition
:details
lang:arithmetic-language-error-detailscondition
defunrequire-semantic-operands
operandssource-formindices
loopforindexinindicesforoperand=
nthindexoperands
forspecification=unlessspecificationcollectintomissingfinally
whenmissing
error'shader-language-error:formsource-form:reason:missing-quantity-specification:detailsmissing
defunrequire-dimensionless-coordinate
specificationsource-form
unless
and
=
math:quantity-specification-tensor-orderspecification
1
math:dimensionless-p
math:quantity-specification-dimensionspecification
math:unitless-p
math:quantity-specification-unitspecification
error'shader-language-error:formsource-form:reason:invalid-sample-coordinate-quantity:detailsspecification
defmethodinfer-shader-call-quantity-specification
operator
eql'sample
operandssource-form
declare
ignoreoperator
let
texture
shader-resource-sample-quantity-specificationtexture
defmethodinfer-shader-call-quantity-layout
operator
eql'sample
operandssource-form
declare
ignoreoperatorsource-form
let
texture
shader-resource-sample-quantity-layouttexture
defmethodinfer-shader-call-quantity-specification
operator
operandssource-form
declare
ignoreoperatorsource-form
let
texture
shader-resource-sample-quantity-specificationtexture
defmethodinfer-shader-call-quantity-layout
operator
operandssource-form
declare
ignoreoperatorsource-form
let
texture
shader-resource-sample-quantity-layouttexture
defmethodinfer-shader-call-quantity-specification
operator
eql'uint
operandssource-form
declare
ignoreoperatoroperandssource-form
nil
defmethodinfer-shader-call-quantity-specification
operator
eql'uint64
operandssource-form
declare
ignoreoperatoroperandssource-form
nil
defmethodinfer-shader-call-quantity-specification
operator
eql'float
operandssource-form
declare
ignoreoperatoroperandssource-form
nil
defmethodinfer-shader-call-quantity-layout
operator
eql'uint
operandssource-form
declare
ignoreoperatoroperandssource-form
nil
defmethodinfer-shader-call-quantity-layout
operator
eql'uint64
operandssource-form
declare
ignoreoperatoroperandssource-form
nil
defmethodinfer-shader-call-quantity-layout
operator
eql'float
operandssource-form
declare
ignoreoperatoroperandssource-form
nil
defmethodinfer-shader-call-quantity-specification
operator
operandssource-form
declare
ignoreoperator
let
coordinate
thirdoperands
reference
fourthoperands
when
require-semantic-operandsoperandssource-form'
23
unless
zerop
math:quantity-specification-tensor-order
error'shader-language-error:formsource-form:reason:invalid-depth-reference-quantity:details
defuninfer-vector-constructor-quantity-specification
operatoroperandssource-form
declare
ignoreoperator
when
require-semantic-operandsoperandssource-form
loopforindexbelow
lengthoperands
collectindex
let*
specifications
first
firstspecifications
name
math:quantity-specification-namefirst
dolist
specification
restspecifications
unless
and
math:dimension=
math:quantity-specification-dimensionspecification
math:quantity-specification-dimensionfirst
math:unit-expression=
math:quantity-specification-unitspecification
math:quantity-specification-unitfirst
eq
math:quantity-specification-characterspecification
math:quantity-specification-characterfirst
error'shader-language-error:formsource-form:reason:invalid-quantity-operation:details:incompatible-vector-constituents
unless
eq
math:quantity-specification-namespecification
name
setfnamenil
math:make-quantity-specificationname:dimension
math:quantity-specification-dimensionfirst
:unit
math:quantity-specification-unitfirst
:tensor-order1:character
math:quantity-specification-characterfirst
defmethodinfer-shader-call-quantity-specification
operator
eql'vec2
operandssource-form
defmethodinfer-shader-call-quantity-specification
operator
eql'vec3
operandssource-form
defmethodinfer-shader-call-quantity-specification
operator
eql'vec4
operandssource-form
defmethodinfer-shader-call-type
operatoroperandssource-form
declare
ignoreoperands
error'shader-language-error:formsource-form:reason:unknown-operator:detailsoperator
defunrequire-numeric-operands
operatoroperandssource-form
unlessoperands
error'shader-language-error:formsource-form:reason:missing-operands:detailsoperator
require-shader-types
lambda
types
operandssource-form:non-numeric-arithmetic
defuninfer-uniform-arithmetic-type
operatoroperandssource-form

The shared + and - contract: every operand carries one common type.

require-numeric-operandsoperatoroperandssource-form
let
types
mapcar#'shader-expression-typeoperands
unless
every
lambda
resttypes
error'shader-language-error:formsource-form:reason:incompatible-arithmetic-types:details
mapcar#'shader-type-nametypes
firsttypes
defmethodinfer-shader-call-type
operator
eql'+
operandssource-form
infer-uniform-arithmetic-typeoperatoroperandssource-form
defmethodinfer-shader-call-type
operator
eql'-
operandssource-form
infer-uniform-arithmetic-typeoperatoroperandssource-form
defmethodinfer-shader-call-type
operator
eql'*
operandssource-form
require-numeric-operandsoperatoroperandssource-form
let*
types
mapcar#'shader-expression-typeoperands
vectors
remove-if-not#'shader-vector-type-ptypes
cond
every
lambda
resttypes
firsttypes
andvectors
eq:float
shader-type-scalar-kind
firstvectors
firstvectors
t
error'shader-language-error:formsource-form:reason:incompatible-product-types:details
mapcar#'shader-type-nametypes
defmethodinfer-shader-call-type
operator
eql'/
operandssource-form
require-numeric-operandsoperatoroperandssource-form
let
types
mapcar#'shader-expression-typeoperands
unless
=
lengthtypes
2
error'shader-language-error:formsource-form:reason:division-arity
cond
shader-type=
firsttypes
secondtypes
firsttypes
and
eq:float
shader-type-scalar-kind
firsttypes
firsttypes
t
error'shader-language-error:formsource-form:reason:incompatible-division-types:details
mapcar#'shader-type-nametypes
defuninfer-scalar-comparison-type
operandssource-form
require-shader-types
lambda
types
and
=2
lengthtypes
=1
shader-type-component-count
firsttypes
member
shader-type-scalar-kind
firsttypes
'
:float:uint
shader-type=
firsttypes
secondtypes
operandssource-form:invalid-scalar-comparison
defmacrodefine-scalar-comparison-type
operator
`
defmethodinfer-shader-call-type
operator
eql',operator
operandssource-form
declare
ignoreoperator
infer-scalar-comparison-typeoperandssource-form
defunswizzle-components
designatorsource-form
let*
name
string-downcase
symbol-namedesignator
indices
loopforcharacteracrossnamecollect
or
positioncharacter"xyzw"
positioncharacter"rgba"
error'shader-language-error:formsource-form:reason:invalid-swizzle:detailsdesignator
unless
<=1
lengthindices
4
error'shader-language-error:formsource-form:reason:invalid-swizzle-length:detailsdesignator
indices
defunvector-type-for-width
widthsource-form&optional
scalar-kind:float
find-shader-type
ecasescalar-kind
:float
ecasewidth
1:float
2:vec2
3:vec3
4:vec4
:uint
ecasewidth
1:uint
2:uvec2
3:uvec3
4:uvec4
source-form
defunvector-constructor-width
operandssource-form
loopforoperandinoperandsforcount=
shader-type-component-count
shader-expression-typeoperand
unlesscountdo
error'shader-language-error:formsource-form:reason:opaque-vector-constituent
sumcount
defmethodinfer-shader-call-type
operator
eql'dot
operandssource-form
require-shader-types
lambda
types
and
=
lengthtypes
2
eq:float
shader-type-scalar-kind
firsttypes
shader-type=
firsttypes
secondtypes
operandssource-form:invalid-dot-product
defmethodinfer-shader-call-type
operator
eql'sample
operandssource-form
require-shader-types
lambda
types
and
=
lengthtypes
3
eq
shader-type-opaque-kind
firsttypes
:texture-2d
shader-type-sample-result-type
firsttypes
eq
shader-type-opaque-kind
secondtypes
:sampler
shader-type=
thirdtypes
:vec2
operandssource-form:invalid-texture-sample
find-shader-type
shader-type-sample-result-type
shader-expression-type
firstoperands
defmethodinfer-shader-call-type
operator
operandssource-form
require-shader-types
lambda
types
and
=
lengthtypes
2
eq
shader-type-opaque-kind
firsttypes
:texture-2d
shader-type-sample-result-type
firsttypes
operandssource-form:invalid-texel-load
find-shader-type
shader-type-sample-result-type
shader-expression-type
firstoperands
defmethodinfer-shader-call-type
operator
eql'uint
operandssource-form
require-shader-types
lambda
types
and
=
lengthtypes
1
=1
shader-type-component-count
firsttypes
member
shader-type-scalar-kind
firsttypes
'
:float:uint
operandssource-form:invalid-uint-conversion
defmethodinfer-shader-call-type
operator
eql'uint64
operandssource-form
require-shader-types
lambda
types
and
=
lengthtypes
1
=1
shader-type-component-count
firsttypes
member
shader-type-scalar-kind
firsttypes
'
:float:uint
operandssource-form:invalid-uint64-conversion
defmethodinfer-shader-call-type
operator
eql'float
operandssource-form
require-shader-types
lambda
types
and
=
lengthtypes
1
=1
shader-type-component-count
firsttypes
member
shader-type-scalar-kind
firsttypes
'
:float:uint
operandssource-form:invalid-float-conversion
defmethodinfer-shader-call-type
operator
eql'mod
operandssource-form
require-shader-types
lambda
types
operandssource-form:invalid-unsigned-remainder
shader-expression-type
firstoperands
defmethodinfer-shader-call-type
operator
operandssource-form
require-shader-types
lambda
types
and
=
lengthtypes
4
eq
shader-type-opaque-kind
firsttypes
:texture-2d
shader-type-image-depth-p
firsttypes
eq
shader-type-opaque-kind
secondtypes
:sampler
shader-type=
thirdtypes
:vec2
shader-type=
fourthtypes
:float
operandssource-form:invalid-depth-comparison-sample
defmethodinfer-shader-call-type
operator
eql'mix
operandssource-form
require-shader-types
lambda
types
and
=
lengthtypes
3
shader-type=
firsttypes
secondtypes
eq:float
shader-type-scalar-kind
firsttypes
operandssource-form:invalid-mix
shader-expression-type
firstoperands

The extended-math family shares one componentwise contract: a fixed or open operand count, every operand carrying the same scalar or vector type, and a result of that type. Each operator states its accepted signature explicitly instead of promising every GLSL overload.

defuninfer-uniform-extended-type
operatoroperandssource-formminimummaximum
unless
and
<=minimum
lengthoperands
or
nullmaximum
<=
lengthoperands
maximum
error'shader-language-error:formsource-form:reason:wrong-operand-count:details
listoperator
lengthoperands
let
type
infer-uniform-arithmetic-typeoperatoroperandssource-form
unless
eq:float
shader-type-scalar-kindtype
error'shader-language-error:formsource-form:reason:invalid-extended-math-type:details
shader-type-nametype
type
defmethodinfer-shader-call-type
operator
eql'min
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form2nil
defmethodinfer-shader-call-type
operator
eql'max
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form2nil
defmethodinfer-shader-call-type
operator
eql'abs
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form11
defmethodinfer-shader-call-type
operator
eql'signum
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form11
defmethodinfer-shader-call-type
operator
eql'sqrt
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form11
macrolet
define-unary-extended-type
&restoperators
`
progn,@
mapcar
lambda
operator
`
defmethodinfer-shader-call-type
operator
eql',operator
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form11
operators
define-unary-extended-typefloorfractsincosexplog
defmethodinfer-shader-call-type
operator
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form11
defmethodinfer-shader-call-type
operator
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form11
defmethodinfer-shader-call-type
operator
eql'expt
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form22
defmethodinfer-shader-call-type
operator
eql'clamp
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form33
defmethodinfer-shader-call-type
operator
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form33
defmethodinfer-shader-call-type
operator
eql'step
operandssource-form
infer-uniform-extended-typeoperatoroperandssource-form22
defmethodinfer-shader-call-type
operator
operandssource-form
require-shader-types
lambda
types
and
=
lengthtypes
1
eq:float
shader-type-scalar-kind
firsttypes
operandssource-form:invalid-normalize
shader-expression-type
firstoperands
defuninfer-vector-constructor-type
type-namewidthoperandssource-form
unless
error'shader-language-error:formsource-form:reason:invalid-vector-width:detailswidth
defmethodinfer-shader-call-type
operator
eql'vec2
operandssource-form
infer-vector-constructor-type:vec22operandssource-form
defmethodinfer-shader-call-type
operator
eql'vec3
operandssource-form
infer-vector-constructor-type:vec33operandssource-form
defmethodinfer-shader-call-type
operator
eql'vec4
operandssource-form
infer-vector-constructor-type:vec44operandssource-form
defmethodinfer-shader-call-type
operator
eql'uvec2
operandssource-form
let
type
infer-vector-constructor-type:uvec22operandssource-form
unless
every
lambda
operand
eq:uint
shader-type-scalar-kind
shader-expression-typeoperand
operands
error'shader-language-error:formsource-form:reason:invalid-unsigned-vector-constituent
type
defmethodinfer-shader-call-type
operator
eql'uvec3
operandssource-form
let
type
infer-vector-constructor-type:uvec33operandssource-form
unless
every
lambda
operand
eq:uint
shader-type-scalar-kind
shader-expression-typeoperand
operands
error'shader-language-error:formsource-form:reason:invalid-unsigned-vector-constituent
type
defmethodinfer-shader-call-type
operator
eql'uvec4
operandssource-form
let
type
infer-vector-constructor-type:uvec44operandssource-form
unless
every
lambda
operand
eq:uint
shader-type-scalar-kind
shader-expression-typeoperand
operands
error'shader-language-error:formsource-form:reason:invalid-unsigned-vector-constituent
type

Operators are named by ordinary symbols, treating the shader language as a small compiled subset of Common Lisp plus a vector library. Where CL already has the word with the right meaning the operator IS that symbol:

  • is CL:+, exactly as SBCL's own compiler keys IR knowledge off standard

names it never funcalls. Where CL is silent (dot, mix, swizzle, ...) the operator is an exported symbol of this package. A shader-call stores the symbol, never a resolved behavior object, so redefining an operator's methods reaches every existing specification on its next compile.

defvar*shader-operator-documentation*
make-hash-table:test#'eq
defmethoddocumentation
namesymbol
type
eql'shader-operator
defmethod
new-value
namesymbol
type
eql'shader-operator
ifnew-value
setfnew-value
defgenericshader-operator-p
operator
:documentation

Whether operator names an operator of the shader language.

Membership is an open set of EQL methods: define-shader-operator admits a name, and the operator's behavior arrives as further EQL methods on parse-shader-operator-call, infer-shader-call-type, and lower-shader-call.

defmethodshader-operator-p
operator
declare
ignoreoperator
nil
defmacrodefine-shader-operator
name&optionaldocumentation

Admit name into the shader operator vocabulary, with its documentation.

Documentation lives under the SHADER-OPERATOR doc-type, so shader meaning never collides with a standard symbol's function documentation: (documentation 'CL:+ 'SHADER-OPERATOR) answers for shaders alone.

`
progn
defmethodshader-operator-p
operator
eql',name
t
,@
whendocumentation`
setf
documentation',name'shader-operator
,documentation
',name
define-shader-operator+"Componentwise addition of uniformly typed scalar or vector values."
define-shader-operator-"Componentwise subtraction, or negation when given a single operand."
define-shader-operator*"Chained multiplication of scalars, matching vectors, and vector-scalar pairs."
define-shader-operator/"Division of two matching values, or a vector scaled by a scalar's reciprocal."
define-shader-operatordot"The scalar inner product of two vectors of the same width."
define-shader-operatorsample"Sample a two-dimensional texture through a sampler at a UV coordinate."
define-shader-operatorsample-compare"Compare a depth reference through a comparison sampler at a UV coordinate."
define-shader-operatortexel-load"Load one exact two-dimensional texel at an unsigned integer coordinate."
define-shader-operatorpayload-element"Read one indexed element of the task payload shared with a mesh shader."
define-shader-operatorbuffer-element"Read one indexed element of a storage buffer resource."
define-shader-operatorldb"Extract the unsigned bit field (BYTE SIZE POSITION) of one unsigned scalar."
define-shader-operatorderivative-x"Return the horizontal screen-space derivative of a fragment value."
define-shader-operatorderivative-y"Return the vertical screen-space derivative of a fragment value."
define-shader-operatoruint"Convert one scalar float or unsigned value to a 32-bit unsigned integer."
define-shader-operatoruint64"Convert one scalar float or unsigned value to a 64-bit unsigned integer."
define-shader-operatorfloat"Convert one scalar float or unsigned value to a 32-bit float."
define-shader-operatormod"Return the unsigned remainder of two scalar integer values."
define-shader-operatormix"Linear interpolation from one value toward another by a scalar amount."
define-shader-operatorvec2"Construct a two-component vector from scalars and vectors of total width 2."
define-shader-operatorvec3"Construct a three-component vector from scalars and vectors of total width 3."
define-shader-operatorvec4"Construct a four-component vector from scalars and vectors of total width 4."
define-shader-operatoruvec2"Construct a two-component unsigned vector from unsigned constituents."
define-shader-operatoruvec3"Construct a three-component unsigned vector from unsigned constituents."
define-shader-operatoruvec4"Construct a four-component unsigned vector from unsigned constituents."
define-shader-operatorswizzle"Select and reorder vector components by a designator such as :XYZ or :RGB."
define-shader-operatormin"The componentwise minimum of two or more uniformly typed values."
define-shader-operatormax"The componentwise maximum of two or more uniformly typed values."
define-shader-operatorabs"The componentwise absolute value of one scalar or vector."
define-shader-operatorsignum"The componentwise sign: negative one, zero, or positive one."
define-shader-operatorsqrt"The componentwise square root of one scalar or vector."
define-shader-operatorexpt"Raise a value to a power, componentwise over one uniform type."

The transcendental and lattice family: what procedural image mathematics needs to build hashes, value noise, and periodic shaping without a table.

define-shader-operatorfloor"The componentwise greatest integer not above one scalar or vector."
define-shader-operatorfract"The componentwise fractional part: the value less its floor."
define-shader-operatorsin"The componentwise sine of one scalar or vector of radians."
define-shader-operatorcos"The componentwise cosine of one scalar or vector of radians."
define-shader-operatorexp"The componentwise natural exponential of one scalar or vector."
define-shader-operatorlog"The componentwise natural logarithm of one scalar or vector."
define-shader-operator<"Test two scalar floats for ordered less-than."
define-shader-operator<="Test two scalar floats for ordered less-or-equal."
define-shader-operator>"Test two scalar floats for ordered greater-than."
define-shader-operator>="Test two scalar floats for ordered greater-or-equal."
define-shader-operator="Test two scalar floats for ordered equality."
define-shader-operatorclamp"Constrain a value between uniformly typed lower and upper bounds."
define-shader-operatorsmoothstep"Hermite interpolation from zero to one across an edge pair, then a value."
define-shader-operatorstep"Return zero below an edge and one at or above it, componentwise."
define-shader-operatornormalize"Scale one vector to unit length."
define-shader-operatorquantity"Construct an explicitly meaningful scalar or vector literal."
define-shader-operatorassume-quantity"State an explicit semantic assumption about an otherwise raw value."
define-shader-operatorinterpret"Assign a checked semantic quantity specification without emitting code."
define-shader-operatorrepresentation"Expose a semantic value's raw representation without emitting code."
define-shader-operatorproject-point"Apply a named projective map to a semantic affine point."
define-shader-operatorproject-sample"Project a homogeneous map application into its declared sampling product."
define-shader-operatorconvert-unit"Explicitly express a semantic quantity in another compatible unit."

Shader functions are typed source composition. Authors write an ordinary expression body, including lexical LET*, and every call is parsed against its actual arguments into an inspectable shader-function-call. Backends inline the resulting expression graph; no shader author constructs forms.

defvar*shader-function-documentation*
make-hash-table:test#'eq
defmethoddocumentation
namesymbol
type
eql'shader-function
defmethod
new-value
namesymbol
type
eql'shader-function
ifnew-value
setfnew-value
defgenericshader-function-definition-for
name
:documentation

Return the live typed shader function named by name, or NIL.

defmethodshader-function-definition-for
name
declare
ignorename
nil
defunmake-shader-function-definition
nameparametersbody
unless
and
symbolpname
listpparameters
every#'symbolpparameters
=
lengthparameters
length
remove-duplicatesparameters:test#'eq
error'shader-language-error:form
list*'define-shader-functionnameparametersbody
:reason:invalid-shader-function-parameters:detailsparameters
unless
=
lengthbody
1
error'shader-language-error:form
list*'define-shader-functionnameparametersbody
:reason:expected-single-shader-function-body
make-instance'shader-function-definition:namename:parameter-formsparameters:parameter-namesparameters:bodybody:source-form
list*'define-shader-functionnameparametersbody
defmacrodefine-shader-function
nameparameters&bodybody

Define a reusable typed shader expression with ordinary source syntax.

The body is parsed at each call site, so argument types and quantity meanings flow through the same operator protocol as handwritten shader expressions. LET* is lexical inside the function. The definition macro records source; its body does not execute as Lisp and does not return generated S-expressions. #RO74NL

let*
function-name
gensym"FUNCTION-NAME"
documentation
and
stringp
firstbody
firstbody
forms
ifdocumentation
restbody
body
`
progn
defmethodshader-function-definition-for
,function-name
eql',name
declare
ignore,function-name
load-time-value
make-shader-function-definition',name',parameters',forms
,@
whendocumentation`
setf
documentation',name'shader-function
,documentation
',name

Abstractions are source vocabulary, not core operators. They rewrite into ordinary shader forms before parsing. Keep them for genuinely syntactic generation, such as unrolling host-known data; ordinary reusable calculations belong in define-shader-function above.

defvar*shader-abstraction-documentation*
make-hash-table:test#'eq
defvar*shader-source-revision-lock*
sb-thread:make-mutex:name"luv shader source revision"
defunshader-source-revision

Return the revision of reusable shader functions and source abstractions.

defunnote-shader-source-redefinition
name

Record that reusable shader source named by name may have changed.

declare
ignorename
defmethodlang:note-arithmetic-function-redefinition
namesymbol

Prefer newly shared source over any shader-only source of the same name.

defmethoddocumentation
namesymbol
type
eql'shader-abstraction
defmethod
new-value
namesymbol
type
eql'shader-abstraction
ifnew-value
setfnew-value
defgenericshader-abstraction-p
operator
:documentation

Whether operator names source vocabulary expanded before shader parsing.

defmethodshader-abstraction-p
operator
declare
ignoreoperator
nil
defgenericexpand-shader-abstraction-call
operatorform
:documentation

Expand one source abstraction call into core shader-language forms.

defmethodexpand-shader-abstraction-call
operatorform
declare
ignoreoperator
error'shader-language-error:formform:reason:unknown-abstraction:details
firstform
defunremove-shader-eql-methods
generic-function-namename
when
fboundpgeneric-function-name
let
generic-function
fdefinitiongeneric-function-name
when
typepgeneric-function'generic-function
dolist
method
copy-list
closer-mop:generic-function-methodsgeneric-function
let
specializer
first
closer-mop:method-specializersmethod
when
and
typepspecializer'closer-mop:eql-specializer
eqname
closer-mop:eql-specializer-objectspecializer
remove-methodgeneric-functionmethod
defunforget-shader-function
name

Remove an old typed-function definition when name becomes an abstraction.

name
defmacrodefine-shader-abstraction
namelambda-list&bodybody

Define name as a source-level shader abstraction.

The expansion body receives the destructured call operands and returns a raw shader source form made from core operators or other abstractions.

let*
form
gensym"FORM"
operator
gensym"OPERATOR"
documentation
and
stringp
firstbody
firstbody
forms
ifdocumentation
restbody
body
`
progn
defmethodshader-abstraction-p
,operator
eql',name
t
defmethodexpand-shader-abstraction-call
,operator
eql',name
,form
destructuring-bind
,operator,@lambda-list
,form
declare
ignore,operator
,@forms
,@
whendocumentation`
setf
documentation',name'shader-abstraction
,documentation
',name
defunexpand-shader-source-form
form

Expand all shader abstraction calls nested inside form.

define-shader-abstractionshadow-depth-test
depth-texturesamplercoordinatereceiver-depthbias
"One receiver-versus-depth-map comparison, filterable after comparison."`
sample-compare,depth-texture,sampler,coordinate
-,receiver-depth,bias
define-shader-abstractionshadow-visibility
depth-texturesamplercoordinatereceiver-depthreceiver-depth-gradienttexel-sizebiasradius
"Weighted disk PCF with receiver-plane depth correction at every tap."
flet
tap
xyweight
let
offset`
interpret
*,texel-size
vec2
*,radius,x
*,radius,y
:quantity:shadow-uv:character:difference
`
*,weight
shadow-depth-test,depth-texture,sampler
+,coordinate,offset
+,receiver-depth
interpret
dot,receiver-depth-gradient,offset
:quantity:shadow-depth:character:difference
,bias
`
/
+,
tap0.00.04.0

An inner, heavier ring gives the footprint a Gaussian-like core.

,@
loopfor
xy
in'
0.450.0
0.31820.3182
0.00.45
-0.31820.3182
-0.450.0
-0.3182-0.3182
0.0-0.45
0.3182-0.3182
collect
tapxy2.0

Rotate the outer ring by half a sector so no square sample border

is reinforced along the light-space axes.

,@
loopfor
xy
in'
0.92390.3827
0.38270.9239
-0.38270.9239
-0.92390.3827
-0.9239-0.3827
-0.3827-0.9239
0.3827-0.9239
0.9239-0.3827
collect
tapxy1.0
28.0
defgenericparse-shader-operator-call
operatorformenvironment
:documentation

Parse one (operator . ARGUMENTS) form into a typed shader-call.

The default method parses every argument as an expression and asks infer-shader-call-type for the result type; an operator with special syntax, such as swizzle's component designator, replaces parsing wholesale.

defmethodparse-shader-operator-call
operatorformenvironment
let
operands
mapcar
lambda
operand
parse-shader-expressionoperandenvironment
restform
make-instance'shader-call:operatoroperator:operandsoperands:type
infer-shader-call-typeoperatoroperandsform
:quantity-specification:quantity-layout:source-formform
defmethodparse-shader-operator-call
operator
formenvironment
unless
=
length
restform
2
error'shader-language-error:formform:reason:swizzle-arity
let*
operand
designator
thirdform
indices
swizzle-componentsdesignatorform
input-width
shader-type-component-count
shader-expression-typeoperand
unless
andinput-width
every
lambda
index
<indexinput-width
indices
error'shader-language-error:formform:reason:swizzle-out-of-range:detailsdesignator
let*
when
error'shader-language-error:formform:reason:undeclared-quantity-projection:detailsdesignator
make-instance'shader-call:operator'swizzle:operands
listoperand
:parameters
listdesignator
:type
vector-type-for-width
lengthindices
form
shader-type-scalar-kind
shader-expression-typeoperand
:quantity-specificationprojected:source-formform
defmethodparse-shader-operator-call
operator
formenvironment
declare
ignoreoperator
unless
=
lengthform
3
error'shader-language-error:formform:reason:payload-element-arity
let*
field-name
secondform
field
shader-environment-valuefield-nameenvironmentform
index
parse-shader-expression
thirdform
environment
unless
and
shader-task-payload-field-element-countfield
error'shader-language-error:formform:reason:not-payload-array:detailsfield-name
unless
shader-uint-type-p
shader-expression-typeindex
error'shader-language-error:formform:reason:payload-index-type:details
shader-type-name
shader-expression-typeindex
multiple-value-bind
constant-indexconstant-p
when
andconstant-p
>=constant-index
shader-task-payload-field-element-countfield
error'shader-language-error:formform:reason:payload-index-out-of-bounds:details
listconstant-index
shader-task-payload-field-element-countfield
make-instance'shader-payload-element:fieldfield:indexindex:type
shader-declaration-typefield
:quantity-specification
shader-declaration-quantity-specificationfield
:quantity-layout
shader-declaration-quantity-layoutfield
:source-formform
defmethodparse-shader-operator-call
operator
formenvironment
declare
ignoreoperator
unless
=
lengthform
3
error'shader-language-error:formform:reason:buffer-element-arity
let*
buffer-name
secondform
buffer
shader-environment-valuebuffer-nameenvironmentform
index
parse-shader-expression
thirdform
environment
unless
error'shader-language-error:formform:reason:not-storage-buffer:detailsbuffer-name
unless
shader-uint-type-p
shader-expression-typeindex
error'shader-language-error:formform:reason:buffer-index-type:details
shader-type-name
shader-expression-typeindex
make-instance'shader-buffer-element:bufferbuffer:indexindex:type
shader-storage-buffer-element-typebuffer
:quantity-specificationnil:quantity-layoutnil:source-formform
defunshader-constant-integer-value
form

Return form's integer value when it is an integer literal or a constant symbol naming one, else NIL.

cond
integerpform
form
and
symbolpform
constantpform
boundpform
integerp
symbol-valueform
symbol-valueform
tnil
defmethodparse-shader-operator-call
operator
eql'ldb
formenvironment

Parse (ldb (BYTE SIZE position) VALUE).

SIZE is a positive integer. position is an integer, or a 32-bit unsigned expression for a field whose place is only known at run time; then the field must still fit the operand's width, which is checked by the caller's data rather than the language.

unless
=
lengthform
3
error'shader-language-error:formform:reason:ldb-arity
let*
specifier
secondform
size
and
conspspecifier
=
lengthspecifier
3
shader-symbol=
firstspecifier
'byte
position-expression
andsize
parse-shader-expression
thirdspecifier
environment
value
parse-shader-expression
thirdform
environment
type
shader-expression-typevalue
unless
andsize
pluspsize
orposition-expression
error'shader-language-error:formform:reason:invalid-byte-specifier:detailsspecifier
unless
error'shader-language-error:formform:reason:invalid-bit-field-operand:details
shader-type-nametype
when
andposition-expression
not
shader-uint-type-p
shader-expression-typeposition-expression
error'shader-language-error:formform:reason:byte-position-type:details
shader-type-name
shader-expression-typeposition-expression
unless
<=
shader-type-bit-widthtype
error'shader-language-error:formform:reason:byte-specifier-exceeds-width:details
listspecifier
shader-type-bit-widthtype
make-instance'shader-bit-field-call:operatoroperator:operands
ifposition-expression
listvalueposition-expression
listvalue
:sizesize:positionposition:typetype:quantity-specificationnil:quantity-layoutnil:source-formform
defunshader-function-binding-name
definitioncall-indexrolename&optionalordinal
let
function-name
binding-name
symbol-namename
make-symbol
ifordinal
formatnil"~A-~D-~A-~D-~A"function-namecall-indexroleordinalbinding-name
formatnil"~A-~D-~A-~A"function-namecall-indexrolebinding-name
defunparse-shader-expression-body
bodyenvironment&keybinding-name-function

Parse one expression body, optionally beginning with lexical LET*.

unless
=
lengthbody
1
error'shader-language-error:formbody:reason:expected-single-shader-function-body
let
form
firstbody
if
and
conspform
eq
firstform
'let*
destructuring-bind
operatorraw-bindings&restresults
form
declare
ignoreoperator
unless
=
lengthresults
1
error'shader-language-error:formform:reason:expected-single-shader-function-result
let
bindingsnil
lexical-environmentenvironment
dolist
raw-bindingraw-bindings
unless
and
conspraw-binding
=
lengthraw-binding
2
symbolp
firstraw-binding
error'shader-language-error:formraw-binding:reason:invalid-binding
let*
source-name
firstraw-binding
name
ifbinding-name-function
funcallbinding-name-functionsource-name
source-name
expression
parse-shader-expression
secondraw-binding
lexical-environment
binding
make-instance'shader-binding:namename:expressionexpression:source-formraw-binding
setfname
pushbindingbindings
push
conssource-namebinding
lexical-environment
values
nreversebindings
parse-shader-expression
firstresults
lexical-environment
valuesnil
defunparse-shader-function-call
definitionformenvironment
let*
unless
=
lengthparameters
lengthargument-forms
error'shader-language-error:formform:reason:shader-function-arity:details
list:expected
lengthparameters
:actual
lengthargument-forms
when
membername*shader-function-call-stack*:test#'eq
error'shader-language-error:formform:reason:recursive-shader-function:details
let*
arguments
mapcar
lambda
argument
parse-shader-expressionargumentenvironment
argument-forms
parameter-bindings
loopforparameterinparametersforargumentinargumentscollect
make-instance'shader-function-parameter-binding:name
shader-function-binding-namedefinitioncall-index"PARAMETER"parameter
:expressionargument:source-form
listparameterargument
function-environment
loopforparameterinparametersforbindinginparameter-bindingscollect
consparameterbinding
let
multiple-value-bind
body-bindingsresult
parse-shader-expression-bodyfunction-environment:binding-name-function
lambda
local-name
shader-function-binding-namedefinitioncall-index"LOCAL"local-name
incflocal-index
make-instance'shader-function-call:definitiondefinition:argumentsarguments:bindings
appendparameter-bindingsbody-bindings
:resultresult:type
shader-expression-typeresult
:quantity-specification:quantity-layout:source-formform
defunparse-shader-counted-fold
formenvironment
multiple-value-bind
index-namecount-formstate-nameinitial-formupdate-formuntil-formvalid-p
unlessvalid-p
error'shader-language-error:formform:reason:invalid-counted-fold
unless
and
symbolpindex-name
symbolpstate-name
not
eqindex-namestate-name
error'shader-language-error:formform:reason:invalid-counted-fold-bindings
let*
count
parse-shader-expressioncount-formenvironment
initial
parse-shader-expressioninitial-formenvironment
count-type
shader-expression-typecount
index-binding
make-instance'shader-binding:nameindex-name:expression
make-instance'shader-literal:value
if00.0
:typecount-type:quantity-specification:source-form
listindex-name0
:source-form
listindex-name0
state-binding
make-instance'shader-binding:namestate-name:expressioninitial:source-form
liststate-nameinitial-form
fold-environment
list*
consindex-nameindex-binding
consstate-namestate-binding
environment
multiple-value-bind
update-bindingsupdate
parse-shader-expression-body
listupdate-form
fold-environment
unless
error'shader-language-error:formcount-form:reason:counted-fold-count-type
unless
and
shader-type=
shader-expression-typeinitial
shader-expression-typeupdate
error'shader-language-error:formform:reason:counted-fold-state-mismatch
make-instance'shader-counted-fold:countcount:initialinitial:index-bindingindex-binding:state-bindingstate-binding:bindingsupdate-bindings:updateupdate:until
parse-shader-counted-fold-untiluntil-formfold-environment
:type
shader-expression-typeinitial
:quantity-specification:quantity-layout:source-formform
defunparse-shader-counted-fold-until
formenvironment

Parse a COUNTED-FOLD's :UNTIL test in the fold's environment.

The test is evaluated at the head of every iteration, seeing the index and the carried state, and must be a straight-line boolean: it lowers into the loop header, so it may not itself fold.

whenform
let
until
unless
shader-type=
shader-expression-typeuntil
:bool
error'shader-language-error:formform:reason:counted-fold-until-type:details
shader-type-name
shader-expression-typeuntil
until
defunparse-shader-conditional
formenvironment
unless
=4
lengthform
error'shader-language-error:formform:reason:conditional-arity
let
condition
consequent
parse-shader-expression
thirdform
environment
alternative
parse-shader-expression
fourthform
environment
unless
shader-type=
shader-expression-typecondition
:bool
error'shader-language-error:form
secondform
:reason:conditional-condition-type:details
shader-type-name
shader-expression-typecondition
unless
and
shader-type=
shader-expression-typeconsequent
shader-expression-typealternative
error'shader-language-error:formform:reason:conditional-branch-mismatch:details
make-instance'shader-conditional:conditioncondition:consequentconsequent:alternativealternative:type
shader-expression-typeconsequent
:quantity-specification:quantity-layout:source-formform
defunparse-shader-call
formenvironment
let*
cond
eqoperator'counted-fold
eqoperator'if
parse-shader-operator-calloperatorformenvironment
t
error'shader-language-error:formform:reason:unknown-operator:detailsoperator

A live named value -- a knob, in the application's word -- may stand in shader source as a symbol. It folds to a literal at parse time, and the parse records what was folded, so a live pipeline can tell when the source it was built from has quietly moved.

defgenericshader-source-value
name
:documentation

The live value name stands for in shader source, or NIL when name names none. Returns (VALUES VALUE declaration FOUND-P): VALUE is a real, and declaration, when given, is a represented-value declaration whose quantity the literal takes on.

defmethodshader-source-value
namet
declare
ignorename
valuesnilnilnil
defvar*shader-source-value-references*nil

When bound to a cons cell, its car collects (NAME . VALUE) for every live named value folded while parsing, so the parser's caller can remember what its artifact depends on.

defunshader-source-value-literal
form

form as a folded literal when it names a live shader source value.

multiple-value-bind
valuedeclarationfound-p
whenfound-p
make-instance'shader-literal:value
coercevalue'single-float
:type:quantity-specification:source-formform
defunshader-source-value-references-current-p
references

Whether every (NAME . VALUE) in references still names that value.

every
lambda
reference
multiple-value-bind
valuedeclarationfound-p
declare
andfound-p
eqlvalue
cdrreference
references
defunparse-shader-expression
formenvironment
cond
realpform
make-instance'shader-literal:value
coerceform'single-float
:type:quantity-specification:source-formform
symbolpform
cond
make-shader-referenceformenvironmentform
and
constantpform
boundpform
realp
symbol-valueform
make-instance'shader-literal:value
coerce
symbol-valueform
'single-float
:type:quantity-specification:source-formform
t
make-shader-referenceformenvironmentform
conspform
parse-shader-callformenvironment
t
error'shader-language-error:formform:reason:unsupported-expression
defunshader-type-tensor-order
typesource-form
let
count
shader-type-component-counttype
unlesscount
error'shader-language-error:formsource-form:reason:quantity-on-opaque-type:details
shader-type-nametype
if
=count1
01
defundeclared-character
affine-pcharacter

Merge the historical :affine-p and the general :character source keywords into one designator for parse-declaration-quantity-specification.

orcharacter
andaffine-pt
defundeclared-character-options
character

Translate a source character designator into constructor options.

NIL leaves the character to the named definition; T is the historical :AFFINE-P spelling of a point; a keyword names the character directly.

cond
nullcharacter
nil
eqcharactert
list:character:point
t
list:charactercharacter
defunparse-declaration-quantity-specification
quantitydimensionunitcharactertypesource-form
when
orquantitydimensionunitcharacter
with-shader-quantity-errors
source-form:invalid-quantity-declaration
defunparse-declaration-quantity-layout
componentstypesource-form&optionalwhole
whencomponents
let
extent
shader-type-component-counttype
unless
andextent
>extent1
error'shader-language-error:formsource-form:reason:quantity-components-on-non-vector:details
shader-type-nametype
let
occupiednil
projectionsnil
dolist
component-formcomponents
destructuring-bind
selector&keyquantity
dimensionnildimension-supplied-p
unitnilunit-supplied-p
affine-pnilaffine-supplied-p
characternilcharacter-supplied-p
component-form
unlessquantity
error'shader-language-error:formcomponent-form:reason:missing-component-quantity
let
positions
unless
every
lambda
<positionextent
positions
error'shader-language-error:formcomponent-form:reason:swizzle-out-of-range:detailsselector
let
overlap
intersectionpositionsoccupied
whenoverlap
error'shader-language-error:formcomponent-form:reason:overlapping-quantity-components:detailsoverlap
setfoccupied
appendpositionsoccupied
let
projection-type
vector-type-for-width
lengthpositions
component-form
shader-type-scalar-kindtype
push
math:make-quantity-projectionpositions
parse-declaration-quantity-specificationquantity
ifdimension-supplied-pdimension
andwhole
math:quantity-specification-dimensionwhole
ifunit-supplied-punit
andwhole
math:quantity-specification-unitwhole
cond
character-supplied-pcharacter
affine-supplied-p
andaffine-p:point
whole
math:quantity-specification-characterwhole
tnil
projection-typecomponent-form
projections
math:make-quantity-layoutextent
nreverseprojections
defunmake-projective-shader-map-definition
name&keydomain-typedomain-quantitydomain-dimensiondomain-unitdomain-affine-psample-typesample-componentscoordinate-scalecoordinate-offsetsource-form

Construct a checked projective map definition from declarative semantics.

let*
domain-type
find-shader-typedomain-typesource-form
homogeneous-type
find-shader-type:vec4source-form
sample-type
find-shader-typesample-typesource-form
domain-component-count
shader-type-component-countdomain-type
component-count
shader-type-component-countsample-type
unless
anddomain-component-countcomponent-count
=domain-component-count3
=component-count3
listpcoordinate-scale
listpcoordinate-offset
=
lengthcoordinate-scale
component-count
=
lengthcoordinate-offset
component-count
every#'realpcoordinate-scale
every#'realpcoordinate-offset
error'shader-language-error:formsource-form:reason:invalid-projective-map-shape
let
domain
parse-declaration-quantity-specificationdomain-quantitydomain-dimensiondomain-unitdomain-affine-pdomain-typesource-form
sample-layout
parse-declaration-quantity-layoutsample-componentssample-typesource-form
unless
error'shader-language-error:formsource-form:reason:invalid-projective-map-semantics
make-instance'shader-projective-map-definition:namename:source-formsource-form:domain-typedomain-type:domain-quantity-specificationdomain:homogeneous-typehomogeneous-type:sample-typesample-type:sample-quantity-layoutsample-layout:coordinate-scalecoordinate-scale:coordinate-offsetcoordinate-offset
defmacrodefine-projective-shader-map
name&keydomain-typedomain-quantitydomain-dimensiondomain-unitdomain-affine-psample-typesample-componentscoordinate-scalecoordinate-offset

Define an inspectable projective map behind an EQL-specialized protocol.

let
storage
intern
formatnil"*~A-SHADER-MAP*"
symbol-namename
*package*
source`
define-projective-shader-map,name:domain-type,domain-type:domain-quantity,domain-quantity:domain-dimension,domain-dimension:domain-unit,domain-unit:domain-affine-p,domain-affine-p:sample-type,sample-type:sample-components,sample-components:coordinate-scale,coordinate-scale:coordinate-offset,coordinate-offset
`
progn
defparameter,storage
make-projective-shader-map-definition',name:domain-type',domain-type:domain-quantity',domain-quantity:domain-dimension',domain-dimension:domain-unit',domain-unit:domain-affine-p',domain-affine-p:sample-type',sample-type:sample-components',sample-components:coordinate-scale',coordinate-scale:coordinate-offset',coordinate-offset:source-form',source
defmethodshader-map-definition-for
map-name
eql',name
declare
ignoremap-name
,storage
',name
defmethodparse-shader-operator-call
operator
formenvironment
declare
ignoreoperator
destructuring-bind
namemap-namepoint-form&restrow-forms
form
declare
ignorename
unless
symbolpmap-name
error'shader-language-error:formform:reason:invalid-shader-map-name:detailsmap-name
let
unlessdefinition
error'shader-language-error:formform:reason:undefined-shader-map:detailsmap-name
unless
=
lengthrow-forms
4
error'shader-language-error:formform:reason:projective-map-row-count:details
lengthrow-forms
let*
point
parse-shader-expressionpoint-formenvironment
rows
mapcar
lambda
row
row-forms
unless
and
shader-type=
shader-expression-typepoint
shader-map-domain-typedefinition
point-quantity
math:quantity-specification=point-quantity
shader-map-domain-quantity-specificationdefinition
error'shader-language-error:formform:reason:projective-map-domain-mismatch:details
unless
every
lambda
row
rows
error'shader-language-error:formform:reason:invalid-projective-map-rows:details
make-instance'shader-map-application:definitiondefinition:pointpoint:rowsrows:type
shader-projective-map-homogeneous-typedefinition
:source-formform
defmethodparse-shader-operator-call
operator
formenvironment
declare
ignoreoperator
destructuring-bind
nameapplication-form
form
declare
ignorename
let*
operand
parse-shader-expressionapplication-formenvironment
unlessapplication
error'shader-language-error:formform:reason:sampling-projection-requires-map-application:details
let
definition
shader-map-application-definitionapplication
unless
error'shader-language-error:formform:reason:unsupported-sampling-projection:details
class-name
class-ofdefinition
make-instance'shader-map-projection:applicationapplication:type
shader-projective-map-sample-typedefinition
:quantity-layout
shader-projective-map-sample-quantity-layoutdefinition
:source-formform
defmethodparse-shader-operator-call
operator
formenvironment
declare
ignoreoperator
destructuring-bind
nameoperand-form&keyquantitydimensionunitaffine-pcharacter
form
declare
ignorename
unless
orquantitydimensionunitaffine-pcharacter
error'shader-language-error:formform:reason:missing-quantity-interpretation
let*
operand
parse-shader-expressionoperand-formenvironment
type
shader-expression-typeoperand
make-instance'shader-interpretation:operandoperand:typetype:quantity-specificationinterpretation:source-formform
defmethodparse-shader-operator-call
operator
formenvironment
declare
ignoreoperator
destructuring-bind
nameoperand-form&key
unitnilunit-supplied-p
form
declare
ignorename
unlessunit-supplied-p
error'shader-language-error:formform:reason:missing-target-unit
let*
unlesssource
error'shader-language-error:formform:reason:unit-conversion-requires-quantity
with-shader-quantity-errors
form:invalid-unit-conversion
multiple-value-bind
targetfactor
make-instance'shader-unit-conversion:operandoperand:factorfactor:type
shader-expression-typeoperand
:quantity-specificationtarget:source-formform
defunshader-constant-uint-value
expression

Return a compile-time unsigned value and true, or NIL and false.

typecaseexpression
t
valuesnilnil
defunparse-raw-quantity-boundary
classformenvironment&keyconstant-only-p
destructuring-bind
nameoperand-form&keyquantitydimensionunitaffine-pcharacter
form
declare
ignorename
unless
orquantitydimensionunitaffine-pcharacter
error'shader-language-error:formform:reason:missing-quantity-interpretation
let*
operand
parse-shader-expressionoperand-formenvironment
type
shader-expression-typeoperand
when
error'shader-language-error:formform:reason:quantity-already-has-semantics:details
when
error'shader-language-error:formform:reason:quantity-requires-literal-construction:details
make-instanceclass:operandoperand:typetype:quantity-specification:source-formform
defmethodparse-shader-operator-call
operator
formenvironment
declare
ignoreoperator
defmethodparse-shader-operator-call
operator
formenvironment
declare
ignoreoperator
defmethodparse-shader-operator-call
operator
formenvironment
declare
ignoreoperator
unless
=
lengthform
2
error'shader-language-error:formform:reason:representation-arity
let
operand
unless
error'shader-language-error:formform:reason:representation-requires-quantity:details
make-instance'shader-representation:operandoperand:type
shader-expression-typeoperand
:source-formform
defunparse-interface-declaration
formdirection
destructuring-bind
nametype&keylocationbuilt-inquantitydimensionunitaffine-pcharactercomponentsinterpolation
form
unless
or
and
typeplocation'
integer0*
and
nulllocation
built-in
error'shader-language-error:formform:reason:invalid-interface-decoration:details
list:locationlocation:built-inbuilt-in
unless
memberinterpolation'
nil:flat
error'shader-language-error:formform:reason:invalid-interface-interpolation:detailsinterpolation
when
andinterpolationbuilt-in
error'shader-language-error:formform:reason:interpolation-on-built-in:detailsbuilt-in
let*
resolved-type
specification
make-instance'shader-interface-variable:namename:typeresolved-type:quantity-specificationspecification:quantity-layout
parse-declaration-quantity-layoutcomponentsresolved-typeformspecification
:directiondirection:locationlocation:built-inbuilt-in:interpolationinterpolation:source-formform
defunparse-resource-declaration
form
destructuring-bind
nametype&key
set0
bindingmemberselementsample-quantitysample-dimensionsample-unitsample-affine-psample-charactersample-componentssample-transfer
form
unless
and
typepset'
integer0*
typepbinding'
integer0*
error'shader-language-error:formform:reason:invalid-resource-location:details
listsetbinding
when
error'shader-language-error:formform:reason:element-on-non-storage-buffer
cond
shader-symbol=type:storage-buffer
let
unless
andelement-type
shader-type-component-countelement-type
member
shader-type-component-countelement-type
'
124
error'shader-language-error:formform:reason:invalid-storage-buffer-element:detailselement
whenmembers
error'shader-language-error:formform:reason:members-on-opaque-resource
make-instance'shader-storage-buffer:namename:type
find-shader-type:storage-bufferform
:element-typeelement-type:descriptor-setset:bindingbinding:source-formform
shader-symbol=type:uniform-block
let
block
make-instance'shader-uniform-block:namename:type
find-shader-type:uniform-blockform
:descriptor-setset:bindingbinding:source-formform
unless
and
listpmembers
members
error'shader-language-error:formform:reason:empty-uniform-block
setf
shader-uniform-block-membersblock
loopformember-forminmembersforindexfrom0collect
destructuring-bind
member-namemember-type&keyquantitydimensionunitaffine-pcharactercomponents
member-form
let
resolved-type
find-shader-typemember-typemember-form

This intentionally models the renderer's current camera ABI: an aggregate of aligned vec4 lanes. Do not imply general std140 packing until the language owns that calculation explicitly.

unless
eqresolved-type
error'shader-language-error:formmember-form:reason:unsupported-uniform-member-type:detailsmember-type
let
specification
make-instance'shader-uniform-member:namemember-name:typeresolved-type:quantity-specificationspecification:quantity-layout
parse-declaration-quantity-layoutcomponentsresolved-typemember-formspecification
:blockblock:indexindex:offset
*index16
:source-formmember-form
block
t
let*
resolved-type
sample-type
and
shader-type-sample-result-typeresolved-type
find-shader-type
shader-type-sample-result-typeresolved-type
form
sample-specification
andsample-type
parse-declaration-quantity-specificationsample-quantitysample-dimensionsample-unit
declared-charactersample-affine-psample-character
sample-typeform
unless
and
shader-type-opaque-kindresolved-type
not
eq
shader-type-opaque-kindresolved-type
:uniform-block
error'shader-language-error:formform:reason:non-resource-type:detailstype
whenmembers
error'shader-language-error:formform:reason:members-on-opaque-resource
unless
membersample-transfer'
nil:identity:srgb-to-linear
error'shader-language-error:formform:reason:invalid-sample-transfer:detailssample-transfer
when
and
orsample-quantitysample-dimensionsample-unitsample-affine-psample-charactersample-componentssample-transfer
nullsample-type
error'shader-language-error:formform:reason:sample-semantics-on-non-texture
make-instance'shader-resource:namename:typeresolved-type:sample-quantity-specificationsample-specification:sample-quantity-layout
andsample-type
parse-declaration-quantity-layoutsample-componentssample-typeformsample-specification
:sample-transfersample-transfer:descriptor-setset:bindingbinding:source-formform
defunparse-output-assignment
formenvironmentoutputs
unless
and
conspform
eq
firstform
'set-output
=
lengthform
3
error'shader-language-error:formform:reason:expected-output-assignment
let*
output-name
secondform
output
shader-environment-valueoutput-name
mapcar
lambda
item
consitem
outputs
form
value
parse-shader-expression
thirdform
environment
unless
shader-type=
shader-declaration-typeoutput
shader-expression-typevalue
error'shader-language-error:formform:reason:output-type-mismatch:details
list
shader-type-name
shader-declaration-typeoutput
shader-type-name
shader-expression-typevalue
let
expected
shader-declaration-quantity-specificationoutput
expected-layout
shader-declaration-quantity-layoutoutput
when
andexpected
or
nullactual
error'shader-language-error:formform:reason:output-quantity-mismatch:details
listexpectedactual
when
andexpected-layout
or
nullactual-layout
not
math:quantity-layout=expected-layoutactual-layout
error'shader-language-error:formform:reason:output-quantity-layout-mismatch:details
listexpected-layoutactual-layout
make-instance'shader-output-assignment:outputoutput:valuevalue:source-formform
defclassshader-parsing-context
stage:initarg:stage:readershader-parsing-context-stage
outputs:initarg:outputs:initformnil:readershader-parsing-context-outputs
task-payload:initarg:task-payload:initformnil:readershader-parsing-context-task-payload
mesh-output:initarg:mesh-output:initformnil:readershader-parsing-context-mesh-output
defuncheck-shader-store-value
declarationvalueformtype-reasonquantity-reasonlayout-reason
unless
shader-type=
shader-declaration-typedeclaration
shader-expression-typevalue
error'shader-language-error:formform:reasontype-reason:details
list
shader-type-name
shader-declaration-typedeclaration
shader-type-name
shader-expression-typevalue
let
expected
shader-declaration-quantity-specificationdeclaration
expected-layout
shader-declaration-quantity-layoutdeclaration
when
andexpected
or
nullactual
error'shader-language-error:formform:reasonquantity-reason:details
listexpectedactual
when
andexpected-layout
or
nullactual-layout
not
math:quantity-layout=expected-layoutactual-layout
error'shader-language-error:formform:reasonlayout-reason:details
listexpected-layoutactual-layout
value
defgenericparse-shader-statement
operatorstageformenvironmentcontext
:documentation

Parse one stage effect, dispatching on its source operator and stage.

defmethodparse-shader-statement
operatorstageformenvironmentcontext
declare
ignoreenvironmentcontext
error'shader-language-error:formform:reason:invalid-statement-for-stage:details
listoperatorstage
defmethodparse-shader-statement
operator
eql'set-output
stageformenvironmentcontext
declare
ignoreoperator
unless
memberstage'
:vertex:fragment:compute
error'shader-language-error:formform:reason:invalid-statement-for-stage:details
list'set-outputstage
parse-output-assignmentformenvironment
shader-parsing-context-outputscontext
defunparse-complete-mesh-output-values
formsdeclarationsenvironmentsource-form
let
seennil
parsednil
dolist
formforms
unless
and
conspform
=
lengthform
2
symbolp
firstform
error'shader-language-error:formform:reason:invalid-mesh-output-value
let*
unlessdeclaration
error'shader-language-error:formform:reason:unknown-mesh-output:detailsname
when
memberdeclarationseen
error'shader-language-error:formform:reason:duplicate-mesh-output:detailsname
let
value
check-shader-store-valuedeclarationvalueform:mesh-output-type-mismatch:mesh-output-quantity-mismatch:mesh-output-quantity-layout-mismatch
pushdeclarationseen
push
consdeclarationvalue
parsed
let
missing
set-differencedeclarationsseen
whenmissing
error'shader-language-error:formsource-form:reason:missing-mesh-output-values:details
mapcar#'shader-object-namemissing
loopfordeclarationindeclarationscollect
assocdeclarationparsed
defmethodparse-shader-statement
operator
eql'set-mesh-output-counts
stage
eql:mesh
formenvironmentcontext
declare
ignoreoperatorcontext
unless
=
lengthform
3
error'shader-language-error:formform:reason:mesh-output-counts-arity
let
vertex-count
primitive-count
parse-shader-expression
thirdform
environment
unless
and
shader-uint-type-p
shader-expression-typevertex-count
shader-uint-type-p
shader-expression-typeprimitive-count
error'shader-language-error:formform:reason:mesh-output-count-type
make-instance'shader-mesh-output-counts:vertex-countvertex-count:primitive-countprimitive-count:source-formform
defmethodparse-shader-statement
operator
eql'set-mesh-vertex
stage
eql:mesh
formenvironmentcontext
declare
ignoreoperator
unless
error'shader-language-error:formform:reason:mesh-vertex-arity
let*
index
mesh-output
shader-parsing-context-mesh-outputcontext
unless
shader-uint-type-p
shader-expression-typeindex
error'shader-language-error:formform:reason:mesh-output-index-type
make-instance'shader-mesh-vertex-store:indexindex:values
parse-complete-mesh-output-values
cddrform
shader-mesh-output-vertex-outputsmesh-output
environmentform
:source-formform
defunmesh-topology-index-type
topology
ecasetopology
:points:uint
:lines:uvec2
:triangles:uvec3
defmethodparse-shader-statement
operator
eql'set-mesh-primitive
stage
eql:mesh
formenvironmentcontext
declare
ignoreoperator
unless
error'shader-language-error:formform:reason:mesh-primitive-arity
let*
index
indices
parse-shader-expression
thirdform
environment
mesh-output
shader-parsing-context-mesh-outputcontext
expected-index-type
mesh-topology-index-type
shader-mesh-output-topologymesh-output
unless
shader-uint-type-p
shader-expression-typeindex
error'shader-language-error:formform:reason:mesh-output-index-type
unless
shader-type=expected-index-type
shader-expression-typeindices
error'shader-language-error:formform:reason:mesh-primitive-indices-type:details
listexpected-index-type
shader-type-name
shader-expression-typeindices
make-instance'shader-mesh-primitive-store:indexindex:indicesindices:values
parse-complete-mesh-output-values
cdddrform
shader-mesh-output-primitive-outputsmesh-output
environmentform
:source-formform
defunshader-payload-field-named
namepayloadsource-form
or
andpayload
findname
shader-task-payload-fieldspayload
:key#'shader-object-name:test#'shader-symbol=
error'shader-language-error:formsource-form:reason:unknown-payload-field:detailsname
defmethodparse-shader-statement
operator
eql'set-payload
stage
eql:task
formenvironmentcontext
declare
ignoreoperator
unless
=
lengthform
3
error'shader-language-error:formform:reason:set-payload-arity
let*
field
shader-payload-field-named
secondform
shader-parsing-context-task-payloadcontext
form
value
parse-shader-expression
thirdform
environment
when
shader-task-payload-field-element-countfield
error'shader-language-error:formform:reason:payload-array-requires-element:details
check-shader-store-valuefieldvalueform:payload-type-mismatch:payload-quantity-mismatch:payload-quantity-layout-mismatch
make-instance'shader-task-payload-store:fieldfield:valuevalue:source-formform
defmethodparse-shader-statement
operator
eql'set-payload-element
stage
eql:task
formenvironmentcontext
declare
ignoreoperator
unless
=
lengthform
4
error'shader-language-error:formform:reason:set-payload-element-arity
let*
field
shader-payload-field-named
secondform
shader-parsing-context-task-payloadcontext
form
index
parse-shader-expression
thirdform
environment
value
parse-shader-expression
fourthform
environment
unless
shader-task-payload-field-element-countfield
error'shader-language-error:formform:reason:not-payload-array:details
unless
shader-uint-type-p
shader-expression-typeindex
error'shader-language-error:formform:reason:payload-index-type
multiple-value-bind
constant-indexconstant-p
when
andconstant-p
>=constant-index
shader-task-payload-field-element-countfield
error'shader-language-error:formform:reason:payload-index-out-of-bounds:details
listconstant-index
shader-task-payload-field-element-countfield
check-shader-store-valuefieldvalueform:payload-type-mismatch:payload-quantity-mismatch:payload-quantity-layout-mismatch
make-instance'shader-task-payload-store:fieldfield:indexindex:valuevalue:source-formform
defmethodparse-shader-statement
operator
eql'emit-mesh-workgroups
stage
eql:task
formenvironmentcontext
declare
ignoreoperatorcontext
unless
=
lengthform
2
error'shader-language-error:formform:reason:emit-mesh-workgroups-arity
let
workgroups
unless
shader-type=:uvec3
shader-expression-typeworkgroups
error'shader-language-error:formform:reason:mesh-workgroups-type:details
shader-type-name
shader-expression-typeworkgroups
make-instance'shader-emit-mesh-workgroups:workgroupsworkgroups:source-formform
defmethodparse-shader-statement
operator
eql'when
stageformenvironmentcontext
declare
ignoreoperator
unless
error'shader-language-error:formform:reason:shader-when-arity
let
condition
unless
shader-type=:bool
shader-expression-typecondition
error'shader-language-error:formform:reason:shader-when-condition-type
make-instance'shader-conditional-statement:conditioncondition:statements
mapcar
lambda
statement
parse-shader-statement-formstatementstageenvironmentcontext
cddrform
:source-formform
defunparse-shader-statement-form
formstageenvironmentcontext
unless
and
conspform
symbolp
firstform
error'shader-language-error:formform:reason:invalid-shader-statement
parse-shader-statement
firstform
stageformenvironmentcontext
defunparse-shader-body
bodyenvironmentcontext
unless
=
lengthbody
1
error'shader-language-error:formbody:reason:expected-single-shader-body
let
form
firstbody

LET* is CL:LET* by identity: the language is a compiled subset of CL, and its binding form is the standard symbol, not a look-alike.

if
and
conspform
eq
firstform
'let*
destructuring-bind
operatorraw-bindings&reststatements
form
declare
ignoreoperator
let
bindingsnil
lexical-environmentenvironment
dolist
raw-bindingraw-bindings
unless
and
conspraw-binding
=
lengthraw-binding
2
symbolp
firstraw-binding
error'shader-language-error:formraw-binding:reason:invalid-binding
let*
name
firstraw-binding
expression
parse-shader-expression
secondraw-binding
lexical-environment
binding
make-instance'shader-binding:namename:expressionexpression:source-formraw-binding
setfname
pushbindingbindings
push
consnamebinding
lexical-environment
values
nreversebindings
mapcar
lambda
statement
parse-shader-statement-formstatement
shader-parsing-context-stagecontext
lexical-environmentcontext
statements
valuesnil
list
parse-shader-statement-formform
shader-parsing-context-stagecontext
environmentcontext
defuncollect-shader-bindings
bindingsstatements

Hoist inline-function lexical bindings in dependency order.

The bindings remain typed objects owned by each shader-function-call. Values needed by the entry block are flattened there, while expressions inside a structured conditional remain owned by that arm so backends do not eagerly evaluate work which the condition excludes.

let
seen
make-hash-table:test#'eq
orderednil
labels
add-binding
bindinghoist-p
unless
or
nothoist-p
gethashbindingseen
visithoist-p
setf
gethashbindingseen
t
pushbindingordered
visit
expressionhoist-p
typecaseexpression
shader-counted-fold

COUNT and INITIAL belong to the preheader. UPDATE owns its lexical work inside the loop body.

visit
lang:arithmetic-counted-fold-countexpression
hoist-p
visit
lang:arithmetic-counted-fold-initialexpression
hoist-p
shader-function-call

A non-hoisted call is lowered where it occurs; its owned bindings and any nested calls travel with it.

whenhoist-p
dolist
visitargumenthoist-p
dolist
if
visithoist-p
add-bindingbindinghoist-p
visithoist-p
t
dolist
visitchildhoist-p
visit-statement
statementhoist-p
typecasestatement
shader-conditional-statement
visit
shader-conditional-statement-conditionstatement
hoist-p
dolist
child
shader-conditional-statement-statementsstatement
visit-statementchildnil
t
dolist
expression
visitexpressionhoist-p
dolist
bindingbindings
add-bindingbindingt
dolist
statementstatements
visit-statementstatementt
nreverseordered
defunparse-workgroup-size
formoptions
unless
and
listpform
=
lengthform
3
every
lambda
value
typepvalue'
integer1*
form
error'shader-language-error:formoptions:reason:invalid-workgroup-size:detailsform
form
defunparse-mesh-output-declaration
form
unless
listpform
error'shader-language-error:formform:reason:invalid-mesh-output
let
topology
getfform:topology
max-vertices
getfform:max-vertices
max-primitives
getfform:max-primitives
unless
membertopology'
:points:lines:triangles
error'shader-language-error:formform:reason:invalid-mesh-topology:detailstopology
unless
and
typepmax-vertices'
integer1*
typepmax-primitives'
integer1*
error'shader-language-error:formform:reason:invalid-mesh-output-limits:details
listmax-verticesmax-primitives
let
vertex-outputs
mapcar
getfform:vertex
primitive-outputs
mapcar
getfform:primitive
unlessvertex-outputs
error'shader-language-error:formform:reason:empty-mesh-vertex-output
unless
=1
count:positionvertex-outputs:key#'shader-interface-built-in
error'shader-language-error:formform:reason:mesh-position-output-count
make-instance'shader-mesh-output:topologytopology:max-verticesmax-vertices:max-primitivesmax-primitives:vertex-outputsvertex-outputs:primitive-outputsprimitive-outputs:source-formform
defunworkgroup-built-in-type
casebuilt-in
:local-invocation-index:uint
:local-invocation-id:workgroup-id:num-workgroups:workgroup-size
:uvec3
otherwisenil
defunvalidate-workgroup-inputs
inputsoptions
let
seennil
dolist
inputinputs
let*
built-in
shader-interface-built-ininput
unlessexpected
error'shader-language-error:form:reason:invalid-workgroup-input:detailsbuilt-in
unless
shader-type=expected
shader-declaration-typeinput
error'shader-language-error:form:reason:workgroup-built-in-type:details
listbuilt-inexpected
when
memberbuilt-inseen
error'shader-language-error:formoptions:reason:duplicate-workgroup-built-in:detailsbuilt-in
pushbuilt-inseen
unless
member:local-invocation-indexseen
error'shader-language-error:formoptions:reason:missing-local-invocation-index
defunstatement-tree-occurrences
statementsclass
loopforstatementinstatementsappend
append
when
typepstatementclass
liststatement
when
statement-tree-occurrences
shader-conditional-statement-statementsstatement
class
defunvalidate-stage-statements
stagestatementssource-form&optionalmesh-output
ecasestage
:vertex:fragment:compute
nil
:mesh
let
unless
=
lengthcounts
1
error'shader-language-error:formsource-form:reason:mesh-output-counts-count:details
lengthcounts
unless
eq
firststatements
firstcounts
error'shader-language-error:form
shader-statement-source-form
firstcounts
:reason:mesh-output-counts-must-be-first
unless
error'shader-language-error:form
shader-statement-source-form
firstcounts
:reason:mesh-output-counts-not-uniform
loopforexpressioninforlimitin
list
shader-mesh-output-max-verticesmesh-output
shader-mesh-output-max-primitivesmesh-output
do
multiple-value-bind
constantconstant-p
when
andconstant-p
error'shader-language-error:form
shader-statement-source-form
firstcounts
:reason:mesh-output-count-exceeds-limit:details
listconstantlimit
unlessstores
error'shader-language-error:formsource-form:reason:empty-mesh-output-body
:task
let
unless
=
lengthemissions
1
error'shader-language-error:formsource-form:reason:mesh-workgroups-emission-count:details
lengthemissions
unless
eq
car
laststatements
firstemissions
error'shader-language-error:form
shader-statement-source-form
firstemissions
:reason:mesh-workgroups-emission-must-be-last
unless
shader-expression-workgroup-uniform-p
shader-emit-mesh-workgroups-counts
firstemissions
error'shader-language-error:form
shader-statement-source-form
firstemissions
:reason:mesh-workgroups-not-uniform
defunparse-shader-specification
nameoptionsbody
let*
stage
getfoptions:stage
expanded-body
inputs
mapcar
lambda
form
getfoptions:inputs
outputs
mapcar
lambda
form
getfoptions:outputs
resources
mapcar#'parse-resource-declaration
getfoptions:resources
workgroup-size
and
memberstage'
:task:mesh
parse-workgroup-size
getfoptions:workgroup-size
options
payload-name
getfoptions:payload
payload
andpayload-name
or
error'shader-language-error:formoptions:reason:undefined-task-payload:detailspayload-name
mesh-output
and
eqstage:mesh
parse-mesh-output-declaration
getfoptions:mesh-output
environment-items
appendinputs
loopforresourceinresourcesif
typepresource'shader-uniform-block
append
shader-uniform-block-membersresource
elsecollectresource
andpayload
shader-task-payload-fieldspayload
environment
mapcar
lambda
item
consitem
environment-items
unless
memberstage'
:vertex:fragment:compute:task:mesh
error'shader-language-error:formoptions:reason:invalid-stage:detailsstage
when
memberstage'
:task:mesh
whenoutputs
error'shader-language-error:formoptions:reason:ordinary-outputs-on-workgroup-stage
when
and
eqstage:task
getfoptions:mesh-output
error'shader-language-error:formoptions:reason:mesh-output-on-task-stage
when
and
not
memberstage'
:task:mesh
orpayload-name
getfoptions:mesh-output
error'shader-language-error:formoptions:reason:workgroup-contract-on-ordinary-stage
let
let
context
make-instance'shader-parsing-context:stagestage:outputsoutputs:task-payloadpayload:mesh-outputmesh-output
multiple-value-bind
bindingsstatements
parse-shader-bodyexpanded-bodyenvironmentcontext
validate-stage-statementsstagestatements
list*'define-shadernameoptionsbody
mesh-output
make-instance'shader-specification:namename:stagestage:inputsinputs:outputsoutputs:resourcesresources:workgroup-sizeworkgroup-size:task-payloadpayload:mesh-outputmesh-output:bindings
collect-shader-bindingsbindingsstatements
:statementsstatements:source-form
list*'define-shadernameoptionsbody
defmacrodefine-shader
nameoptions&bodybody

Define name as a function returning a durable, inspectable shader graph.

let*
package
or
symbol-packagename
*package*
variable
intern
formatnil"*~A*"
symbol-namename
package
`
progn
defparameter,variable
parse-shader-specification',name',options',body
defun,name
,variable

A whole-renderer live artifact cannot subscribe narrowly to a

standalone shader function through the method MOP. Publish the

same source revision used by shared shader functions so replacing a

top-level stage also invalidates its owning cohort.

',name
defmacrodefine-live-shader
nameoptions&bodybody

Define name as a function that reparses its shader source on every call.

Where define-shader parses once at load, this parses each time it is asked, so live named values (shader-source-value) folded into the body are read afresh -- and noted in *SHADER-SOURCE-VALUE-REFERENCES* -- by every pipeline build, exactly as a define-shader-method's body is. Parsing at load still happens once, to fail early on a broken source.

`
progn
parse-shader-specification',name',options',body
defun,name
parse-shader-specification',name',options',body
',name

Live definitions ---------------------------------------------------------

defgenericshader-specification-for
rolestage
:documentation

Return the current durable shader specification for role and stage.

defmacrodefine-shader-method
generic-functionnamespecialized-lambda-listoptions&bodybody

Define a shader-producing method with ordinary DEFMETHOD identity.

Calling the method reparses its small source form so changes to source-level abstractions participate in live rebuilding. Method replacement remains the role/stage identity watched by the MOP; abstraction revisions are tracked separately by live artifacts.

`
defmethod,generic-function,specialized-lambda-list
parse-shader-specification',name',options',body
defclassshader-definition-dependent
generic-function:initarg:generic-function:readershader-definition-dependent-generic-function
arguments:initarg:arguments:readershader-definition-dependent-arguments
lock:initform
sb-thread:make-mutex:name"luv shader definition dependent"
:readershader-definition-dependent-lock
revision:initform0:accessorshader-definition-dependent-revision
attempted-revision:initform0:accessorshader-definition-dependent-attempted-revision
last-event:initformnil:accessorshader-definition-dependent-last-event
subscribed-p:initformnil:accessorshader-definition-dependent-subscribed-p
:documentation

A narrow MOP subscription for one generic-function argument tuple.

update-dependent only records a monotonically increasing revision. Consumers perform compilation, GPU work, and calls back into the generic function after the method mutation has completed and outside the generic function's lock.

defunshader-method-specializer-accepts-p
specializerargument
if
typepspecializer'closer-mop:eql-specializer
eqlargument
closer-mop:eql-specializer-objectspecializer
typepargumentspecializer
defunshader-method-accepts-arguments-p
methodarguments
let
specializers
closer-mop:method-specializersmethod
and
=
lengthspecializers
lengtharguments
every#'shader-method-specializer-accepts-pspecializersarguments
defmethodcloser-mop:update-dependent
generic-functionstandard-generic-function
&restevent
declare
ignoregeneric-function

SBCL/Closer-MOP may also announce generic-function reinitialization with no event arguments. ADD-METHOD and REMOVE-METHOD contain the affected method and are sufficient; replacement naturally coalesces to one pending revision before the next consumer turn.

when
and
=
lengthevent
2
member
firstevent
'
add-methodremove-method
shader-method-accepts-arguments-p
secondevent
shader-definition-dependent-argumentsdependent
sb-thread:with-mutex
shader-definition-dependent-lockdependent
incf
shader-definition-dependent-revisiondependent
setf
shader-definition-dependent-last-eventdependent
event
nil
defunmake-shader-definition-dependent
generic-functionarguments

Subscribe a revision source to generic-function changes for arguments.

check-typegeneric-functionstandard-generic-function
let
dependent
make-instance'shader-definition-dependent:generic-functiongeneric-function:arguments
copy-listarguments
closer-mop:add-dependentgeneric-functiondependent
setf
shader-definition-dependent-subscribed-pdependent
t
dependent
defunshader-definition-change-pending-p
dependent
sb-thread:with-mutex
shader-definition-dependent-lockdependent
>
shader-definition-dependent-revisiondependent
shader-definition-dependent-attempted-revisiondependent
defunshader-definition-change-snapshot
dependent

Return the current definition revision and its most recent MOP event.

sb-thread:with-mutex
shader-definition-dependent-lockdependent
values
shader-definition-dependent-revisiondependent
copy-list
shader-definition-dependent-last-eventdependent
defunacknowledge-shader-definition-change
dependentrevision

Record that the consumer finished attempting revision.

A newer concurrent notification remains pending.

sb-thread:with-mutex
shader-definition-dependent-lockdependent
setf
shader-definition-dependent-attempted-revisiondependent
max
shader-definition-dependent-attempted-revisiondependent
minrevision
shader-definition-dependent-revisiondependent
dependent
defunrelease-shader-definition-dependent
dependent

Remove dependent from its generic function. This operation is idempotent.

when
shader-definition-dependent-subscribed-pdependent
closer-mop:remove-dependent
shader-definition-dependent-generic-functiondependent
dependent
setf
shader-definition-dependent-subscribed-pdependent
nil
nil

Lowering protocols -------------------------------------------------------

defgenericlower-shader-specification
targetspecification
:documentation

Lower specification for target without changing its source graph.

target participates in ordinary CLOS dispatch so each backend can own its structured product and source provenance. #JDLQPN

defgenericlower-shader-call
operatorcontextexpression
:argument-precedence-ordercontextoperatorexpression
:documentation

Lower expression into context's target product and return its value.

Target context deliberately precedes operator identity in method selection: an operator implemented only for one backend must not capture another backend's context before its source-located unsupported-operation method.

defmethodlower-shader-call
operatorcontextexpression
declare
ignorecontext
error'shader-language-error:form:reason:unknown-operator:detailsoperator