luv

Workshop wiki

lowering.lisp

hal/metal/msl/lowering.lisp

system luv/msl · 174 definitions · on GitHub

Direct Metal Shading Language lowering for luv's mathematical shaders.

The source shader graph stays unchanged. This sibling compiler produces a small structured document and records every rendered expression occurrence, rather than routing Metal through SPIR-V or accumulating one opaque string.

in-package#:luv.msl
defclassmsl-target
language-version:initarg:language-version:initform"4.0":readermsl-target-language-version
:documentation

The Metal language policy selected for one direct shader lowering.

defparameter*metal-4-target*
make-instance'msl-target:language-version"4.0"
defclassmsl-source-occurrence
expression:initarg:expression:readermsl-source-occurrence-expression
text:initarg:text:readermsl-source-occurrence-text
:documentation

One rendered occurrence retaining its originating shader expression.

defclassmsl-field
type:initarg:type:readermsl-field-type
name:initarg:name:readermsl-field-name
attribute:initarg:attribute:readermsl-field-attribute
origin:initarg:origin:readermsl-field-origin
array-length:initarg:array-length:initformnil:readermsl-field-array-length
:documentation

One rendered structure field retaining its shader declaration for #YA4KDP.

defclassmsl-structure-declaration
name:initarg:name:readermsl-structure-name
fields:initarg:fields:readermsl-structure-fields
defclassmsl-parameter
type:initarg:type:readermsl-parameter-type
name:initarg:name:readermsl-parameter-name
attribute:initarg:attribute:readermsl-parameter-attribute
origin:initarg:origin:initformnil:readermsl-parameter-origin
:documentation

One entry-point parameter and the resource, if any, which produced it.

defclassmsl-variable-statement
type:initarg:type:readermsl-variable-statement-type
name:initarg:name:readermsl-variable-statement-name
value:initarg:value:readermsl-variable-statement-value
origin:initarg:origin:readermsl-variable-statement-origin
:documentation

One local declaration retaining its semantic shader binding.

defclassmsl-output-statement
field:initarg:field:readermsl-output-statement-field
value:initarg:value:readermsl-output-statement-value
origin:initarg:origin:readermsl-output-statement-origin
:documentation

One output assignment retaining its semantic shader assignment.

