luv

Workshop wiki

lowering.lisp

hal/vulkan/spir-v/lowering.lisp

system luv/spir-v · 143 definitions · on GitHub

SPIR-V lowering for luv's typed shader graph.

The source language and its generic lowering protocols live in luv.SHADER; this sibling owns only the SPIR-V construction context and result product.

in-package#:luv.spir-v
defclassshader-lowering
specification:initarg:specification:readershader-lowering-specification
module:initarg:module:readershader-lowering-module
expression-instructions:initarg:expression-instructions:readershader-lowering-expression-instructions
instruction-expressions:initarg:instruction-expressions:readershader-lowering-instruction-expressions
diagnostics:initarg:diagnostics:initformnil:readershader-lowering-diagnostics
defclassshader-lowering-context
type-ids:initform
make-hash-table:test#'eq
:accessorcontext-type-ids
pointer-ids:initform
make-hash-table:test#'equal
:accessorcontext-pointer-ids
constant-ids:initform
make-hash-table:test#'equal
:accessorcontext-constant-ids
variable-ids:initform
make-hash-table:test#'eq
:accessorcontext-variable-ids
direct-values:initform
make-hash-table:test#'eq
:accessorcontext-direct-values
array-type-ids:initform
make-hash-table:test#'equal
:accessorcontext-array-type-ids
bool-vector-type-ids:initform
make-hash-table:test#'eql
:accessorcontext-bool-vector-type-ids
uniform-struct-ids:initform
make-hash-table:test#'eq
:accessorcontext-uniform-struct-ids
stage:initformnil:accessorcontext-stage
task-payload-variable:initformnil:accessorcontext-task-payload-variable
mesh-primitive-indices-variable:initformnil:accessorcontext-mesh-primitive-indices-variable
loaded-values:initform
make-hash-table:test#'eq
:accessorcontext-loaded-values
loaded-blocks:initform
make-hash-table:test#'eq
:accessorcontext-loaded-blocks
loaded-instructions:initform
make-hash-table:test#'eq
:accessorcontext-loaded-instructions
constant-instructions:initform
make-hash-table:test#'equal
:accessorcontext-constant-instructions
expression-values:initform
make-hash-table:test#'eq
:accessorcontext-expression-values
map-component-values:initform
make-hash-table:test#'eq
:accessorcontext-map-component-values
expression-instructions:initform
make-hash-table:test#'eq
:readercontext-expression-instructions
instruction-expressions:initform
make-hash-table:test#'eq
:readercontext-instruction-expressions
claimed-ids:initform
make-hash-table:test#'eq
:accessorcontext-claimed-ids
name-counts:initform
make-hash-table:test#'equal
:accessorcontext-name-counts
extended-instruction-imports:initformnil:accessorcontext-extended-instruction-imports
type-declarations:initformnil:accessorcontext-type-declarations
constant-declarations:initformnil:accessorcontext-constant-declarations
variable-declarations:initformnil:accessorcontext-variable-declarations
annotations:initformnil:accessorcontext-annotations
interfaces:initformnil:accessorcontext-interfaces
fold-values:initform
make-hash-table:test#'eq
:accessorcontext-fold-values
basic-blocks:initformnil:accessorcontext-basic-blocks
current-block:initformnil:accessorcontext-current-block
instructions:initformnil:accessorcontext-instructions
defunbegin-shader-basic-block
let
block
make-instance'spir-v-basic-block:labellabel
setf
context-basic-blockscontext
nconc
context-basic-blockscontext
listblock
context-current-blockcontext
block
block
defunshader-id-string
name
let
text
string-upcase
stringname
with-output-to-string
stream
write-char#\%stream
loopforcharacteracrosstextdo
write-char
if
or
alphanumericpcharacter
char=character#\-
character#\-
stream
defunshader-id
name
intern
find-package'#:luv.spir-v
defunreserve-shader-id
let
id
if
gethashid
context-claimed-idscontext
progn
setf
gethashid
context-claimed-idscontext
t
id
defunfresh-shader-id
let*
count
gethashbase
context-name-countscontext
0
loopfornext=
1+count
then
1+next
forcandidate-name=
if
=next1
base
formatnil"~A-~D"basenext
forcandidate=
interncandidate-name
find-package'#:luv.spir-v
unless
gethashcandidate
context-claimed-idscontext
do
setf
gethashbase
context-name-countscontext
next
gethashcandidate
context-claimed-idscontext
t
cl:returncandidate
defunappend-context-form
slotcontextform
setf
slot-valuecontextslot
nconc
slot-valuecontextslot
listform
form
defunensure-shader-type-id
let
or
gethashtype
context-type-idscontext
let*
kind
shader-type-opaque-kindtype
setf
gethashtype
context-type-idscontext
id
append-context-form'type-declarationscontext
cond
eqkind:texture-2d
listid'type-image
ensure-shader-type-idcontext
ecase
shader-type-scalar-kind
find-shader-type
shader-type-sample-result-typetype
:float:float
:uint:uint
'2d
if
shader-type-image-depth-ptype
10
001'unknown
eqkind:sampler
=
shader-type-component-counttype
1
ecase
shader-type-scalar-kindtype
:float
listid'type-float
shader-type-bit-widthtype
:uint
listid'type-int
shader-type-bit-widthtype
0
t
listid'type-vector
ensure-shader-type-idcontext
ecase
shader-type-scalar-kindtype
:float:float
:uint:uint
shader-type-component-counttype
id
defunensure-void-type-id
let
id
shader-id"VOID"
unless
gethashid
context-claimed-idscontext
append-context-form'type-declarationscontext
listid'type-void
id
defunensure-bool-type-id
let
or
gethashtype
context-type-idscontext
gethash:bool
context-type-idscontext
let
setf
gethash:bool
context-type-idscontext
id
gethashtype
context-type-idscontext
id
append-context-form'type-declarationscontext
listid'type-bool
id
defunensure-bool-vector-type-id
contextcount

