luv

Workshop wiki

tests.lisp

hal/metal/msl/tests.lisp

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

in-package#:luvcraft.tests
shader:define-shadermsl-unsigned-texel-fold-probe
:stage:fragment:resources
band-data:uint-texture-2d:binding0
curve-data:texture-2d:binding1
:outputs
color:vec4:location0
let*
header
shader:texel-loadband-dataorigin
count
offset
seed
total
shader:counted-fold
indexcountsumseed
let*
address
+offsetindex
location
shader:uvec2
modaddress
/address
word
+sum
floatword
shader:set-outputcolor
shader:vec4totaltotaltotal1.0
shader:define-shadermsl-vertex-index-probe
:stage:vertex:inputs
vertex-index:uint:built-in:vertex-index
instance-index:uint:built-in:instance-index
:outputs
clip-position:vec4:built-in:position
let*
x
shader:float
mod
+vertex-indexinstance-index
shader:set-outputclip-position
shader:vec4x0.00.01.0
shader:define-shadermsl-nested-inline-call-probe
:stage:fragment:inputs
value:float:location0
:outputs
result:float:location0
shader:set-outputresult
shader:define-task-payloadmsl-task-mesh-payload
payload-site:uint64
payload-position
:array:vec432
shader:define-shadermsl-task-probe
:stage:task:workgroup-size
3211
:payloadmsl-task-mesh-payload:inputs
lane:uint:built-in:local-invocation-index
local-id:uvec3:built-in:local-invocation-id
group:uvec3:built-in:workgroup-id
group-count:uvec3:built-in:num-workgroups
threads:uvec3:built-in:workgroup-size
let*
three
position
if
shader:vec4-0.8-0.80.01.0
if
=laneone
shader:vec40.8-0.80.01.0
shader:vec40.00.80.01.0
when
shader:set-payloadpayload-site
shader:set-payload-elementpayload-positionlaneposition
shader:emit-mesh-workgroups
shader:define-shadermsl-mesh-probe
:stage:mesh:workgroup-size
3211
:payloadmsl-task-mesh-payload:inputs
lane:uint:built-in:local-invocation-index
group:uvec3:built-in:workgroup-id
:mesh-output
:topology:triangles:max-vertices32:max-primitives16:vertex
position:vec4:built-in:position
uv:vec2:location0
:primitive
primitive-color:vec4:location1
let*
vertex-count
shader:uintpayload-site
primitive-count
shader:set-mesh-output-countsvertex-countprimitive-count
when
<lanevertex-count
shader:set-mesh-vertexlane
position
shader:payload-elementpayload-positionlane
uv
when
shader:set-mesh-primitive
primitive-color
shader:vec41.01.01.01.0
shader:define-shadermsl-mesh-fragment-probe
:stage:fragment:outputs
color:vec4:location0
shader:set-outputcolor
shader:vec40.250.50.751.0
defunmsl-binding-named
namespecification
findname
shader:shader-specification-bindingsspecification
:key#'shader:shader-object-name:test
lambda
leftright
string-equal
symbol-nameleft
symbol-nameright
defunmsl-named
nameobjectsname-function
findnameobjects:keyname-function:test#'string=
deftestblock-fragment-lowers-directly-to-structured-msl
let*
source
msl:msl-document-sourcedocument
ok
eqspecification
msl:msl-document-specificationdocument
ok
=
length
msl:msl-document-declarationsdocument
3
ok
typep
msl:msl-document-entry-pointdocument
'msl:msl-entry-point
ok
search"fragment BlockWorldFragmentSpecificationOutput"source
ok
search"BlockWorldFragmentSpecificationInput stage_in [[stage_in]]"source
ok
search"texture2d<float> block_atlas [[texture(0)]]"source
ok
search"sampler block_sampler [[sampler(1)]]"source
ok
search"constant FrameState& frame_state [[buffer(2)]]"source
ok
search"tile_offset_input [[user(locn8), flat]]"source
ok
search"depth2d<float> shadow_map [[texture(3)]]"source
ok
search"shadow_map.sample_compare"source
ok
search"result.color_output = rgba;"source
deftestexact-unsigned-texel-fold-lowers-directly-to-metal
let
ok
search"texture2d<uint> band_data [[texture(0)]]"source
ok
search"band_data.read"source
ok
search"for (uint fold_index_1 = 0u;"source
ok
search"% uint(4096.0f)"source
ok
search"/ uint(4096.0f)"source
ok
search"float("source
deftestnested-inline-call-materializes-each-local-once
let*
source
declaration"float msl_reused_local_1_local_1_sum ="
ok
searchdeclarationsource
ok
null
searchdeclarationsource:start2
1+
searchdeclarationsource
deftestvertex-index-is-a-direct-metal-built-in-parameter
let
source
ok
search"uint vertex_index [[vertex_id]]"source
ok
search"uint instance_index [[instance_id]]"source
ok
search"(vertex_index + instance_index) % uint(2.0f)"source
ng
search"stage_in.vertex_index"source
ng
search"stage_in.instance_index"source
ng
search"[[stage_in]]"source
deftesttask-and-mesh-specifications-retain-their-workgroup-contracts
let*
payload
shader:shader-specification-task-payloadtask
mesh-output
shader:shader-specification-mesh-outputmesh
ok
equal'
3211
shader:shader-specification-workgroup-sizetask
ok
eqpayload
shader:shader-specification-task-payloadmesh
ok
=2
length
shader:shader-task-payload-fieldspayload
ok
=32
shader:shader-task-payload-field-element-count
second
shader:shader-task-payload-fieldspayload
ok
eq:triangles
shader:shader-mesh-output-topologymesh-output
ok
=32
shader:shader-mesh-output-max-verticesmesh-output
ok
=16
shader:shader-mesh-output-max-primitivesmesh-output
ok
typep
first
shader:shader-specification-statementsmesh
'shader:shader-mesh-output-counts
deftesttask-and-mesh-effects-enforce-stage-and-collective-legality
flet
failure-reason
nameoptionsbody
handler-case
prognnil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
ok
eq:mesh-output-counts-not-uniform
failure-reason'varying-mesh-counts'
:stage:mesh:workgroup-size
3211
:inputs
lane:uint:built-in:local-invocation-index
:mesh-output
:topology:triangles:max-vertices32:max-primitives16:vertex
position:vec4:built-in:position
'
let*
shader:set-mesh-output-countslaneone
shader:set-mesh-vertexlane
ok
eq:mesh-workgroups-emission-must-be-last
failure-reason'nonterminal-task-emission'
:stage:task:workgroup-size
111
:payloadmsl-task-mesh-payload:inputs
lane:uint:built-in:local-invocation-index
'
let*
shader:emit-mesh-workgroups
shader:set-payloadpayload-site
ok
eq:invalid-statement-for-stage
failure-reason'task-vertex-write'
:stage:task:workgroup-size
111
:inputs
lane:uint:built-in:local-invocation-index
'
shader:set-mesh-vertexlane
ok
eq:mesh-output-count-exceeds-limit
failure-reason'oversized-mesh-count'
:stage:mesh:workgroup-size
111
:inputs
lane:uint:built-in:local-invocation-index
:mesh-output
:topology:triangles:max-vertices32:max-primitives16:vertex
position:vec4:built-in:position
'
let*
vertices
primitives
shader:set-mesh-output-countsverticesprimitives
shader:set-mesh-vertexlane
ok
eq:payload-index-out-of-bounds
failure-reason'payload-overrun'
:stage:task:workgroup-size
111
:payloadmsl-task-mesh-payload:inputs
lane:uint:built-in:local-invocation-index
'
let*
shader:set-payload-elementpayload-position
shader:vec40.00.00.01.0
shader:emit-mesh-workgroups
deftesttask-and-mesh-lower-to-metal-object-and-mesh-entry-points
let
task-source
msl:msl-document-source
mesh-source
msl:msl-document-source
ok
search"struct MslTaskMeshPayload"task-source
ok
search"ulong payload_site;"task-source
ok
search"payload.payload_site = ulong(three);"task-source
ok
search"float4 payload_position[32];"task-source
ok
search"[[object]] void msl_task_probe("task-source
ok
search"object_data MslTaskMeshPayload& payload [[payload]]"task-source
ok
search"uint lane [[thread_index_in_threadgroup]]"task-source
ok
search"uint3 local_id [[thread_position_in_threadgroup]]"task-source
ok
search"uint3 group [[threadgroup_position_in_grid]]"task-source
ok
search"uint3 group_count [[threadgroups_per_grid]]"task-source
ok
search"uint3 threads [[threads_per_threadgroup]]"task-source
ok
search"payload.payload_position[lane]"task-source
ok
search"mesh_grid.set_threadgroups_per_grid"task-source
ok
search"[[mesh]] void msl_mesh_probe("mesh-source
ok
search"metal::mesh<MslMeshProbeVertex, MslMeshProbePrimitive, 32, 16, metal::topology::triangle> mesh_out"mesh-source
ok
search"object_data const MslTaskMeshPayload& payload [[payload]]"mesh-source
ok
search"uint(payload.payload_site)"mesh-source
ok
search"mesh_out.set_primitive_count(primitive_count);"mesh-source
ok
search"mesh_out.set_vertex(lane, MslMeshProbeVertex{"mesh-source
ok
search"mesh_out.set_index"mesh-source
ok
search"mesh_out.set_primitive"mesh-source
deftestslug-atlas-derivatives-and-band-selection-lower-to-metal
let
ok
search"dfdx(stage_in.render_coordinate)"fragment-source
ok
search"dfdy(stage_in.render_coordinate)"fragment-source
ok
search"stage_in.render_coordinate.y - stage_in.band_bounds.y"fragment-source
ok
search"stage_in.render_coordinate.x - stage_in.band_bounds.x"fragment-source
ok
search"band_base + horizontal_band"fragment-source
ok
search"band_base + horizontal_band_count"fragment-source
ok
search"result.render_band_bounds = float4(stage_in.band_low.xy, stage_in.band_high.xy)"vertex-source
deftestblock-vertex-lowers-projective-map-to-msl
let*
source
msl:msl-document-sourcedocument
binding
msl-binding-named'shadow-projectionspecification
ok
search"vertex BlockWorldVertexSpecificationOutput"source
ok
search"float3 shadow_projection ="source
ok
search"dot(frame_state.shadow_row_x, float4(stage_in.world_position, 1.0f))"source
ok
search"float3(0.5f, 0.5f, 1.0f)"source
ok
search"float3(0.5f, 0.5f, 0.0f)"source