defclassmsl-if-statement
condition:initarg:condition:readermsl-if-statement-condition
statements:initarg:statements:readermsl-if-statement-statements
origin:initarg:origin:readermsl-if-statement-origin
defclassmsl-mesh-output-counts-statement
lane:initarg:lane:readermsl-mesh-output-counts-lane
vertex-count:initarg:vertex-count:readermsl-mesh-output-counts-vertex-count
primitive-count:initarg:primitive-count:readermsl-mesh-output-counts-primitive-count
origin:initarg:origin:readermsl-mesh-output-counts-origin
defclassmsl-mesh-vertex-statement
index:initarg:index:readermsl-mesh-vertex-index
vertex-type:initarg:vertex-type:readermsl-mesh-vertex-type
values:initarg:values:readermsl-mesh-vertex-values
origin:initarg:origin:readermsl-mesh-vertex-origin
defclassmsl-mesh-primitive-statement
index:initarg:index:readermsl-mesh-primitive-index
indices:initarg:indices:readermsl-mesh-primitive-indices
topology:initarg:topology:readermsl-mesh-primitive-topology
primitive-type:initarg:primitive-type:initformnil:readermsl-mesh-primitive-type
values:initarg:values:initformnil:readermsl-mesh-primitive-values
origin:initarg:origin:readermsl-mesh-primitive-origin
defclassmsl-task-payload-store-statement
field:initarg:field:readermsl-task-payload-store-field
index:initarg:index:initformnil:readermsl-task-payload-store-index
value:initarg:value:readermsl-task-payload-store-value
origin:initarg:origin:readermsl-task-payload-store-origin
defclassmsl-emit-mesh-workgroups-statement
lane:initarg:lane:readermsl-emit-mesh-workgroups-lane
workgroups:initarg:workgroups:readermsl-emit-mesh-workgroups-counts
origin:initarg:origin:readermsl-emit-mesh-workgroups-origin
defclassmsl-counted-fold-statement
type:initarg:type:readermsl-counted-fold-statement-type
state-name:initarg:state-name:readermsl-counted-fold-statement-state-name
initial:initarg:initial:readermsl-counted-fold-statement-initial
index-name:initarg:index-name:readermsl-counted-fold-statement-index-name
index-type:initarg:index-type:readermsl-counted-fold-statement-index-type
count:initarg:count:readermsl-counted-fold-statement-count
bindings:initarg:bindings:initformnil:readermsl-counted-fold-statement-bindings
update:initarg:update:readermsl-counted-fold-statement-update
until-bindings:initarg:until-bindings:initformnil:readermsl-counted-fold-statement-until-bindings
until:initarg:until:initformnil:readermsl-counted-fold-statement-until
origin:initarg:origin:readermsl-counted-fold-statement-origin
defclassmsl-entry-point
stage:initarg:stage:readermsl-entry-point-stage
return-type:initarg:return-type:readermsl-entry-point-return-type
name:initarg:name:readermsl-entry-point-name
parameters:initarg:parameters:readermsl-entry-point-parameters
statements:initarg:statements:readermsl-entry-point-statements
defclassmsl-document
target:initarg:target:readermsl-document-target
specification:initarg:specification:readermsl-document-specification
declarations:initarg:declarations:readermsl-document-declarations
entry-point:initarg:entry-point:readermsl-document-entry-point
source:initarg:source:accessormsl-document-source
expression-occurrences:initarg:expression-occurrences:readermsl-document-expression-occurrences
occurrence-expression:initarg:occurrence-expression:readermsl-document-occurrence-expression
defclassmsl-lowering-context
target:initarg:target:readermsl-context-target
specification:initarg:specification:readermsl-context-specification
references:initform
make-hash-table:test#'eq
:readermsl-context-references
expression-occurrences:initform
make-hash-table:test#'eq
:readermsl-context-expression-occurrences
occurrence-expression:initform
make-hash-table:test#'eq
:readermsl-context-occurrence-expression
function-call-results:initform
make-hash-table:test#'eq
:readermsl-context-function-call-results
pending-statements:initformnil:accessormsl-context-pending-statements
fold-counter:initform0:accessormsl-context-fold-counter
defundrain-msl-pending-statements
prog1
msl-context-pending-statementscontext
setf
msl-context-pending-statementscontext
nil
defunmsl-identifier
name
let
text
string-downcase
stringname
with-output-to-string
stream
loopforcharacteracrosstextforfirstp=tthennilforemitted=
if
or
alphanumericpcharacter
char=character#\_
character#\_
do
when
andfirstp
digit-char-pemitted
write-char#\_stream
write-charemittedstream
defunmsl-type-name
type&optionalsource-form
case
shader:shader-type-name
:bool"bool"
:float"float"
:uint"uint"
:uint64"ulong"
:vec2"float2"
:vec3"float3"
:vec4"float4"
:uvec2"uint2"
:uvec3"uint3"
:uvec4"uint4"
:texture-2d"texture2d<float>"
:depth-texture-2d"depth2d<float>"
:uint-texture-2d"texture2d<uint>"
:sampler"sampler"
otherwise
error'shader:shader-language-error:formsource-form:reason:unsupported-msl-type:details
shader:shader-type-nametype
defunmsl-structure-name-for
name&optionalsuffix
let
capitalize-next-pt
with-output-to-string
stream
loopforcharacteracross
string-downcase
stringname
if
alphanumericpcharacter
do
write-char
ifcapitalize-next-p
char-upcasecharacter
character
stream
setfcapitalize-next-pnil
elsedo
setfcapitalize-next-pt
whensuffix
write-stringsuffixstream
defunmsl-float-literal
value
let*
raw
string-downcase
write-to-string
coercevalue'single-float
normalized
map'string
lambda
character
if
findcharacter"sfdl":test#'char=
#\echaracter
raw
formatnil"~A~Af"normalized
if
or
find#\.normalized
find#\enormalized
""".0"
defunmsl-semantic-words
name
substitute#\Space#\-
string-downcase
symbol-namename
defunmsl-factor-description
factor
let
name
power
cdrfactor
casepower
1name
2
formatnil"~A squared"name
3
formatnil"~A cubed"name
otherwise
formatnil"~A to the ~A power"namepower
defunmsl-factor-product-description
factors
formatnil"~{~A~^ times ~}"
mapcar#'msl-factor-descriptionfactors
defunmsl-tensor-description
order
caseorder
0"scalar"
1"vector"
otherwise
formatnil"tensor of order ~D"order
defunmsl-character-description
specification
case
math:quantity-specification-characterspecification
:point"point-valued"
:absolute
if"non-negative absolute""absolute"
:difference"difference-valued"
defunmsl-quantity-predicate
specification
let*
kind
math:quantity-specification-kindspecification
unit-factors
math:unit-expression-factors
math:quantity-specification-unitspecification
dimension-factors
math:dimension-factors
math:quantity-specification-dimensionspecification
with-output-to-string
stream
formatstream"a ~A ~A"
msl-tensor-description
math:quantity-specification-tensor-orderspecification
whenkind
formatstream" in the ~A kind"
cond
and
nullunit-factors
write-string", unitless and dimensionless"stream
t
ifunit-factors
formatstream", measured in ~A units"
write-string", unitless"stream
ifdimension-factors
formatstream", with ~A dimension"
write-string", and dimensionless"stream
defunmsl-capitalize-sentence
text
if
plusp
lengthtext
concatenate'string
string
char-upcase
chartext0
subseqtext1
text
defunmsl-quantity-sentence
specification
let
name
math:quantity-specification-namespecification
formatnil"~A is ~A."
defunmsl-lane-name
positions
coerce
mapcar
lambda
char"xyzw"position
positions
'string
defunmsl-layout-sentences
layout&keysampled-p
let
occupiednil
sentencesnil
dolist
projection
math:quantity-layout-projectionslayout
let*
positions
math:quantity-projection-positionsprojection
specification
math:quantity-projection-specificationprojection
name
math:quantity-specification-namespecification
lanes
msl-lane-namepositions
setfoccupied
nconc
copy-listpositions
occupied
push
formatnil"The ~A~A ~A ~A ~A~A."
ifsampled-p"sampled """
lanes
if
=
lengthpositions
1
"lane""lanes"
if
=
lengthpositions
1
"holds""hold"
ifname"an unnamed quantity"
formatnil" as ~A"
sentences
let
uncovered
loopforpositionbelow
math:quantity-layout-extentlayout
unless
memberpositionoccupied
collectposition
whenuncovered
push
formatnil"The ~A~A ~A ~A no quantity annotation."
ifsampled-p"sampled """
msl-lane-nameuncovered
if
=
lengthuncovered
1
"lane""lanes"
if
=
lengthuncovered
1
"has""have"
sentences
nreversesentences
defgenericmsl-origin-quantity-specification
origin
:documentation