The OpTypeVector of count booleans: a vector select's condition.

or
gethashcount
context-bool-vector-type-idscontext
let
id
reserve-shader-idcontext
formatnil"BVEC~D"count
setf
gethashcount
context-bool-vector-type-idscontext
id
id
defunensure-pointer-type-id
let*
key
liststorage-classvalue-id
or
gethashkey
context-pointer-idscontext
let
id
reserve-shader-idcontext
formatnil"~A-~A-POINTER"storage-class
shader-type-name
setf
gethashkey
context-pointer-idscontext
id
id
defunensure-pointer-to-type-id
let
key
liststorage-classvalue-id
or
gethashkey
context-pointer-idscontext
let
setf
gethashkey
context-pointer-idscontext
id
id
defunensure-array-type-id
contextelement-typeelement-count
let*
element-type
find-shader-typeelement-type
key
listelement-typeelement-count
or
gethashkey
context-array-type-idscontext
let*
element-id
length-id
reserve-shader-idcontext
formatnil"ARRAY-LENGTH-~D-~A"element-count
shader-type-nameelement-type
id
reserve-shader-idcontext
formatnil"~A-ARRAY-~D"
shader-type-nameelement-type
element-count
setf
gethashkey
context-array-type-idscontext
id

Array lengths are type operands, so keep their constants directly beside the derived type instead of in the later value-constant section.

append-context-form'type-declarationscontext
listlength-id'constantelement-count
append-context-form'type-declarationscontext
listid'type-arrayelement-idlength-id
id
defunensure-uniform-block-type-id
contextblock
or
gethashblock
context-uniform-struct-idscontext
let
setf
gethashblock
context-uniform-struct-idscontext
id
append-context-form'type-declarationscontext
list*id'type-struct
mapcar
lambda
member
ensure-shader-type-idcontext
shader-declaration-typemember
shader-uniform-block-membersblock
append-context-form'annotationscontext
list'decorateid'block
dolist
member
shader-uniform-block-membersblock
append-context-form'annotationscontext
list'member-decorateid
shader-uniform-member-indexmember
'offset
shader-uniform-member-offsetmember
id
defunensure-uniform-block-pointer-type-id
contextblock
let*
key
list'uniformstruct-id
or
gethashkey
context-pointer-idscontext
let
id
setf
gethashkey
context-pointer-idscontext
id
append-context-form'type-declarationscontext
listid'type-pointer'uniformstruct-id
id
defunensure-storage-buffer-type-id
contextbuffer

Return the id of buffer's block struct: one runtime array of elements.

or
gethashbuffer
context-uniform-struct-idscontext
let*
element-id
ensure-shader-type-idcontext
shader-storage-buffer-element-typebuffer
array-id
reserve-shader-idcontext
formatnil"~A-RUNTIME-ARRAY"name
id
reserve-shader-idcontext
formatnil"~A-BLOCK"name
setf
gethashbuffer
context-uniform-struct-idscontext
id
append-context-form'type-declarationscontext
listarray-id'type-runtime-arrayelement-id
append-context-form'type-declarationscontext
listid'type-structarray-id
append-context-form'annotationscontext
list'decorateid'block
append-context-form'annotationscontext
list'member-decorateid0'offset0
append-context-form'annotationscontext
list'member-decorateid0'non-writable
id
defunensure-storage-buffer-pointer-type-id
contextbuffer
let*
key
list'storage-bufferstruct-id
or
gethashkey
context-pointer-idscontext
let
id
setf
gethashkey
context-pointer-idscontext
id
append-context-form'type-declarationscontext
listid'type-pointer'storage-bufferstruct-id
id
defunshader-constant-name
value
formatnil"FLOAT-~A"value
defunensure-shader-constant
contextvalue&optionalexpression
let*
value
coercevalue'single-float
key
list:floatvalue
multiple-value-bind
idfound-p
gethashkey
context-constant-idscontext
iffound-p
progn
whenexpression
associate-shader-instructioncontextexpression
gethashkey
context-constant-instructionscontext
id
let*
setf
gethashkey
context-constant-idscontext
id
gethashkey
context-constant-instructionscontext
instruction
id
defunensure-shader-uint-constant
contextvalue

Return an internal unsigned constant used for structural addressing.

let
key
list:uintvalue
or
gethashkey
context-constant-idscontext
let
id
reserve-shader-idcontext
formatnil"UINT-~D"value
setf
gethashkey
context-constant-idscontext
id
append-context-form'constant-declarationscontext
listid'constanttype-idvalue
id
defunensure-sampled-image-type-id
contexttexture-type
let*
texture-type
find-shader-typetexture-type
key
list:sampled-imagetexture-type
table
context-pointer-idscontext
or
gethashkeytable
let
id
reserve-shader-idcontext
formatnil"~A-SAMPLED-IMAGE"
shader-type-nametexture-type
setf
gethashkeytable
id
id
defunensure-glsl-extended-import

Return the module's single GLSL.std.450 import id, requesting it once.

Modules whose expressions use no extended mathematics never acquire one.