The shared camera graph uses Vulkan framebuffer orientation. Metal's target boundary owns the one required clip-space Y conversion.

ok
search"result.clip_position = float4((clip).x, -(clip).y, (clip).z, (clip).w);"source
ok
search"result.shadow_depth_output = shadow_depth;"source
ok
search"tile_offset_output [[user(locn8), flat]]"source
ok
gethashexpression
msl:msl-document-expression-occurrencesdocument
deftestmsl-lowering-is-deterministic-and-does-not-perturb-spir-v
let*
spir-v-before
first
msl:msl-document-source
msl:compile-mslspecification
second
msl:msl-document-source
msl:compile-mslspecification
spir-v-after
ok
string=firstsecond
ok
equalpspir-v-beforespir-v-after
deftestmsl-occurrences-retain-expression-provenance
let*
binding
msl-binding-named'reflectedspecification
occurrences
gethashexpression
msl:msl-document-expression-occurrencesdocument
okoccurrences
ok
every
lambda
occurrence
eqexpression
gethashoccurrence
msl:msl-document-occurrence-expressiondocument
occurrences
ok
some
lambda
occurrence
search"albedo"
msl:msl-source-occurrence-textoccurrence
occurrences
deftestgenerated-msl-explains-quantities-in-plain-language
let*
source
msl:msl-document-sourcedocument
input
first
shader:shader-specification-inputsspecification
input-structure
first
msl:msl-document-declarationsdocument
field
msl-named"world_position"
msl:msl-structure-fieldsinput-structure
#'msl:msl-field-name
binding
msl-binding-named'view-zspecification
output
first
shader:shader-specification-statementsspecification
statement
msl-named"view_z"
msl:msl-entry-point-statements
msl:msl-document-entry-pointdocument
lambda
statement
and
msl:msl-variable-statement-namestatement
ok
search"World position is a point-valued vector in the lattice coordinate kind, measured in cell units, and dimensionless."source
ok
search"The xy lanes hold tile local uv as a point-valued vector"source
ok
search"This numeric value has no quantity annotation."source
ok
search"View distance is a difference-valued scalar in the lattice coordinate kind, measured in cell units"source
ok
eqinput
msl:msl-field-originfield
ok
eqbinding
msl:msl-variable-statement-originstatement
ok
eqoutput
msl:msl-output-statement-origin
find-if
lambda
statement
msl:msl-entry-point-statements
msl:msl-document-entry-pointdocument
deftesttexture-parameters-describe-their-sampled-quantity-layout
let*
source
msl:msl-document-sourcedocument
resource
find"BLOCK-ATLAS"
shader:shader-specification-resourcesspecification
:key
lambda
resource
symbol-name
:test#'string=
parameter
msl-named"block_atlas"
msl:msl-entry-point-parameters
msl:msl-document-entry-pointdocument
#'msl:msl-parameter-name
ok
search"The sampled xyz lanes hold linear rgb"source
ok
search"The sampled w lane holds surface relief"source
ok
eqresource
msl:msl-parameter-originparameter
deftesttarget-context-precedes-operator-identity
ok
equal
mapcar#'symbol-name
closer-mop:generic-function-argument-precedence-order#'shader:lower-shader-call
'
"CONTEXT""OPERATOR""EXPRESSION"
deftestslug-proof-lowers-to-direct-metal-pixel-mathematics
let*
ok
search"fragment SlugBezierFragmentSpecificationOutput"source
ok
search"sign("source
ok
search"sqrt("source
ok
search"result.color_output"source
deftestanalytic-roundrect-lowers-to-direct-metal-distance-mathematics
let*
ok
search"fragment RoundrectFragmentSpecificationOutput"source
ok
search"dfdx("source
ok
search"dfdy("source
ok
search"sqrt("source
ok
search"result.color_output"source
deftestslug-band-function-lexicals-stay-inside-their-metal-loops
let*
first-loop
search"for (uint fold_index_1"source
first-local
search"_local_1_axis_a"source
first-break
search"if ((fold_state_1.z * 1.0f) > 0.5f) break;"source
first-update
search"fold_state_1 = float3((fold_state_1.x"source
ok
search"texture2d<uint> band_data"source
ok
search"texture2d<float> curve_data"source
okfirst-loop
ok
search"for (uint fold_index_2"source
okfirst-break
ok
<first-loopfirst-breakfirst-localfirst-update
deftestcounted-fold-lowers-to-a-direct-metal-loop
let*
specification
shader:parse-shader-specification'metal-fold-probe'
:stage:fragment:inputs
count:float:location0
:outputs
result:float:location0
'
shader:set-outputresult
shader:counted-fold
indexcountsum0.0
+sumindex
source
msl:msl-document-source
msl:compile-mslspecification
ok
search"float fold_state_1 = 0.0f;"source
ok
search"for (float fold_index_1 = 0.0f;"source
ok
search"fold_state_1 = (fold_state_1 + fold_index_1);"source
ok
search"result.result = fold_state_1;"source
deftestshared-conditionals-lower-inside-direct-metal-folds
let*
specification
shader:parse-shader-specification'metal-conditional-fold-probe'
:stage:fragment:inputs
count:float:location0
limit:float:location1
:outputs
result:float:location0
'
shader:set-outputresult
shader:counted-fold
indexcountsum0.0
if
<indexlimit
+sumindex
sum
source
msl:msl-document-source
msl:compile-mslspecification
ok
search"fold_index_1 < stage_in.limit"source
ok
search"? (fold_state_1 + fold_index_1) : fold_state_1"source
deftestunsupported-msl-boundaries-retain-source-reasons
flet
reason-for
specification
handler-case
progn
msl:compile-mslspecification
nil
shader:shader-language-error
condition
shader:shader-language-error-reasoncondition
let
compute
shader:parse-shader-specification'compute-probe'
:stage:compute:outputs
value:float:location0
'
shader:set-outputvalue1.0
descriptor-set
shader:parse-shader-specification'descriptor-set-probe'
:stage:fragment:outputs
value:float:location0
:resources
image:texture-2d:set1:binding0
'
shader:set-outputvalue1.0
ok
eq:unsupported-msl-stage
reason-forcompute
ok
eq:unsupported-msl-descriptor-set
reason-fordescriptor-set
defteststorage-buffers-and-bit-fields-lower-to-device-pointers-and-shifts
let
source
ok
search"const device ulong* sites [[buffer(1)]]"source
ok
search"const device uint4* words [[buffer(2)]]"source
ok
search"ulong term = sites[uint(3.0f)];"source
ok
search"words[extent].x"source

A 64-bit field masks with a 64-bit literal, a 32-bit one with a 32-bit literal, and a field reaching the top bit needs no mask.

ok
search"((term >> 4ul) & 0xFFFFFFul)"source
ok
search"((term >> 0ul) & 0xFul)"source
ok
search"(word >> 16u)"source
ok
search"uint whole = (word);"source