Return the homogeneous quantity carried by origin.

defmethodmsl-origin-quantity-specification
shader:shader-declaration-quantity-specificationorigin
defmethodmsl-origin-quantity-specification
shader:shader-resource-sample-quantity-specificationorigin
defgenericmsl-origin-quantity-layout
origin
:documentation

Return the component quantity layout carried by origin.

defmethodmsl-origin-quantity-layout
origint
nil
defmethodmsl-origin-quantity-layout
shader:shader-declaration-quantity-layoutorigin
defmethodmsl-origin-quantity-layout
shader:shader-resource-sample-quantity-layoutorigin
defunmsl-semantic-sentences
origin&keysampled-punannotated-p
let
cond
specification
list
unannotated-p
list"This numeric value has no quantity annotation."
defunwrite-msl-semantic-comments
originstreamindentation&keysampled-punannotated-p
dolist
sentence
msl-semantic-sentencesorigin:sampled-psampled-p:unannotated-punannotated-p
formatstream"~A// ~A~%"indentationsentence
defunnote-msl-occurrence
contextexpressiontext
let
occurrence
make-instance'msl-source-occurrence:expressionexpression:texttext
pushoccurrence
gethashexpression
msl-context-expression-occurrencescontext
setf
gethashoccurrence
msl-context-occurrence-expressioncontext
expression
occurrence
defunmsl-occurrence-text
occurrence
msl-source-occurrence-textoccurrence
defgenericlower-msl-expression
contextexpression
:documentation

Render one shader expression and retain a source occurrence for it.

defmethodlower-msl-expression
let
index
lower-msl-expressioncontext
shader:shader-payload-element-indexexpression
note-msl-occurrencecontextexpression
formatnil"payload.~A[~A]"
msl-identifier
shader:shader-object-name
shader:shader-payload-element-fieldexpression
defmethodlower-msl-expression
let
index
lower-msl-expressioncontext
shader:shader-buffer-element-indexexpression
note-msl-occurrencecontextexpression
formatnil"~A[~A]"
msl-identifier
shader:shader-object-name
shader:shader-buffer-element-bufferexpression
defmethodlower-msl-expression
multiple-value-bind
cached-resultcached-p
gethashexpression
msl-context-function-call-resultscontext
ifcached-p
note-msl-occurrencecontextexpressioncached-result
let
local-statementsnil
saved-referencesnil
unwind-protect
progn
dolist
unless
or
nth-value1
gethashbinding
msl-context-referencescontext
multiple-value-bind
old-referenceold-reference-p
gethashbinding
msl-context-referencescontext
push
listbindingold-referenceold-reference-p
saved-references
let*
setflocal-statements
gethashbinding
msl-context-referencescontext
name
setflocal-statements
nconclocal-statements
list
make-instance'msl-variable-statement:type
msl-type-name
shader:shader-expression-typebinding-expression
:namename:valuevalue:originbinding
let*
setflocal-statements
msl-context-pending-statementscontext
nconcouter-statementslocal-statements
gethashexpression
msl-context-function-call-resultscontext
result-text
note-msl-occurrencecontextexpressionresult-text
dolist
savedsaved-references
destructuring-bind
bindingold-referenceold-reference-p
saved
ifold-reference-p
setf
gethashbinding
msl-context-referencescontext
old-reference
remhashbinding
msl-context-referencescontext
defmethodlower-msl-expression
let
condition
lower-msl-expressioncontext
lang:arithmetic-conditional-conditionexpression
consequent
lower-msl-expressioncontext
lang:arithmetic-conditional-consequentexpression
alternative
lower-msl-expressioncontext
lang:arithmetic-conditional-alternativeexpression
note-msl-occurrencecontextexpression
formatnil"(~A ? ~A : ~A)"
defmethodlower-msl-expression
let*
ordinal
incf
msl-context-fold-countercontext
state-name
formatnil"fold_state_~D"ordinal
index-name
formatnil"fold_index_~D"ordinal
count
lower-msl-expressioncontext
lang:arithmetic-counted-fold-countexpression
initial
lower-msl-expressioncontext
lang:arithmetic-counted-fold-initialexpression
index-binding
lang:arithmetic-counted-fold-index-bindingexpression
state-binding
lang:arithmetic-counted-fold-state-bindingexpression
multiple-value-bind
old-indexold-index-p
gethashindex-binding
msl-context-referencescontext
multiple-value-bind
old-stateold-state-p
gethashstate-binding
msl-context-referencescontext
setf
gethashindex-binding
msl-context-referencescontext
index-name
gethashstate-binding
msl-context-referencescontext
state-name
let*
until-expression
lang:arithmetic-counted-fold-untilexpression
until
anduntil-expression
local-statementsnil
dolist
binding
lang:arithmetic-counted-fold-bindingsexpression
let*
setflocal-statements
setf
gethashbinding
msl-context-referencescontext
name
setflocal-statements
nconclocal-statements
list
make-instance'msl-variable-statement:type
msl-type-name
shader:shader-expression-typebinding-expression
:namename:valuevalue:originbinding
let
update
lower-msl-expressioncontext
lang:arithmetic-counted-fold-updateexpression
setflocal-statements
setf
msl-context-pending-statementscontext
nconcpreheader-statements
list
make-instance'msl-counted-fold-statement:type
msl-type-name
shader:shader-expression-typeexpression
:state-namestate-name:initialinitial:index-nameindex-name:index-type
msl-type-name
shader:shader-expression-type
lang:arithmetic-counted-fold-countexpression
:countcount:bindingslocal-statements:updateupdate:until-bindingsuntil-statements:untiluntil:originexpression
dolist
binding
lang:arithmetic-counted-fold-bindingsexpression
remhashbinding
msl-context-referencescontext
ifold-index-p
setf
gethashindex-binding
msl-context-referencescontext
old-index
remhashindex-binding
msl-context-referencescontext
ifold-state-p
setf
gethashstate-binding
msl-context-referencescontext
old-state
remhashstate-binding
msl-context-referencescontext
note-msl-occurrencecontextexpressionstate-name
defgenericlower-msl-shader-map-application
:documentation