let
import
first
context-extended-instruction-importscontext
ifimport
spir-v-extended-instruction-import-result-idimport
let
id
setf
context-extended-instruction-importscontext
list
make-instance'spir-v-extended-instruction-import:result-idid
id
defunregister-shader-variable
let*
setf
gethashdeclaration
context-variable-idscontext
variable-id
append-context-form'variable-declarationscontext
listvariable-id'variablepointer-iddirection
etypecasedeclaration
shader-interface-variable
append-context-form'annotationscontext
if
shader-interface-built-indeclaration
list'decoratevariable-id'built-in
list'enum'built-in
shader-interface-built-indeclaration
list'decoratevariable-id'location
shader-interface-locationdeclaration
when
shader-interface-interpolationdeclaration
append-context-form'annotationscontext
list'decoratevariable-id
shader-interface-interpolationdeclaration
setf
context-interfacescontext
nconc
context-interfacescontext
listvariable-id
shader-resource
append-context-form'annotationscontext
list'decoratevariable-id'descriptor-set
shader-resource-descriptor-setdeclaration
append-context-form'annotationscontext
list'decoratevariable-id'binding
shader-resource-bindingdeclaration

SPIR-V 1.4 modules list every global the entry point touches.

when
member
context-stagecontext
'
:task:mesh
setf
context-interfacescontext
nconc
context-interfacescontext
listvariable-id
variable-id
defunregister-workgroup-size-value
contextdeclarationworkgroup-size
let*
append-context-form'constant-declarationscontext
list*value-id'constant-compositetype-id
mapcarworkgroup-size
append-context-form'annotationscontext
list'decoratevalue-id'built-in'
enumbuilt-inworkgroup-size
setf
gethashdeclaration
context-direct-valuescontext
value-id
value-id
defunensure-task-payload-type-id
contextpayload
or
gethashpayload
context-uniform-struct-idscontext
let
id
reserve-shader-idcontext
formatnil"~A-PAYLOAD-TYPE"
setf
gethashpayload
context-uniform-struct-idscontext
id
append-context-form'type-declarationscontext
list*id'type-struct
mapcar
lambda
field
let
element-count
shader-task-payload-field-element-countfield
ifelement-count
ensure-array-type-idcontext
shader-declaration-typefield
element-count
ensure-shader-type-idcontext
shader-declaration-typefield
shader-task-payload-fieldspayload
id
defunregister-task-payload
contextpayload
let*
pointer-id
ensure-pointer-to-type-idcontext'task-payload-workgroup-exttype-id
formatnil"~A-PAYLOAD-POINTER"
variable-id
reserve-shader-idcontext
formatnil"~A-PAYLOAD"
append-context-form'variable-declarationscontext
listvariable-id'variablepointer-id'task-payload-workgroup-ext
setf
context-task-payload-variablecontext
variable-id
context-interfacescontext
nconc
context-interfacescontext
listvariable-id
variable-id
defunmesh-output-array-size
mesh-outputper-primitive-p
ifper-primitive-p
shader-mesh-output-max-primitivesmesh-output
shader-mesh-output-max-verticesmesh-output
defunregister-mesh-output-variable
contextdeclarationmesh-outputper-primitive-p
let*
element-type
shader-declaration-typedeclaration
array-type-id
ensure-array-type-idcontextelement-type
mesh-output-array-sizemesh-outputper-primitive-p
pointer-id
ensure-pointer-to-type-idcontext'outputarray-type-id
formatnil"~A-OUTPUT-ARRAY-POINTER"
setf
gethashdeclaration
context-variable-idscontext
variable-id
append-context-form'variable-declarationscontext
listvariable-id'variablepointer-id'output
append-context-form'annotationscontext
if
shader-interface-built-indeclaration
list'decoratevariable-id'built-in
list'enum'built-in
shader-interface-built-indeclaration
list'decoratevariable-id'location
shader-interface-locationdeclaration
when
shader-interface-interpolationdeclaration
append-context-form'annotationscontext
list'decoratevariable-id
shader-interface-interpolationdeclaration
whenper-primitive-p
append-context-form'annotationscontext
list'decoratevariable-id'per-primitive-ext
setf
context-interfacescontext
nconc
context-interfacescontext
listvariable-id
variable-id
defunregister-mesh-outputs
contextmesh-output
dolist
declaration
shader-mesh-output-vertex-outputsmesh-output
dolist
declaration
shader-mesh-output-primitive-outputsmesh-output
let*
topology
shader-mesh-output-topologymesh-output
index-type
array-type-id
ensure-array-type-idcontextindex-type
shader-mesh-output-max-primitivesmesh-output
pointer-id
ensure-pointer-to-type-idcontext'outputarray-type-id"PRIMITIVE-INDICES-POINTER"
variable-id
reserve-shader-idcontext"PRIMITIVE-INDICES"
append-context-form'variable-declarationscontext
listvariable-id'variablepointer-id'output
append-context-form'annotationscontext
list'decoratevariable-id'built-in
list'enum'built-in
ecasetopology
:points'primitive-point-indices-ext
:lines'primitive-line-indices-ext
:triangles'primitive-triangle-indices-ext
setf
context-mesh-primitive-indices-variablecontext
variable-id
context-interfacescontext
nconc
context-interfacescontext
listvariable-id
defunassociate-shader-instruction
let
forward
context-expression-instructionscontext
reverse
context-instruction-expressionscontext
unless
memberinstruction
gethashexpressionforward
:test#'eq
setf
gethashexpressionforward
nconc
gethashexpressionforward
unless
memberexpression
gethashinstructionreverse
:test#'eq
setf
gethashinstructionreverse
nconc
gethashinstructionreverse
listexpression
instruction
defunemit-shader-instruction
contextexpressionform
let
setf
context-instructionscontext
nconc
context-instructionscontext
let
block
context-current-blockcontext
unlessblock
error'shader-language-error:formform:reason:instruction-outside-basic-block
setf
spir-v-basic-block-instructionsblock
nconc
spir-v-basic-block-instructionsblock
instruction
defunalias-shader-expression
contextexpressionsource-expression
dolist
instruction
gethashsource-expression
context-expression-instructionscontext
defgenericshader-operator-result-name
operator
:documentation