Render one semantic shader-map application for MSL.

defmethodlower-msl-shader-map-application
declare
let*
point
msl-occurrence-text
lower-msl-expressioncontext
shader:shader-map-application-pointapplication
rows
mapcar
shader:shader-map-application-rowsapplication
homogeneous
formatnil"float4(~A, 1.0f)"point
clip-components
mapcar
lambda
row
formatnil"dot(~A, ~A)"rowhomogeneous
rows
note-msl-occurrencecontextapplication
formatnil"float4(~{~A~^, ~})"clip-components
defmethodlower-msl-expression
let*
application
shader:shader-map-projection-applicationexpression
definition
shader:shader-map-application-definitionapplication
point
msl-occurrence-text
lower-msl-expressioncontext
shader:shader-map-application-pointapplication
rows
mapcar
shader:shader-map-application-rowsapplication
homogeneous
formatnil"float4(~A, 1.0f)"point
clip-components
mapcar
lambda
row
formatnil"dot(~A, ~A)"rowhomogeneous
rows
normalized
formatnil"(float3(~{~A~^, ~}) / ~A)"
subseqclip-components03
fourthclip-components
scale
formatnil"float3(~{~A~^, ~})"
mapcar#'msl-float-literal
shader:shader-projective-map-coordinate-scaledefinition
offset
formatnil"float3(~{~A~^, ~})"
mapcar#'msl-float-literal
shader:shader-projective-map-coordinate-offsetdefinition
note-msl-occurrencecontextexpression
formatnil"((~A * ~A) + ~A)"normalizedscaleoffset
defmethodlower-msl-expression
lower-msl-shader-map-application
shader:shader-map-application-definitionexpression
contextexpression
defmethodlower-msl-expression
declare
ignorecontext
error'shader:shader-language-error:form:reason:unsupported-msl-expression:details
class-name
class-ofexpression
defunlower-msl-infix-call
contextexpressionoperator
let
note-msl-occurrencecontextexpression
cond
and
string=operator"-"
=
lengthoperands
1
formatnil"(-~A)"
firstoperands
=
lengthoperands
1
formatnil"(~A)"
firstoperands
t
reduce
lambda
leftright
formatnil"(~A ~A ~A)"leftoperatorright
restoperands
:initial-value
firstoperands
defunlower-msl-function-call
contextexpressionname
let
note-msl-occurrencecontextexpression
formatnil"~A(~{~A~^, ~})"nameoperands
defunlower-msl-chained-function-call
contextexpressionname
let
note-msl-occurrencecontextexpression
reduce
lambda
leftright
formatnil"~A(~A, ~A)"nameleftright
restoperands
:initial-value
firstoperands
defmethodshader:lower-shader-call
operatorexpression
error'shader:shader-language-error:form:reason:unsupported-msl-operator:detailsoperator
defmacrodefine-msl-infix-operator
operatortext
`
defmethodshader:lower-shader-call
operator
eql',operator
declare
ignoreoperator
defmethodshader:lower-shader-call

Lower ldb to a logical shift and mask in the operand's own width.

declare
ignoreoperator
let*
operands
size
shader:shader-bit-field-sizeexpression
position
shader:shader-bit-field-positionexpression
width
shader:shader-type-bit-width
shader:shader-expression-typeexpression
suffix
if"ul""u"
note-msl-occurrencecontextexpression
cond
formatnil"(~A)"value
formatnil"(~A >> ~A)"valueshift
t
formatnil"((~A >> ~A) & 0x~X~A)"valueshift
1-
ash1size
suffix
defmacrodefine-msl-function-operator
operatorname
`
defmethodshader:lower-shader-call
operator
eql',operator
declare
ignoreoperator
defmacrodefine-msl-chained-function-operator
operatorname
`
defmethodshader:lower-shader-call
operator
eql',operator
declare
ignoreoperator
defunlower-msl-vector-constructor
contextexpression
let
note-msl-occurrencecontextexpression
formatnil"~A(~{~A~^, ~})"
msl-type-name
shader:shader-expression-typeexpression
operands
defmethodshader:lower-shader-call
declare
ignoreoperator
let*
components
string-downcase
string
note-msl-occurrencecontextexpression
formatnil"~A.~A"components
defmethodshader:lower-shader-call
declare
ignoreoperator
destructuring-bind
texturesamplercoordinate
let*
lowered
mapcar
lambda
operand
listtexturesamplercoordinate
sample
formatnil"~A.sample(~A, ~A)"
text
if
shader:shader-type-image-depth-p
shader:shader-expression-typetexture
formatnil"float4(~A)"sample
sample
defmethodshader:lower-shader-call
declare
ignoreoperator
let
note-msl-occurrencecontextexpression
destructuring-bind
texturesamplercoordinatedepth-reference
operands
formatnil"~A.sample_compare(~A, ~A, ~A)"texturesamplercoordinatedepth-reference
defmethodshader:lower-shader-call
declare
ignoreoperator
destructuring-bind
texturecoordinate
note-msl-occurrencecontextexpression
formatnil"~A.read(~A)"texturecoordinate
defunmsl-interface-attribute
let
direction
shader:shader-interface-directiondeclaration
location
shader:shader-interface-locationdeclaration
built-in
shader:shader-interface-built-indeclaration
interpolation
shader:shader-interface-interpolationdeclaration
cond
and
eqdirection:output
eqbuilt-in:position
"[[position]]"
and
eqstage:vertex
eqdirection:input
eqbuilt-in:vertex-index
"[[vertex_id]]"
and
eqstage:vertex
eqdirection:input
eqbuilt-in:instance-index
"[[instance_id]]"
and
memberstage'
:task:mesh
eqdirection:input
casebuilt-in
:local-invocation-index"[[thread_index_in_threadgroup]]"
:local-invocation-id"[[thread_position_in_threadgroup]]"
:workgroup-id"[[threadgroup_position_in_grid]]"
:num-workgroups"[[threadgroups_per_grid]]"
:workgroup-size"[[threads_per_threadgroup]]"
otherwise
error'shader:shader-language-error:formsource-form:reason:unsupported-msl-built-in:details
listdirectionbuilt-in
built-in
error'shader:shader-language-error:formsource-form:reason:unsupported-msl-built-in:details
listdirectionbuilt-in
and
eqstage:vertex
eqdirection:input
formatnil"[[attribute(~D)]]"location
and
eqstage:fragment
eqdirection:output
formatnil"[[color(~D)]]"location
t
formatnil"[[user(locn~D)~@[, ~A~]]]"location
caseinterpolation
:flat"flat"
otherwisenil
defunmsl-uniform-structure
resource
make-instance'msl-structure-declaration:name:fields
mapcar
lambda
member
make-instance'msl-field:type
msl-type-name
shader:shader-declaration-typemember
:name:attributenil:originmember
shader:shader-uniform-block-membersresource
defunmsl-task-payload-structure
payload
make-instance'msl-structure-declaration:name:fields
mapcar
lambda
field
make-instance'msl-field:type
msl-type-name
shader:shader-declaration-typefield
:name:attributenil:originfield:array-length
shader:shader-task-payload-field-element-countfield
shader:shader-task-payload-fieldspayload
defunmsl-resource-parameter
resource
unless
zerop
shader:shader-resource-descriptor-setresource
error'shader:shader-language-error:form:reason:unsupported-msl-descriptor-set:details
shader:shader-resource-descriptor-setresource
let*
binding
shader:shader-resource-bindingresource
type
shader:shader-declaration-typeresource
kind
shader:shader-type-opaque-kindtype
casekind
:uniform-block
make-instance'msl-parameter:type:namename:attribute
formatnil"[[buffer(~D)]]"binding
:originresource
:storage-buffer
make-instance'msl-parameter:type
formatnil"const device ~A*"
msl-type-name
shader:shader-storage-buffer-element-typeresource
:namename:attribute
formatnil"[[buffer(~D)]]"binding
:originresource
:texture-2d
make-instance'msl-parameter:type:namename:attribute
formatnil"[[texture(~D)]]"binding
:originresource
:sampler
make-instance'msl-parameter:type"sampler":namename:attribute
formatnil"[[sampler(~D)]]"binding
:originresource
otherwise
error'shader:shader-language-error:form:reason:unsupported-msl-resource:detailskind
defunregister-msl-declaration-references
contextspecificationinput-parameter-name
dolist
input
shader:shader-specification-inputsspecification
setf
gethashinput
msl-context-referencescontext
if
shader:shader-interface-built-ininput
formatnil"~A.~A"input-parameter-name
dolist
resource
shader:shader-specification-resourcesspecification
let
setf
gethashresource
msl-context-referencescontext
resource-name
when
dolist
member
shader:shader-uniform-block-membersresource
setf
gethashmember
msl-context-referencescontext
formatnil"~A.~A"resource-name
let
payload
shader:shader-specification-task-payloadspecification
whenpayload
dolist
field
shader:shader-task-payload-fieldspayload
unless
shader:shader-task-payload-field-element-countfield
setf
gethashfield
msl-context-referencescontext
formatnil"payload.~A"
context
defmethodwrite-msl-declaration
formatstream"struct ~A {~%"
msl-structure-namedeclaration
dolist
field
msl-structure-fieldsdeclaration
write-msl-semantic-comments
msl-field-originfield
stream" ":unannotated-pt
formatstream" ~A ~A~A~@[ ~A~];~%"
msl-field-typefield
msl-field-namefield
if
msl-field-array-lengthfield
formatnil"[~D]"
msl-field-array-lengthfield
""
msl-field-attributefield
formatstream"};~%"
defgenericwrite-msl-statement
statementstream
defunwrite-msl-indent
stream&optional
extra0
looprepeatdo
write-string" "stream
defunmsl-position-adjusted-text
if
eq:position
shader:shader-interface-built-indeclaration

The shared camera graph intentionally retains Vulkan's framebuffer-oriented clip Y. Metal owns the target conversion.

formatnil"float4((~A).x, -(~A).y, (~A).z, (~A).w)"valuevaluevaluevalue
value
defunmsl-control-condition-text
condition
if
and
plusp
lengthcondition
char=#\(
charcondition0
char=#\)
charcondition
1-
lengthcondition
condition
formatnil"(~A)"condition
defmethodwrite-msl-statement
stream
write-msl-semantic-comments
msl-variable-statement-originstatement
stream"":unannotated-pt
formatstream"~A ~A = ~A;~%"
msl-variable-statement-typestatement
msl-variable-statement-namestatement
msl-occurrence-text
msl-variable-statement-valuestatement
defmethodwrite-msl-statement
stream
let*
origin
msl-output-statement-originstatement
output
shader:shader-assignment-outputorigin
value
msl-occurrence-text
msl-output-statement-valuestatement
formatstream"result.~A = ~A;~%"
msl-output-statement-fieldstatement
text
defmethodwrite-msl-statement
stream
formatstream"if ~A {~%"
msl-control-condition-text
msl-occurrence-text
msl-if-statement-conditionstatement
let
dolist
child
msl-if-statement-statementsstatement
formatstream"}~%"
defmethodwrite-msl-statement
formatstream"// publishes ~A vertices and ~A primitives~%"
msl-occurrence-text
msl-mesh-output-counts-vertex-countstatement
msl-occurrence-text
msl-mesh-output-counts-primitive-countstatement
formatstream"if (~A == 0u)~%"
msl-mesh-output-counts-lanestatement
formatstream"mesh_out.set_primitive_count(~A);~%"
msl-occurrence-text
msl-mesh-output-counts-primitive-countstatement
defmethodwrite-msl-statement
formatstream"mesh_out.set_vertex(~A, ~A{~{~A~^, ~}});~%"
msl-occurrence-text
msl-mesh-vertex-indexstatement
msl-mesh-vertex-typestatement
loopfor
declaration.occurrence
in
msl-mesh-vertex-valuesstatement
collect
defmethodwrite-msl-statement
let*
primitive-index
msl-occurrence-text
msl-mesh-primitive-indexstatement
indices
msl-occurrence-text
msl-mesh-primitive-indicesstatement
components
ecase
msl-mesh-primitive-topologystatement
:points'
nil
:lines'
"x""y"
:triangles'
"x""y""z"
width
lengthcomponents
loopforcomponentincomponentsforoffsetfrom0do
formatstream"mesh_out.set_index((~A * ~Du) + ~Du, ~A~A);~%"primitive-indexwidthoffsetindices
ifcomponent
formatnil".~A"component
""
when
msl-mesh-primitive-typestatement
formatstream"mesh_out.set_primitive(~A, ~A{~{~A~^, ~}});~%"primitive-index
msl-mesh-primitive-typestatement
mapcar
lambda
pair
msl-mesh-primitive-valuesstatement
defmethodwrite-msl-statement
formatstream"payload.~A~A = ~A;~%"
msl-task-payload-store-fieldstatement
if
msl-task-payload-store-indexstatement
formatnil"[~A]"
msl-occurrence-text
msl-task-payload-store-indexstatement
""
msl-occurrence-text
msl-task-payload-store-valuestatement
defmethodwrite-msl-statement
formatstream"if (~A == 0u)~%"
msl-emit-mesh-workgroups-lanestatement
formatstream"mesh_grid.set_threadgroups_per_grid(~A);~%"
msl-occurrence-text
msl-emit-mesh-workgroups-countsstatement
defmethodwrite-msl-statement
formatstream"~A ~A = ~A;~%"
msl-counted-fold-statement-typestatement
msl-counted-fold-statement-state-namestatement
msl-occurrence-text
msl-counted-fold-statement-initialstatement
let*
index-type
msl-counted-fold-statement-index-typestatement
unsigned-p
string=index-type"uint"
formatstream"for (~A ~A = ~A; ~A < ~A; ~A += ~A) {~%"index-type
msl-counted-fold-statement-index-namestatement
ifunsigned-p"0u""0.0f"
msl-counted-fold-statement-index-namestatement
msl-occurrence-text
msl-counted-fold-statement-countstatement
msl-counted-fold-statement-index-namestatement
ifunsigned-p"1u""1.0f"
let
until
msl-counted-fold-statement-untilstatement
whenuntil
let
dolist
binding
msl-counted-fold-statement-until-bindingsstatement
write-msl-statementbindingstream
formatstream"if ~A break;~%"
dolist
binding
msl-counted-fold-statement-bindingsstatement
formatstream"~A ~A = ~A;~%"
msl-variable-statement-typebinding
msl-variable-statement-namebinding
msl-occurrence-text
msl-variable-statement-valuebinding
formatstream"~A = ~A;~%"
msl-counted-fold-statement-state-namestatement
msl-occurrence-text
msl-counted-fold-statement-updatestatement
formatstream"}~%"
defunmsl-stage-qualifier
stage
ecasestage
:vertex"vertex"
:fragment"fragment"
:compute"kernel"
:task"[[object]]"
:mesh"[[mesh]]"
defunwrite-msl-entry-point
formatstream"~A ~A ~A("
msl-stage-qualifier
msl-entry-point-stageentry-point
msl-entry-point-return-typeentry-point
msl-entry-point-nameentry-point
loopforparameterin
msl-entry-point-parametersentry-point
forfirstp=tthennildo
unlessfirstp
formatstream",~%"
when
msl-parameter-originparameter
write-msl-semantic-comments
msl-parameter-originparameter
stream" ":sampled-pt
unlessfirstp
write-string" "stream
formatstream"~A ~A~@[ ~A~]"
msl-parameter-typeparameter
msl-parameter-nameparameter
msl-parameter-attributeparameter
let
void-p
string="void"
msl-entry-point-return-typeentry-point
formatstream") {~%"
unlessvoid-p
formatstream" ~A result = {};~%"
msl-entry-point-return-typeentry-point
let
dolist
statement
msl-entry-point-statementsentry-point
write-msl-statementstatementstream
unlessvoid-p
formatstream" return result;~%"
formatstream"}~%"
defunrender-msl-document
with-output-to-string
stream
formatstream"#include <metal_stdlib>~%~%using namespace metal;~%"
dolist
declaration
msl-document-declarationsdocument
terpristream
terpristream
write-msl-entry-point
msl-document-entry-pointdocument
stream
defunmsl-local-invocation-index-name
specification
msl-identifier
shader:shader-object-name
find:local-invocation-index
shader:shader-specification-inputsspecification
:key#'shader:shader-interface-built-in
defgenericlower-msl-statement
contextstatement
:documentation

Lower one semantic shader statement to structured MSL.

defmethodlower-msl-statement
multiple-value-bind
valuepending
lower-msl-expression-with-pendingcontext
shader:shader-assignment-valuestatement
appendpending
list
make-instance'msl-output-statement:field
msl-identifier
shader:shader-object-name
shader:shader-assignment-outputstatement
:valuevalue:originstatement
defmethodlower-msl-statement
multiple-value-bind
conditionpending
lower-msl-expression-with-pendingcontext
shader:shader-conditional-statement-conditionstatement
appendpending
list
make-instance'msl-if-statement:conditioncondition:statements
mapcan
shader:shader-conditional-statement-statementsstatement
:originstatement
defmethodlower-msl-statement
let
vertex-count
lower-msl-expressioncontext
shader:shader-mesh-output-vertex-countstatement
primitive-count
lower-msl-expressioncontext
shader:shader-mesh-output-primitive-countstatement
append
list
make-instance'msl-mesh-output-counts-statement:lane:vertex-countvertex-count:primitive-countprimitive-count:originstatement
defunlower-msl-declaration-values
contextvalues
let
pendingnil
lowerednil
dolist
pairvalues
let
push
cons
carpair
value
lowered
values
nreverselowered
pending
defmethodlower-msl-statement
let
index
lower-msl-expressioncontext
shader:shader-mesh-vertex-store-indexstatement
let
multiple-value-bind
valuesvalue-pending
lower-msl-declaration-valuescontext
shader:shader-mesh-vertex-store-valuesstatement
appendpendingvalue-pending
list
make-instance'msl-mesh-vertex-statement:indexindex:vertex-type:valuesvalues:originstatement
defmethodlower-msl-statement
let
index
lower-msl-expressioncontext
shader:shader-mesh-primitive-store-indexstatement
indices
lower-msl-expressioncontext
shader:shader-mesh-primitive-store-indicesstatement
let
multiple-value-bind
valuesvalue-pending
lower-msl-declaration-valuescontext
shader:shader-mesh-primitive-store-valuesstatement
let*
specification
msl-context-specificationcontext
mesh-output
shader:shader-specification-mesh-outputspecification
appendpendingvalue-pending
list
make-instance'msl-mesh-primitive-statement:indexindex:indicesindices:topology
shader:shader-mesh-output-topologymesh-output
:primitive-type:valuesvalues:originstatement
defmethodlower-msl-statement
let
index
and
shader:shader-task-payload-store-indexstatement
lower-msl-expressioncontext
shader:shader-task-payload-store-indexstatement
value
lower-msl-expressioncontext
shader:shader-task-payload-store-valuestatement
append
list
make-instance'msl-task-payload-store-statement:field
msl-identifier
shader:shader-object-name
shader:shader-task-payload-store-fieldstatement
:indexindex:valuevalue:originstatement
defmethodlower-msl-statement
multiple-value-bind
workgroupspending
lower-msl-expression-with-pendingcontext
shader:shader-emit-mesh-workgroups-countsstatement
appendpending
list
make-instance'msl-emit-mesh-workgroups-statement:lane:workgroupsworkgroups:originstatement
defunlower-msl-bindings
contextspecification
let
statementsnil
dolist
binding
shader:shader-specification-bindingsspecification
let*
setfstatements
setf
gethashbinding
msl-context-referencescontext
name
setfstatements
nconcstatements
list
make-instance'msl-variable-statement:type
msl-type-name
shader:shader-expression-typeexpression
:namename:valuevalue:originbinding
statements
defunlower-msl-statements
contextspecification
mapcan
lambda
statement
shader:shader-specification-statementsspecification
defunmsl-uniform-structures
specification
loopforresourcein
shader:shader-specification-resourcesspecification
whencollect
defunfinish-msl-document
maphash
lambda
expressionoccurrences
setf
gethashexpression
msl-context-expression-occurrencescontext
nreverseoccurrences
msl-context-expression-occurrencescontext
let
document
make-instance'msl-document:targettarget:specificationspecification:declarationsdeclarations:entry-pointentry-point:source"":expression-occurrences
msl-context-expression-occurrencescontext
:occurrence-expression
msl-context-occurrence-expressioncontext
document
defunlower-traditional-msl-specification
targetspecificationcontext
let*
stage
shader:shader-specification-stagespecification
base-name
ordinary-inputs
remove-if#'shader:shader-interface-built-in
shader:shader-specification-inputsspecification
built-in-inputs
remove-if-not#'shader:shader-interface-built-in
shader:shader-specification-inputsspecification
input-structure
whenordinary-inputs
msl-interface-structurebase-name"Input"stageordinary-inputs
output-structure
msl-interface-structurebase-name"Output"stage
shader:shader-specification-outputsspecification
input-parameter-name"stage_in"
unless
memberstage'
:vertex:fragment
error'shader:shader-language-error:form:reason:unsupported-msl-stage:detailsstage
register-msl-declaration-referencescontextspecificationinput-parameter-name
let
entry-point
make-instance'msl-entry-point:stagestage:return-type
msl-structure-nameoutput-structure
:name:parameters
append
wheninput-structure
list
make-instance'msl-parameter:type
msl-structure-nameinput-structure
:nameinput-parameter-name:attribute"[[stage_in]]"
mapcar
lambda
input
built-in-inputs
mapcar#'msl-resource-parameter
shader:shader-specification-resourcesspecification
:statements
finish-msl-documenttargetspecificationcontext
append
removenil
listinput-structureoutput-structure
entry-point
defunmsl-workgroup-parameters
stagespecification
mapcar
lambda
input
shader:shader-specification-inputsspecification
defunmsl-payload-parameter
stagepayload
whenpayload
make-instance'msl-parameter:type
formatnil"object_data ~A~A&"
if
eqstage:mesh
"const """
:name"payload":attribute"[[payload]]"
defunlower-task-msl-specification
targetspecificationcontext
let*
payload
shader:shader-specification-task-payloadspecification
payload-structure
finish-msl-documenttargetspecificationcontext
append
removenil
listpayload-structure
make-instance'msl-entry-point:stage:task:return-type"void":name:parameters
append
removenil
list
make-instance'msl-parameter:type"metal::mesh_grid_properties":name"mesh_grid":attributenil
msl-workgroup-parameters:taskspecification
mapcar#'msl-resource-parameter
shader:shader-specification-resourcesspecification
:statements
defunmsl-mesh-topology-name
topology
ecasetopology
:points"point"
:lines"line"
:triangles"triangle"
defunlower-mesh-msl-specification
targetspecificationcontext
let*
base-name
mesh-output
shader:shader-specification-mesh-outputspecification
vertex-structure
msl-interface-structurebase-name"Vertex":mesh
shader:shader-mesh-output-vertex-outputsmesh-output
primitive-outputs
shader:shader-mesh-output-primitive-outputsmesh-output
primitive-structure
andprimitive-outputs
msl-interface-structurebase-name"Primitive":meshprimitive-outputs
payload
shader:shader-specification-task-payloadspecification
payload-structure
mesh-type
formatnil"metal::mesh<~A, ~A, ~D, ~D, metal::topology::~A>"
msl-structure-namevertex-structure
ifprimitive-structure
msl-structure-nameprimitive-structure
"void"
shader:shader-mesh-output-max-verticesmesh-output
shader:shader-mesh-output-max-primitivesmesh-output
msl-mesh-topology-name
shader:shader-mesh-output-topologymesh-output
finish-msl-documenttargetspecificationcontext
append
removenil
listvertex-structureprimitive-structurepayload-structure
make-instance'msl-entry-point:stage:mesh:return-type"void":name:parameters
append
list
make-instance'msl-parameter:typemesh-type:name"mesh_out":attributenil
removenil
list
msl-workgroup-parameters:meshspecification
mapcar#'msl-resource-parameter
shader:shader-specification-resourcesspecification
:statements
defmethodshader:lower-shader-specification

Lower the shared shader graph directly to a structured MSL document.

let
context
make-instance'msl-lowering-context:targettarget:specificationspecification
case
shader:shader-specification-stagespecification
:vertex:fragment
:task
:mesh
otherwise
error'shader:shader-language-error:form:reason:unsupported-msl-stage:details
shader:shader-specification-stagespecification
defuncompile-msl
specification&optional
defunwrite-msl
documentpathname

Write document's deterministic source to pathname and return pathname.

with-open-file
streampathname:direction:output:if-exists:supersede:if-does-not-exist:create
write-string
msl-document-sourcedocument
stream
pathname