The noun naming operator's SSA results in lowered provenance.

defmethodshader-operator-result-name
operatorsymbol
operator
defmethodshader-operator-result-name
operator
eql'+
'sum
defmethodshader-operator-result-name
operator
eql'-
'difference
defmethodshader-operator-result-name
operator
eql'*
'product
defmethodshader-operator-result-name
operator
eql'/
'quotient
defgenericshader-expression-provenance-name
expression
:documentation

The default noun naming expression's lowered results.

defmethodshader-expression-provenance-name
declare
ignoreexpression
'conditional
defmethodshader-expression-provenance-name
declare
ignoreexpression
'homogeneous-point
defmethodshader-expression-provenance-name
declare
ignoreexpression
'projected-sample
defmethodshader-expression-provenance-name
shader-object-name
shader-payload-element-fieldexpression
defmethodshader-expression-provenance-name
shader-object-name
shader-buffer-element-bufferexpression
defmethodshader-expression-provenance-name
declare
ignoreexpression
'interpretation
defmethodshader-expression-provenance-name
declare
ignoreexpression
'assumption
defunemit-value-instruction
contextexpressiontypeinstructionoperands

Types own their canonical names. Claim the result type before deriving a value name: a first-use constructor such as (vec3 0 0 0) otherwise lets both its type and its value independently choose %VEC3.

defunlower-shader-reference
contextexpression
let
target
multiple-value-bind
directdirect-p
gethashtarget
context-direct-valuescontext
ifdirect-pdirect
etypecasetarget
shader-binding
multiple-value-bind
fold-valuefold-value-p
gethashtarget
context-fold-valuescontext
iffold-value-pfold-value
shader-task-payload-field
let*
type
shader-declaration-typetarget
pointer
fresh-shader-idcontext
formatnil"~A-POINTER"
emit-shader-instructioncontextexpression
listpointer'access-chain
ensure-pointer-type-idcontext'task-payload-workgroup-exttype
context-task-payload-variablecontext
ensure-shader-uint-constantcontext
shader-task-payload-field-indextarget
value
shader-uniform-member
let*
block
shader-uniform-member-blocktarget
type
shader-declaration-typetarget
pointer
fresh-shader-idcontext
formatnil"~A-POINTER"
emit-shader-instructioncontextexpression
listpointer'access-chain
gethashblock
context-variable-idscontext
ensure-shader-uint-constantcontext
shader-uniform-member-indextarget
value
shader-variable-declaration
multiple-value-bind
valuefound-p
gethashtarget
context-loaded-valuescontext
if
andfound-p
eq
gethashtarget
context-loaded-blockscontext
context-current-blockcontext
progn
associate-shader-instructioncontextexpression
gethashtarget
context-loaded-instructionscontext
value
let*
type
shader-declaration-typetarget
value
emit-value-instructioncontextexpressiontype'load
list
gethashtarget
context-variable-idscontext
instruction
car
last
context-instructionscontext
setf
gethashtarget
context-loaded-valuescontext
value
gethashtarget
context-loaded-blockscontext
context-current-blockcontext
gethashtarget
context-loaded-instructionscontext
instruction
value
defgenericbinary-arithmetic-instruction
operatorleft-typeright-type
:documentation

The SPIR-V instruction computing one binary step of operator.

defmethodbinary-arithmetic-instruction
operator
eql'+
left-typeright-type
declare
ignoreright-type
ecase
shader-type-scalar-kindleft-type
:float'f-add
:uint'i-add
defmethodbinary-arithmetic-instruction
operator
eql'-
left-typeright-type
declare
ignoreright-type
ecase
shader-type-scalar-kindleft-type
:float'f-sub
:uint'i-sub
defmethodbinary-arithmetic-instruction
operator
eql'/
left-typeright-type
declare
ignoreright-type
ecase
shader-type-scalar-kindleft-type
:float'f-div
:uint'u-div
defmethodbinary-arithmetic-instruction
operator
eql'*
left-typeright-type
if'vector-times-scalar
ecase
shader-type-scalar-kindleft-type
:float'f-mul
:uint'i-mul
defunemit-binary-arithmetic
contextexpressionoperatorresult-typeleft-idleft-typeright-idright-type
let
instruction
binary-arithmetic-instructionoperatorleft-typeright-type
when
rotatefleft-idright-id
emit-value-instructioncontextexpressionresult-typeinstruction
listleft-idright-id
defunemit-extended-instruction
contextexpressiontypeinstruction-nameoperands

Emit one GLSL.std.450 operation, keyed by its enumerated instruction name.

defunlower-extended-call

Lower expression as one extended instruction over its lowered operands.

emit-extended-instructioncontextexpression
shader-expression-typeexpression
instruction-name
mapcar
lambda
operand
defunlower-chained-extended-call

Fold expression's operands left to right through a binary extended step.

let*
operands
dolist
operand
restoperands
value
setfvalue
emit-extended-instructioncontextexpression
shader-expression-typeexpression
instruction-name
defunlower-chained-arithmetic
contextexpression

Fold expression's operands left to right through its binary operator.

let*
operator
operands
first
firstoperands
value-type
shader-expression-typefirst
dolist
operand
restoperands
value
let
operand-value
operand-type
shader-expression-typeoperand
setfvalue
emit-binary-arithmeticcontextexpressionoperator
cond
value-type
operand-type
t
shader-expression-typeexpression
valuevalue-typeoperand-valueoperand-type
value-type
cond
value-type
operand-type
t
shader-expression-typeexpression
defmethodlower-shader-call
operator
eql'+
contextexpression
defmethodlower-shader-call
operator
eql'*
contextexpression
defmethodlower-shader-call
operator
eql'-
contextexpression
let
operands
if
=
lengthoperands
1
if
eq:float
shader-type-scalar-kind
find-shader-type
shader-expression-typeexpression
emit-value-instructioncontextexpression
shader-expression-typeexpression
'f-negate
error'shader-language-error:form:reason:unsigned-negation
defmethodlower-shader-call
operator
eql'mod
contextexpression
destructuring-bind
leftright
emit-value-instructioncontextexpression
shader-expression-typeexpression
'u-mod
defmethodlower-shader-call
operator
eql'ldb
contextexpression

Left-align the field, then right-align it: two logical shifts by 32-bit amounts extract any field of a 32- or 64-bit value without bit-field instructions, which Vulkan restricts to 32-bit operands, and without wide mask constants. A run-time position subtracts itself from the constant left shift.

let*
type
shader-expression-typeexpression
width
shader-type-bit-widthtype
size
shader-bit-field-sizeexpression
position
shader-bit-field-positionexpression
operands
aligned
ifleft-shift
emit-value-instructioncontextexpressiontype'shift-left-logical
listvalueleft-shift
value
if
=sizewidth
progn
alias-shader-expressioncontextexpression
firstoperands
aligned
defmethodlower-shader-call
operator
eql'/
contextexpression
let
operands
if
and
shader-vector-type-p
shader-expression-type
firstoperands
shader-float-type-p
shader-expression-type
secondoperands
let*
vector
firstoperands
scalar
secondoperands
float-type
reciprocal-id
emit-binary-arithmeticcontextexpression'*
shader-expression-typevector
vector-id
shader-expression-typevector
reciprocal-idfloat-type
defuncomparison-instruction
operatoroperand-type
ecase
shader-type-scalar-kindoperand-type
:float
ecaseoperator
<'f-ord-less-than
<='f-ord-less-than-equal
>'f-ord-greater-than
>='f-ord-greater-than-equal
='f-ord-equal
:uint
ecaseoperator
<'u-less-than
<='u-less-than-equal
>'u-greater-than
>='u-greater-than-equal
='i-equal
defmacrodefine-comparison-lowering
operator
`
defmethodlower-shader-call
operator
eql',operator
contextexpression
emit-value-instructioncontextexpression:bool
comparison-instructionoperator
shader-expression-type
first
mapcar
lambda
operand
defmethodlower-shader-call
operator
eql'mix
contextexpression
destructuring-bind
fromtoamount
let*
float-type
value-type
shader-expression-typeexpression
inverse
emit-binary-arithmeticcontextexpression'-float-typeone-idfloat-typeamount-idfloat-type

Emit the target contribution first to retain the arithmetic ordering of luvcraft's original pointful shader.

to-part
emit-binary-arithmeticcontextexpression'*value-typeto-idvalue-typeamount-idfloat-type
from-part
emit-binary-arithmeticcontextexpression'*value-typefrom-idvalue-typeinversefloat-type
emit-binary-arithmeticcontextexpression'+value-typeto-partvalue-typefrom-partvalue-type
defmethodlower-shader-call
operator
contextexpression
defgenericlower-shader-map-homogeneous-components
definitioncontextapplication&optionalorigin
:documentation

Lower application once and return its four homogeneous components.

defmethodlower-shader-map-homogeneous-components
contextapplication&optional
originapplication
or
gethashapplication
context-map-component-valuescontext
let*
point
shader-map-application-pointapplication
clip
mapcar
shader-map-application-rowsapplication
setf
gethashapplication
context-map-component-valuescontext
clip
defgenericlower-shader-map-sample-components
:documentation

Project one homogeneous application into represented sample components.

defmethodlower-shader-map-sample-components
or
gethashprojection
context-map-component-valuescontext
let*
application
shader-map-projection-applicationprojection
float-type
w
fourthclip
normalized
loopforcomponentin
subseqclip03
collect
emit-binary-arithmeticcontextprojection'/:floatcomponentfloat-typewfloat-type
result
loopforcomponentinnormalizedforscalein
shader-projective-map-coordinate-scaledefinition
foroffsetin
shader-projective-map-coordinate-offsetdefinition
collect
let
scaled
ifcomponent
emit-binary-arithmeticcontextprojection'*:floatcomponentfloat-typefloat-type
if
zeropoffset
scaled
emit-binary-arithmeticcontextprojection'+:floatscaledfloat-typefloat-type
setf
gethashprojection
context-map-component-valuescontext
result
defunlower-shader-map-projection
contextexpressionprojectionindices
let
components
lower-shader-map-sample-components
shader-map-application-definition
shader-map-projection-applicationprojection
contextprojection
alias-shader-expressioncontextexpressionprojection
if
=
lengthindices
1
nth
firstindices
components
emit-value-instructioncontextexpression
shader-expression-typeexpression
'composite-construct
mapcar
lambda
index
nthindexcomponents
indices
defmethodlower-shader-call
operator
contextexpression
let*
ifmap-projection
lower-shader-map-projectioncontextexpressionmap-projectionindices
let
if
=
lengthindices
1
emit-value-instructioncontextexpression
shader-expression-typeexpression
'composite-extract
listvalue
firstindices
emit-value-instructioncontextexpression
shader-expression-typeexpression
'vector-shuffle
list*valuevalueindices
defunlower-vector-constructor
contextexpression
emit-value-instructioncontextexpression
shader-expression-typeexpression
'composite-construct
mapcar
lambda
operand
defmethodlower-shader-call
operator
eql'vec2
contextexpression
defmethodlower-shader-call
operator
eql'vec3
contextexpression
defmethodlower-shader-call
operator
eql'vec4
contextexpression
defmethodlower-shader-call
operator
eql'uvec2
contextexpression
defmethodlower-shader-call
operator
eql'uvec3
contextexpression
defmethodlower-shader-call
operator
eql'uvec4
contextexpression
defmethodlower-shader-call
operator
eql'uint
contextexpression
let*
operand
first
type
shader-expression-typeoperand
cond
t
emit-value-instructioncontextexpression:uint'convert-f-to-u
listvalue
defmethodlower-shader-call
operator
eql'uint64
contextexpression
let*
operand
first
type
shader-expression-typeoperand
cond
t
emit-value-instructioncontextexpression:uint64'convert-f-to-u
listvalue
defmethodlower-shader-call
operator
eql'float
contextexpression
let*
operand
first
if
shader-float-type-p
shader-expression-typeoperand
prognvalue
emit-value-instructioncontextexpression:float'convert-u-to-f
listvalue
defmethodlower-shader-call
operator
eql'min
contextexpression
defmethodlower-shader-call
operator
eql'max
contextexpression
defmethodlower-shader-call
operator
eql'abs
contextexpression
defmethodlower-shader-call
operator
eql'signum
contextexpression
defmethodlower-shader-call
operator
eql'sqrt
contextexpression
macrolet
define-unary-extended-lowering
&restpairs
`
progn,@
mapcar
lambda
pair
destructuring-bind
operatorinstruction
pair
`
defmethodlower-shader-call
operator
eql',operator
contextexpression
pairs
define-unary-extended-lowering
defmethodlower-shader-call
operator
contextexpression
emit-value-instructioncontextexpression
shader-expression-typeexpression
'd-pdx
defmethodlower-shader-call
operator
contextexpression
emit-value-instructioncontextexpression
shader-expression-typeexpression
'd-pdy
defmethodlower-shader-call
operator
eql'expt
contextexpression
defmethodlower-shader-call
operator
eql'clamp
contextexpression
lower-extended-callcontextexpression'f-clamp
defmethodlower-shader-call
operator
contextexpression
lower-extended-callcontextexpression'smooth-step
defmethodlower-shader-call
operator
eql'step
contextexpression
defmethodlower-shader-call
operator
eql'sample
contextexpression
destructuring-bind
texturesamplercoordinate
let*
coordinate-id
texture-type
shader-expression-typetexture
emit-shader-instructioncontextexpression
listsampled-id'sampled-imagetexture-idsampler-id
emit-value-instructioncontextexpression
shader-expression-typeexpression
'image-sample-implicit-lod
listsampled-idcoordinate-id
defmethodlower-shader-call
operator
contextexpression
destructuring-bind
texturecoordinate
defmethodlower-shader-call
operator
contextexpression
destructuring-bind
texturesamplercoordinatedepth-reference
let*
coordinate-id
depth-reference-id
texture-type
shader-expression-typetexture
emit-shader-instructioncontextexpression
listsampled-id'sampled-imagetexture-idsampler-id
emit-value-instructioncontextexpression
shader-expression-typeexpression
'image-sample-dref-implicit-lod
listsampled-idcoordinate-iddepth-reference-id
defgenericlower-shader-expression-value
contextexpression
:documentation

Lower expression into instructions and return its value id.

defmethodlower-shader-expression-value
let*
field
shader-payload-element-fieldexpression
type
shader-declaration-typefield
pointer
fresh-shader-idcontext
formatnil"~A-ELEMENT-POINTER"
index
lower-shader-expressioncontext
shader-payload-element-indexexpression
emit-shader-instructioncontextexpression
listpointer'access-chain
ensure-pointer-type-idcontext'task-payload-workgroup-exttype
context-task-payload-variablecontext
ensure-shader-uint-constantcontext
shader-task-payload-field-indexfield
index
emit-value-instructioncontextexpressiontype'load
listpointer
defmethodlower-shader-expression-value
let*
buffer
shader-buffer-element-bufferexpression
type
shader-storage-buffer-element-typebuffer
pointer
fresh-shader-idcontext
formatnil"~A-ELEMENT-POINTER"
index
lower-shader-expressioncontext
shader-buffer-element-indexexpression
emit-value-instructioncontextexpressiontype'load
listpointer
defmethodlower-shader-expression-value
let*
type
shader-expression-typeexpression
count
shader-type-component-count
condition
lower-shader-expressioncontext
lang:arithmetic-conditional-conditionexpression
consequent
lower-shader-expressioncontext
lang:arithmetic-conditional-consequentexpression
alternative
lower-shader-expressioncontext
lang:arithmetic-conditional-alternativeexpression

OpSelect took one boolean per component until SPIR-V 1.4 relaxed it, and a stage's module version is not this expression's business, so a scalar condition choosing between vectors is splatted rather than leaned on: the wider form is valid at every version.

when
andcount
>count1
let
splat
fresh-shader-idcontext"CONDITION-VECTOR"
emit-shader-instructioncontextnil
list*splat'composite-construct
make-listcount:initial-elementcondition
setfconditionsplat
emit-value-instructioncontextexpressiontype'select
listconditionconsequentalternative
defmethodlower-shader-expression-value
let*
count-expression
lang:arithmetic-counted-fold-countexpression
count-type
shader-expression-typecount-expression
unsigned-p
preheader
spir-v-basic-block-label
context-current-blockcontext
count
initial
lower-shader-expressioncontext
lang:arithmetic-counted-fold-initialexpression
state-type
shader-expression-typeexpression
header-label
body-label
continue-label
merge-label
index-id
state-id
next-index-id
fresh-shader-idcontext'fold-next-index
emit-shader-instructioncontextexpression
list'branchheader-label
let

The index and state phis are prepended to the header once the back edge is known, so an :UNTIL test lowered here may already refer to them through the fold values.

setf
gethash
lang:arithmetic-counted-fold-index-bindingexpression
context-fold-valuescontext
index-id
gethash
lang:arithmetic-counted-fold-state-bindingexpression
context-fold-valuescontext
state-id
let
condition-id
fresh-shader-idcontext'fold-condition
until
lang:arithmetic-counted-fold-untilexpression
emit-shader-instructioncontextexpression
listcondition-id
ifunsigned-p'u-less-than'f-ord-less-than
index-idcount
whenuntil
let
continue-id
fresh-shader-idcontext'fold-continue-p
guarded-id
fresh-shader-idcontext'fold-guarded-condition
emit-shader-instructioncontextexpression
listcontinue-id'logical-notuntil-id
emit-shader-instructioncontextexpression
listguarded-id'logical-andcondition-idcontinue-id
setfcondition-idguarded-id
emit-shader-instructioncontextexpression
list'loop-mergemerge-labelcontinue-label'none
emit-shader-instructioncontextexpression
list'branch-conditionalcondition-idbody-labelmerge-label
let
next-state
lower-shader-expressioncontext
lang:arithmetic-counted-fold-updateexpression
emit-shader-instructioncontextexpression
list'branchcontinue-label
emit-shader-instructioncontextexpression
listnext-index-id
ifunsigned-p'i-add'f-add
index-idone
emit-shader-instructioncontextexpression
list'branchheader-label
let
index-phi
parse-instruction
listindex-id'phizeropreheadernext-index-idcontinue-label
state-phi
parse-instruction
liststate-id'phiinitialpreheadernext-statecontinue-label
setf
spir-v-basic-block-instructionsheader
list*index-phistate-phi
spir-v-basic-block-instructionsheader
context-instructionscontext
nconc
context-instructionscontext
listindex-phistate-phi
remhash
lang:arithmetic-counted-fold-index-bindingexpression
context-fold-valuescontext
remhash
lang:arithmetic-counted-fold-state-bindingexpression
context-fold-valuescontext
state-id
defmethodlower-shader-expression-value
emit-value-instructioncontextexpression
shader-expression-typeexpression
'composite-construct
lower-shader-map-homogeneous-components
shader-map-application-definitionexpression
contextexpression
defmethodlower-shader-expression-value
declare
ignorecontext
error'shader-language-error:form:reason:sampling-projection-requires-field-selection
defmethodlower-shader-expression-value
let*
if
=factor1
prognoperand-value
emit-binary-arithmeticcontextexpression'*
shader-expression-typeexpression
operand-value
shader-expression-typeoperand
defunlower-shader-expression
contextexpression
or
gethashexpression
context-expression-valuescontext
setf
gethashexpression
context-expression-valuescontext
defgenericlower-shader-statement
contextstatement
:documentation

Lower one semantic shader effect into SPIR-V control/data flow.

defmethodlower-shader-statement
let*
expression
shader-assignment-valuestatement
output-id
gethash
shader-assignment-outputstatement
context-variable-idscontext
emit-shader-instructioncontextexpression
list'storeoutput-idvalue
defmethodlower-shader-statement
let
condition
lower-shader-expressioncontext
shader-conditional-statement-conditionstatement
body-label
fresh-shader-idcontext'conditional-body
merge-label
fresh-shader-idcontext'conditional-merge
emit-shader-instructioncontext
shader-conditional-statement-conditionstatement
list'selection-mergemerge-label'none
emit-shader-instructioncontext
shader-conditional-statement-conditionstatement
list'branch-conditionalconditionbody-labelmerge-label
dolist
child
shader-conditional-statement-statementsstatement
defmethodlower-shader-statement
let
vertex-expression
shader-mesh-output-vertex-countstatement
emit-shader-instructioncontextvertex-expression
list'set-mesh-outputs-ext
lower-shader-expressioncontext
shader-mesh-output-primitive-countstatement
defmethodlower-shader-statement
let
index
lower-shader-expressioncontext
shader-mesh-vertex-store-indexstatement
dolist
pair
shader-mesh-vertex-store-valuesstatement
lower-shader-array-storecontext
carpair
index
cdrpair
'output
defmethodlower-shader-statement
let*
index-expression
shader-mesh-primitive-store-indexstatement
index
indices-expression
shader-mesh-primitive-store-indicesstatement
indices-pointer
fresh-shader-idcontext'primitive-indices-pointer
emit-shader-instructioncontextindices-expression
listindices-pointer'access-chain
ensure-pointer-type-idcontext'output
shader-expression-typeindices-expression
context-mesh-primitive-indices-variablecontext
index
emit-shader-instructioncontextindices-expression
list'storeindices-pointer
dolist
pair
shader-mesh-primitive-store-valuesstatement
lower-shader-array-storecontext
carpair
index
cdrpair
'output
defmethodlower-shader-statement
let*
field
shader-task-payload-store-fieldstatement
expression
shader-task-payload-store-valuestatement
pointer
indices
append
list
ensure-shader-uint-constantcontext
shader-task-payload-field-indexfield
when
shader-task-payload-store-indexstatement
list
lower-shader-expressioncontext
shader-task-payload-store-indexstatement
emit-shader-instructioncontextexpression
list*pointer'access-chain
ensure-pointer-type-idcontext'task-payload-workgroup-ext
shader-declaration-typefield
context-task-payload-variablecontext
indices
defmethodlower-shader-statement
let*
expression
shader-emit-mesh-workgroups-countsstatement
components
loopforcomponentbelow3collect
let
id
fresh-shader-idcontext'mesh-group-count
id
emit-shader-instructioncontextexpression
appendcomponents
when
context-task-payload-variablecontext
list
context-task-payload-variablecontext
defunshader-entry-execution-model
stage
ecasestage
:vertex'vertex
:fragment'fragment
:compute'gl-compute
:task'task-ext
:mesh'mesh-ext
defunmesh-topology-execution-mode
topology
ecasetopology
:points'output-points
:lines'output-lines-ext
:triangles'output-triangles-ext
defunshader-execution-modes
specificationmain-id
let
stage
shader-specification-stagespecification
casestage
:fragment
list
make-instance'spir-v-execution-mode:functionmain-id:name'origin-upper-left
:task:mesh
append
list
make-instance'spir-v-execution-mode:functionmain-id:name'local-size:literals
shader-specification-workgroup-sizespecification
when
eqstage:mesh
let
mesh-output
shader-specification-mesh-outputspecification
list
make-instance'spir-v-execution-mode:functionmain-id:name
mesh-topology-execution-mode
shader-mesh-output-topologymesh-output
make-instance'spir-v-execution-mode:functionmain-id:name'output-vertices:literals
list
shader-mesh-output-max-verticesmesh-output
make-instance'spir-v-execution-mode:functionmain-id:name'output-primitives-ext:literals
list
shader-mesh-output-max-primitivesmesh-output
defuncompile-shader-specification
specification

Lower specification and retain bidirectional expression/instruction links.

check-typespecificationshader-specification
let*
storage-buffers
remove-if-not
lambda
resource
typepresource'shader-storage-buffer
shader-specification-resourcesspecification
function-type-id
setf
context-stagecontext
shader-specification-stagespecification
append-context-form'type-declarationscontext
listfunction-type-id'type-functionvoid-id
dolist
declaration
shader-specification-inputsspecification
if
eq:workgroup-size
shader-interface-built-indeclaration
register-workgroup-size-valuecontextdeclaration
shader-specification-workgroup-sizespecification
dolist
declaration
append
shader-specification-outputsspecification
shader-specification-resourcesspecification
when
shader-specification-task-payloadspecification
register-task-payloadcontext
shader-specification-task-payloadspecification
when
shader-specification-mesh-outputspecification
register-mesh-outputscontext
shader-specification-mesh-outputspecification

LET* is part of the language contract, not merely pretty syntax. Emit binding computations in source order so the resulting basic block reads alongside the specification and retains ordinary Lisp evaluation order.

dolist
binding
shader-specification-bindingsspecification
dolist
statement
shader-specification-statementsspecification
unless
eq:task
shader-specification-stagespecification
let*
module
make-instance'spir-v-module:version
if
member
shader-specification-stagespecification
'
:task:mesh
#x00010400#x00010000
:capabilities
append'
shader
when
gethash
context-type-idscontext
'
int64
when
member
shader-specification-stagespecification
'
:task:mesh
'
mesh-shading-ext
:extensions
append
when
member
shader-specification-stagespecification
'
:task:mesh
'
"SPV_EXT_mesh_shader"

The StorageBuffer storage class is core from SPIR-V 1.3; the 1.0 modules of ordinary stages must ask for it.

when
andstorage-buffers
not
member
shader-specification-stagespecification
'
:task:mesh
'
"SPV_KHR_storage_buffer_storage_class"
:extended-instruction-imports
context-extended-instruction-importscontext
:entry-points
list
make-instance'spir-v-entry-point:execution-model
shader-entry-execution-model
shader-specification-stagespecification
:functionmain-id:interfaces
context-interfacescontext
:execution-modes
shader-execution-modesspecificationmain-id
:annotations
context-annotationscontext
:global-declarations
append
context-type-declarationscontext
context-constant-declarationscontext
context-variable-declarationscontext
:function-definitions
list
make-instance'spir-v-function-definition:result-idmain-id:return-typevoid-id:function-typefunction-type-id:basic-blocks
context-basic-blockscontext
lowering
make-instance'shader-lowering:specificationspecification:modulemodule:expression-instructions
context-expression-instructionscontext
:instruction-expressions
context-instruction-expressionscontext
lowering
defmethodlower-shader-specification
target
eql:spir-v
declare
ignoretarget
defunshader-module
specification
shader-lowering-module