luv

Workshop wiki

gpu.lisp

hal/metal/gpu.lisp

system luv · 137 definitions · on GitHub

The Metal 4 implementation of luv's portable GPU protocol.

in-package#:luv
define-conditionmetal-gpu-error
reason:initarg:reason:readermetal-gpu-error-reason
details:initarg:details:initformnil:readermetal-gpu-error-details
:report
lambda
conditionstream
formatstream"Metal GPU operation ~S failed: ~S~@[ (~S)~]."
gpu-error-operationcondition
metal-gpu-error-reasoncondition
metal-gpu-error-detailscondition
defclassmetal-gpu-provider
:documentation

A provider for the system's preferred Metal device.

Metal is the native default on Apple hosts. Preserve an explicit provider installed by an embedding application before luv finishes loading.

defclassmetal-gpu-object
native-object:initarg:native-object:readermetal-native-object
destroyed-p:initformnil:accessormetal-object-destroyed-p
retirement-teardown:initformnil:accessormetal-object-retirement-teardown
last-submission:initform0:accessormetal-object-last-submission:documentation"Newest queue submission which may still use this object."
defclassmetal-gpu-device
queue:initformnil:accessormetal-device-queue
compiler:initarg:compiler:readermetal-device-compiler
residency-set:initarg:residency-set:readermetal-device-residency-set
retiring-p:initformnil:accessormetal-device-retiring-p
residency-retired-p:initformnil:accessormetal-device-residency-retired-p
native-device-retired-p:initformnil:accessormetal-device-native-retired-p
destroy-admission:initformnil:accessormetal-device-destroy-admission
destroy-teardown:initformnil:accessormetal-device-destroy-teardown
defstructmetal-submissionvaluecommand-buffersresources
defclassmetal-gpu-queue
device:initarg:device:readermetal-queue-device
completion-event:initarg:completion-event:readermetal-queue-completion-event
submitted-value:initform0:accessormetal-queue-submitted-value
completion-signal-ready-value:initform0:accessormetal-queue-completion-signal-ready-value:documentation"Highest committed value whose presentation step finished."
completion-signal-enqueued-value:initform0:accessormetal-queue-completion-signal-enqueued-value:documentation"Highest value successfully enqueued on the shared event."
pending-submissions:initformnil:accessormetal-queue-pending-submissions
retirement-ledger:initform
make-gpu-retirement-ledger
:readermetal-queue-retirement-ledger
lock:initform
sb-thread:make-mutex:name"luv Metal submission queue"
:readermetal-queue-lock
defgenericmetal-admission-closed-p
object
:method
objectt
nil
defmethodmetal-admission-closed-p
metal-device-retiring-pdevice
defmethodmetal-admission-closed-p
metal-device-retiring-p
metal-queue-devicequeue
defclassmetal-gpu-buffer
device:initarg:device:readermetal-buffer-device
mapped:initarg:mapped:readermetal-buffer-mapped
defclassmetal-gpu-texture
device:initarg:device:readermetal-texture-device
owned-p:initarg:owned-p:initformt:readermetal-texture-owned-p
resident-p:initarg:resident-p:initformnil:readermetal-texture-resident-p
external-owner:initarg:external-owner:initformnil:readermetal-texture-external-owner
defclassmetal-gpu-texture-view
device:initarg:device:readermetal-texture-view-device
defclassmetal-gpu-sampler
device:initarg:device:readermetal-sampler-device
defclassmetal-gpu-temporal-scaler
device:initarg:device:readermetal-temporal-scaler-device
fence:initarg:fence:readermetal-temporal-scaler-fence
exposure-texture:initarg:exposure-texture:readermetal-temporal-scaler-exposure-texture
color-format:initarg:color-format:readermetal-temporal-scaler-color-format
depth-format:initarg:depth-format:readermetal-temporal-scaler-depth-format
motion-format:initarg:motion-format:readermetal-temporal-scaler-motion-format
output-format:initarg:output-format:readermetal-temporal-scaler-output-format
:documentation

A Metal4FX temporal scaler, its fence, and neutral exposure texture.

defclassmetal-gpu-bind-group-layout
device:initarg:device:readermetal-bind-group-layout-device
entries:initarg:entries:readermetal-bind-group-layout-entries
defclassmetal-gpu-bind-group
device:initarg:device:readermetal-bind-group-device
layout:initarg:layout:readermetal-bind-group-layout
entries:initarg:entries:readermetal-bind-group-entries
defclassmetal-gpu-shader-module
device:initarg:device:readermetal-shader-module-device
document:initarg:document:readermetal-shader-module-document
entry-point:initarg:entry-point:readermetal-shader-module-entry-point
function-type:initarg:function-type:readermetal-shader-module-function-type
:documentation

A device-compiled MSL library retaining its source document.

defclassmetal-gpu-render-pipeline
device:initarg:device:readermetal-render-pipeline-device
layout:initarg:layout:readermetal-render-pipeline-layout
vertex-buffers:initarg:vertex-buffers:readermetal-render-pipeline-vertex-buffers
depth-format:initarg:depth-format:readermetal-render-pipeline-depth-format
primitive-topology:initarg:primitive-topology:readermetal-render-pipeline-primitive-topology
fragment-p:initarg:fragment-p:readermetal-render-pipeline-fragment-p
depth-stencil-state:initarg:depth-stencil-state:readermetal-render-pipeline-depth-stencil-state
:documentation

A linked Metal 4 render pipeline and its draw-time depth state.

defclassmetal-gpu-mesh-render-pipeline
task-workgroup-size:initarg:task-workgroup-size:readermetal-mesh-pipeline-task-workgroup-size
mesh-workgroup-size:initarg:mesh-workgroup-size:readermetal-mesh-pipeline-mesh-workgroup-size
:documentation

A linked Metal 4 object/mesh pipeline with its dispatch geometry.

defclassmetal-gpu-command-encoder
device:initarg:device:readermetal-command-encoder-device
allocator:initarg:allocator:accessormetal-encoder-allocator
command-buffer:initarg:command-buffer:accessormetal-encoder-command-buffer
resources:initform
make-hash-table:test#'eq
:readermetal-encoder-resources
active-pass:initformnil:accessormetal-encoder-active-pass
pending-consumer-barrier:initformnil:accessormetal-encoder-pending-consumer-barrier
retirement-teardown:initformnil:accessormetal-encoder-retirement-teardown
state:initform:recording:accessormetal-encoder-state
encoded-p:initformnil:accessormetal-encoder-encoded-p
:documentation

A general Metal 4 command encoder which owns recording memory until finish.

defclassmetal-gpu-command-buffer
device:initarg:device:readermetal-command-buffer-device
allocator:initarg:allocator:readermetal-command-buffer-allocator
resources:initarg:resources:readermetal-command-buffer-resources
state:initform:ready:accessormetal-command-buffer-state
:documentation

One finished, one-shot Metal 4 command buffer and its recorded dependencies.

defclassmetal-render-pass-encoder
owner:initarg:owner:readermetal-render-pass-owner
native-encoder:initarg:native-encoder:readermetal-render-pass-native-encoder
pipeline:initformnil:accessormetal-render-pass-pipeline
argument-table:initformnil:accessormetal-render-pass-argument-table
vertex-bindings:initform
make-hash-table
:readermetal-render-pass-vertex-bindings
bind-group:initformnil:accessormetal-render-pass-bind-group
state:initform:encoding:accessormetal-render-pass-state
:documentation

A Metal 4 render encoder whose resources arrive through argument tables.

The first vertex-stage realization is the executable mechanism described by #348B7B; it deliberately has no legacy individual-resource setter path.

defunensure-live-metal-object
objectoperation
when
or
metal-object-destroyed-pobject
error'gpu-object-destroyed-error:objectobject:operationoperation
object
defuncall-with-live-metal-device-queue
deviceoperationthunk

Serialize admitted device-native work against device destruction.

let
queue
metal-device-queuedevice
ifqueue
sb-thread:with-recursive-lock
metal-queue-lockqueue
funcallthunk
progn
funcallthunk
defmacrowith-live-metal-device-queue
deviceoperation
&bodybody
`
call-with-live-metal-device-queue,device,operation
lambda
,@body
defuncheck-metal-device-descriptor
descriptor
unless
typepdescriptor'device-descriptor
error'gpu-request-error:operation:request-device:descriptordescriptor:reason:invalid-descriptor:detailsdescriptor
when
device-descriptor-required-featuresdescriptor
error'gpu-request-error:operation:request-device:descriptordescriptor:reason:unsupported-features:details
device-descriptor-required-featuresdescriptor
when
device-descriptor-required-limitsdescriptor
error'gpu-request-error:operation:request-device:descriptordescriptor:reason:unsupported-limits:details
device-descriptor-required-limitsdescriptor
defmethodrequest-gpu-device
&optionaldescriptor
declare
ignoreprovider
let
descriptor
ordescriptor
make-device-descriptor
let
unlessnative-device
error'metal-gpu-error:operation:request-device:reason:no-system-device
handler-case
let
native-queuenil
native-compilernil
native-residency-setnil
native-completion-eventnil
unwind-protect
progn
setfnative-queue
unlessnative-queue
error'metal-gpu-error:operation:request-device:reason:metal-4-unavailable
multiple-value-bind
compilerdiagnostic
luv.metal:new-metal-4-compilernative-device:label"luv Metal 4 compiler"
unlesscompiler
error'metal-gpu-error:operation:request-device:reason:metal-4-compiler-unavailable:detailsdiagnostic
setfnative-compilercompiler
multiple-value-bind
residency-setdiagnostic
luv.metal:new-metal-residency-setnative-device:label"luv Metal 4 resources"
unlessresidency-set
error'metal-gpu-error:operation:request-device:reason:residency-set-creation-failed:detailsdiagnostic
setfnative-residency-setresidency-set
setfnative-completion-event
unlessnative-completion-event
error'metal-gpu-error:operation:request-device:reason:completion-event-creation-failed
luv.metal:add-metal-queue-residency-setnative-queuenative-residency-set
let*
device
make-instance'metal-gpu-device:label
gpu-descriptor-labeldescriptor
:native-objectnative-device:compilernative-compiler:residency-setnative-residency-set
queue
make-instance'metal-gpu-queue:label"default Metal 4 queue":native-objectnative-queue:devicedevice:completion-eventnative-completion-event
setf
metal-device-queuedevice
queue
native-queuenilnative-compilernilnative-residency-setnilnative-completion-eventnil
device
whennative-completion-event
whennative-residency-set
whennative-compiler
whennative-queue
error
condition
unless
luv.objective-c:objective-c-object-released-pnative-device
errorcondition
defmethoddevice-queue
ensure-live-metal-objectdevice:device-queue
metal-device-queuedevice
defunensure-metal-command-encoder-state
encoderoperation
unless
eq:recording
metal-encoder-stateencoder
error'gpu-invalid-state-error:objectencoder:operationoperation:state
metal-encoder-stateencoder
:expected-state:recording
encoder
defunensure-no-active-metal-pass
encoderoperation
when
metal-encoder-active-passencoder
error'gpu-invalid-state-error:objectencoder:operationoperation:state:pass-active:expected-state:between-passes
encoder
defunretain-metal-resource
encoderresource

Retain resource as a dependency of encoder's eventual command buffer.

setf
gethashresource
metal-encoder-resourcesencoder
t
resource
defunmetal-encoder-resource-list
encoder
loopforresourcebeingthehash-keysof
metal-encoder-resourcesencoder
collectresource
defmethodcreate
descriptorcommand-encoder-descriptor

Allocate and begin one general Metal 4 command buffer.

ensure-live-metal-objectdevice:create-command-encoder
let
allocatornil
command-buffernil
completed-pnil
unwind-protect
progn
setfallocator
luv.metal:new-command-allocator
metal-native-objectdevice
command-buffer
luv.metal:new-command-buffer
metal-native-objectdevice
unless
andallocatorcommand-buffer
error'metal-gpu-error:operation:create-command-encoder:reason:command-resource-creation-failed
luv.metal:begin-command-buffercommand-bufferallocator
let
encoder
make-instance'metal-gpu-command-encoder:label
gpu-descriptor-labeldescriptor
:devicedevice:allocatorallocator:command-buffercommand-buffer
setfallocatornilcommand-buffernilcompleted-pt
encoder
unlesscompleted-p
whencommand-buffer
defmethodfinish

End recording and transfer native memory and dependencies to one-shot work.

unless
member
metal-encoder-stateencoder
'
:recording:ended
error'gpu-invalid-state-error:objectencoder:operation:finish:state
metal-encoder-stateencoder
:expected-state:recording-or-ended
when
eq:recording
metal-encoder-stateencoder
let*
device
metal-command-encoder-deviceencoder
queue
metal-device-queuedevice
flet
finish-under-lock
unless
member
metal-encoder-stateencoder
'
:recording:ended
error'gpu-invalid-state-error:objectencoder:operation:finish:state
metal-encoder-stateencoder
:expected-state:recording-or-ended
when
eq:recording
metal-encoder-stateencoder
let
command-buffer
metal-encoder-command-bufferencoder
allocator
metal-encoder-allocatorencoder
when
eq:recording
metal-encoder-stateencoder

Retain explicit encoder ownership until wrapper publication.

setf
metal-encoder-stateencoder
:ended
let
wrapper
make-metal-finished-command-bufferencoderdevicecommand-bufferallocator
setf
metal-encoder-stateencoder
:finished
metal-encoder-command-bufferencoder
nil
metal-encoder-allocatorencoder
nil
wrapper
ifqueue
sb-thread:with-recursive-lock
metal-queue-lockqueue
finish-under-lock
finish-under-lock
defunmake-metal-finished-command-buffer
encoderdevicecommand-bufferallocator

Publish encoder's ended native ownership as one command-buffer wrapper.

make-instance'metal-gpu-command-buffer:label
gpu-object-labelencoder
:native-objectcommand-buffer:allocatorallocator:devicedevice:resources
defgenericmetal-native-teardown-closure
object
:documentation

Return object's persistent, progress-tracked native teardown closure.

defunflush-metal-queue-completion-signal
queue

Enqueue queue's newest ready shared-event signal, retaining it on failure.

sb-thread:with-recursive-lock
metal-queue-lockqueue
let
ready
metal-queue-completion-signal-ready-valuequeue
enqueued
metal-queue-completion-signal-enqueued-valuequeue
when
>readyenqueued

Re-enqueuing the same monotonic value is safe if the Objective-C wrapper returned nonlocally after the native message took effect.

luv.metal:signal-metal-event
metal-native-objectqueue
metal-queue-completion-eventqueue
ready
setf
metal-queue-completion-signal-enqueued-valuequeue
ready
t
defunmetal-retirement-custodian-quiescent-p
queue

Whether queue owns no signal, submitted, or native-retirement obligation.

let
ledger
metal-queue-retirement-ledgerqueue
and
<=
metal-queue-completion-signal-ready-valuequeue
metal-queue-completion-signal-enqueued-valuequeue
null
metal-queue-pending-submissionsqueue
null
gpu-retirement-ledger-active-batchledger
null
gpu-retirement-ledger-entriesledger
defunmaybe-release-metal-retirement-custodian
queue

Unroot queue only after backend quiescence was proved under its lock.

defunmaintain-metal-queue
queue

Retire completed submissions and every now-eligible native ownership.

sb-thread:with-recursive-lock
metal-queue-lockqueue
let
loopwhile
and
metal-queue-pending-submissionsqueue
<=
metal-submission-value
first
metal-queue-pending-submissionsqueue
frontier
do
pop
metal-queue-pending-submissionsqueue
maintain-gpu-retirement-ledger
metal-queue-retirement-ledgerqueue
frontier:operation:maintain-metal-queue
frontier
defmethodservice-gpu-retirement-custodian

Service queue from the process custodian registry without caller access.

sb-thread:with-recursive-lock
metal-queue-lockqueue
let*
device
metal-queue-devicequeue
ledger
metal-queue-retirement-ledgerqueue
before
+
length
metal-queue-pending-submissionsqueue
if
>
metal-queue-completion-signal-ready-valuequeue
metal-queue-completion-signal-enqueued-valuequeue
10
length
gpu-retirement-ledger-active-batchledger
length
gpu-retirement-ledger-entriesledger
cond
or
metal-object-destroyed-pqueue
metal-object-destroyed-pdevice
metal-device-retiring-pdevice
metal-device-native-retired-pdevice

Never message a retiring/released MTLDevice or its event. Device teardown has already enforced this queue's complete barrier.

t
let
after
+
length
metal-queue-pending-submissionsqueue
if
>
metal-queue-completion-signal-ready-valuequeue
metal-queue-completion-signal-enqueued-valuequeue
10
length
gpu-retirement-ledger-active-batchledger
length
gpu-retirement-ledger-entriesledger
or
<afterbefore
zeropafter
defunlive-metal-retirement-queue-p
queuedevice
andqueue
eqqueue
metal-device-queuedevice
not
metal-object-destroyed-pdevice
not
metal-device-retiring-pdevice
not
metal-device-native-retired-pdevice
not
metal-object-destroyed-pqueue
defunretire-metal-native-owner
resourcedeviceready-afterteardowninvalidateoperation

Transfer one native owner after revalidating its queue under the lock.

labels
retire-directly
&optionalqueue-snapshot
perform-gpu-retirement-directlyresource
lambda
unless
or
metal-object-destroyed-pdevice
metal-device-native-retired-pdevice
when
andqueue-snapshot
or
not
eqqueue-snapshot
metal-device-queuedevice
metal-object-destroyed-pqueue-snapshot
error"The Metal retirement queue is no longer live."
funcallteardown
invalidate:operationoperation
let
queue
metal-device-queuedevice
ifqueue
sb-thread:with-recursive-lock
metal-queue-lockqueue
if
progn
transfer-gpu-retirement
metal-queue-retirement-ledgerqueue
resourceready-afterteardowninvalidatequeue
retire-directlyqueue
retire-directly
values
defmethodretire-gpu-native-owner
ownerteardowninvalidate
retire-metal-native-ownerownerdevice0teardowninvalidate:retire-gpu-native-owner
defunmetal-destroy-or-defer
resourcedevice&optionalextra-invalidation

Transfer resource's native ownership before logically invalidating it.

flet
invalidate
setf
metal-object-destroyed-presource
t
whenextra-invalidation
funcallextra-invalidation
let
teardown
or
metal-object-retirement-teardownresource
setf
metal-object-retirement-teardownresource
retire-metal-native-ownerresourcedevice
metal-object-last-submissionresource
teardown#'invalidate:destroy-metal-resource
values
defuncheck-metal-command-buffer-for-submit
queuecommand-buffer
unless
typepcommand-buffer'metal-gpu-command-buffer
error'gpu-request-error:operation:submit:descriptorcommand-buffer:reason:invalid-command-buffer
ensure-live-metal-objectcommand-buffer:submit
unless
eq
metal-queue-devicequeue
metal-command-buffer-devicecommand-buffer
error'gpu-device-mismatch-error:objectcommand-buffer:operation:submit:expected-device
metal-queue-devicequeue
:actual-device
metal-command-buffer-devicecommand-buffer
unless
eq:ready
metal-command-buffer-statecommand-buffer
error'gpu-invalid-state-error:objectcommand-buffer:operation:submit:state
metal-command-buffer-statecommand-buffer
:expected-state:ready
dolist
resource
metal-command-buffer-resourcescommand-buffer
command-buffer
defuncollect-metal-submission-resources
command-buffers
remove-duplicates
loopforcommand-bufferacrosscommand-buffersappend
metal-command-buffer-resourcescommand-buffer
:test#'eq
defmethodsubmitted-work-done

Wait for the Metal 4 shared-event frontier most recently submitted.

ensure-live-metal-objectqueue:submitted-work-done
sb-thread:with-recursive-lock
metal-queue-lockqueue
ensure-live-metal-objectqueue:submitted-work-done
let
value
metal-queue-submitted-valuequeue
when
pluspvalue
unless
plusp
luv.metal:wait-for-metal-shared-event
metal-queue-completion-eventqueue
value30000
error'metal-gpu-error:operation:submitted-work-done:reason:completion-timeout:detailsvalue
values
defunsubmit-metal-command-buffers
queuecommand-buffers&keyafter-commit

Commit finished Metal work and retain its dependencies to queue's frontier.

after-commit performs the drawable signal and presentation handshake before the completion event is enqueued. Presentation is the only caller of that backend-local extension; ordinary callers use submit. #T9K4RC

unless
vectorpcommand-buffers
error'gpu-request-error:operation:submit:descriptorcommand-buffers:reason:invalid-command-buffers
when
zerop
lengthcommand-buffers
sb-thread:with-recursive-lock
metal-queue-lockqueue

Device teardown closes admission under this lock. Recheck after any wait to make this the authoritative gate before maintenance and FFI.

loopforcommand-bufferacrosscommand-buffersdo
let*
resources
native-command-buffers
map'vector#'metal-native-objectcommand-buffers
luv.metal:commit-command-buffers
metal-native-objectqueue
native-command-buffers
let
value
incf
metal-queue-submitted-valuequeue
loopforcommand-bufferacrosscommand-buffersdo
setf
metal-command-buffer-statecommand-buffer
:submitted
metal-object-last-submissioncommand-buffer
value
dolist
resourceresources
setf
metal-object-last-submissionresource
value

Register queue ownership before presentation can fail.

setf
metal-queue-pending-submissionsqueue
nconc
metal-queue-pending-submissionsqueue
list
make-metal-submission:valuevalue:command-bufferscommand-buffers:resourcesresources
retain-gpu-retirement-ledger-custodian
metal-queue-retirement-ledgerqueue
queue
unwind-protect
whenafter-commit
funcallafter-commit

Presentation must be ordered before completion, but failure to enqueue that completion is now a rooted retryable queue obligation.

setf
metal-queue-completion-signal-ready-valuequeue
maxvalue
metal-queue-completion-signal-ready-valuequeue
value
defmethoddestroy
when
member
metal-encoder-stateencoder
'
:recording:ended
when
and
eq:recording
metal-encoder-stateencoder
metal-encoder-active-passencoder
end-pass
metal-encoder-active-passencoder
let
device
metal-command-encoder-deviceencoder
command-buffer
metal-encoder-command-bufferencoder
allocator
metal-encoder-allocatorencoder
ended-p
eq:ended
metal-encoder-stateencoder
flet
invalidate
setf
metal-encoder-command-bufferencoder
nil
metal-encoder-allocatorencoder
nil
metal-encoder-stateencoder
:destroyed
let
teardown
or
metal-encoder-retirement-teardownencoder
setf
metal-encoder-retirement-teardownencoder
apply#'make-gpu-retirement-sequence
append
whencommand-buffer
append
unlessended-p
list
lambda
whenallocator
retire-metal-native-ownerencoderdevice0teardown#'invalidate:destroy-metal-command-encoder
unless
eq:destroyed
metal-encoder-stateencoder
setf
metal-encoder-stateencoder
:destroyed
values
defmethodmetal-native-teardown-closure
let
native
metal-native-objectcommand-buffer
allocator
metal-command-buffer-allocatorcommand-buffer
defmethoddestroy
unless
metal-object-destroyed-pcommand-buffer
metal-destroy-or-defercommand-buffer
metal-command-buffer-devicecommand-buffer
lambda
setf
metal-command-buffer-statecommand-buffer
:destroyed
values
defmethodsubmit
submit-metal-command-buffersqueue
vectorcommand-buffer
defmethodsubmit
command-buffersvector
submit-metal-command-buffersqueuecommand-buffers
defunmake-metal-device-destroy-admission
devicequeue

Return a persistent completion-and-ledger barrier for device destruction.

let
waited-submissionnil
lambda
unless
metal-device-retiring-pdevice
let
submission
ifqueue
metal-queue-submitted-valuequeue
0
unless
eqlsubmissionwaited-submission
when
pluspsubmission
unless
plusp
luv.metal:wait-for-metal-shared-event
metal-queue-completion-eventqueue
submission30000
error'metal-gpu-error:operation:destroy-metal-device:reason:completion-timeout:detailssubmission
setfwaited-submissionsubmission
whenqueue
ensure-gpu-retirement-ledger-empty
metal-queue-retirement-ledgerqueue
:operation:destroy-metal-device
setf
metal-device-retiring-pdevice
t
defunmake-metal-device-destroy-teardown
devicequeue

Return device's persistent one-native-call-at-a-time teardown.

apply#'make-gpu-retirement-sequence
append
list
lambda
whenqueue
list
lambda
luv.metal:remove-metal-queue-residency-set
metal-native-objectqueue
metal-device-residency-setdevice
lambda
luv.objective-c:release-objective-c-object
metal-queue-completion-eventqueue
lambda
list
lambda
luv.objective-c:release-objective-c-object
metal-device-residency-setdevice
setf
metal-device-residency-retired-pdevice
t
lambda
setf
metal-device-native-retired-pdevice
t
lambda
setf
metal-object-destroyed-pdevice
t
whenqueue
setf
metal-object-destroyed-pqueue
t
defmethoddestroy
unless
metal-object-destroyed-pdevice
let
queue
metal-device-queuedevice
flet
tear-down-device
funcall
or
metal-device-destroy-admissiondevice
setf
metal-device-destroy-admissiondevice
whenqueue
ensure-gpu-retirement-ledger-empty
metal-queue-retirement-ledgerqueue
:operation:destroy-metal-device
funcall
or
metal-device-destroy-teardowndevice
setf
metal-device-destroy-teardowndevice
ifqueue
sb-thread:with-recursive-lock
metal-queue-lockqueue
tear-down-device
tear-down-device
values
defmethodcreate
descriptorbuffer-descriptor

Create one shared Metal buffer and add its allocation to device residency.

ensure-live-metal-objectdevice:create-buffer
let
size
buffer-descriptor-sizedescriptor
usage
buffer-descriptor-usagedescriptor
let
native-buffer
luv.metal:new-metal-buffer
metal-native-objectdevice
size0
unlessnative-buffer
error'metal-gpu-error:operation:create-buffer:reason:buffer-creation-failed:detailssize
let
resident-pnil
completed-pnil
unwind-protect
let
when
cffi:null-pointer-pmapped
error'metal-gpu-error:operation:create-buffer:reason:buffer-not-cpu-visible
luv.metal:add-metal-residency-allocation
metal-device-residency-setdevice
native-buffer
setfresident-pt
luv.metal:commit-metal-residency-set
metal-device-residency-setdevice
let
buffer
make-instance'metal-gpu-buffer:label
gpu-descriptor-labeldescriptor
:sizesize:usageusage:devicedevice:native-objectnative-buffer:mappedmapped
setfcompleted-pt
buffer
unlesscompleted-p
whenresident-p
luv.metal:remove-metal-residency-allocation
metal-device-residency-setdevice
native-buffer
luv.metal:commit-metal-residency-set
metal-device-residency-setdevice
defmethodwrite-buffer
data&key
offset0

Copy a one-dimensional numeric array into shared Metal memory.

data holds single-floats or unsigned 8-, 16-, 32-, or 64-bit integers; offset is aligned to the element size.

ensure-live-metal-objectbuffer:write-buffer
multiple-value-bind
foreign-typeelement-size
unlessforeign-type
reject-metal-gpu-requestbuffer:unsupported-buffer-datadata
unless
and
typepoffset'
unsigned-byte64
zerop
modoffsetelement-size
<=
+offset
*element-size
lengthdata
gpu-buffer-sizebuffer
reject-metal-gpu-requestbuffer:buffer-write-out-of-bounds
list:offsetoffset:length
*element-size
lengthdata

Numeric storage vectors are unboxed. Pin and copy their bytes once; crossing CFFI once per element turns large streamed populations into a multi-million-call owner-thread stall.

let
destination
cffi:inc-pointer
metal-buffer-mappedbuffer
offset
sb-kernel:with-array-data
vectordata
start0
end
lengthdata
sb-sys:with-pinned-objects
vector
sb-kernel:system-area-ub8-copy
sb-sys:vector-sapvector
*startelement-size
destination0
*element-size
-endstart
buffer
defmethodread-buffer
&key
offset0
size
ensure-live-metal-objectbuffer:read-buffer
let
size
orsize
-
gpu-buffer-sizebuffer
offset
unless
and
typepoffset'
unsigned-byte64
typepsize'
unsigned-byte64
<=
+offsetsize
gpu-buffer-sizebuffer
reject-metal-gpu-requestbuffer:buffer-read-out-of-bounds
list:offsetoffset:sizesize
submitted-work-done
device-queue
metal-buffer-devicebuffer
let
bytes
make-arraysize:element-type'
unsigned-byte8
source
cffi:inc-pointer
metal-buffer-mappedbuffer
offset
sb-sys:with-pinned-objects
bytes
sb-kernel:system-area-ub8-copysource0
sb-sys:vector-sapbytes
0size
bytes
defmethodread-buffer-if-ready
&key
offset0
size
ensure-live-metal-objectbuffer:read-buffer-if-ready
let*
size
orsize
-
gpu-buffer-sizebuffer
offset
queue
device-queue
metal-buffer-devicebuffer
unless
and
typepoffset'
unsigned-byte64
typepsize'
unsigned-byte64
<=
+offsetsize
gpu-buffer-sizebuffer
reject-metal-gpu-requestbuffer:buffer-read-out-of-bounds
list:offsetoffset:sizesize
sb-thread:with-recursive-lock
metal-queue-lockqueue
ensure-live-metal-objectbuffer:read-buffer-if-ready
let
when
<=
metal-object-last-submissionbuffer
frontier
let
bytes
make-arraysize:element-type'
unsigned-byte8
source
cffi:inc-pointer
metal-buffer-mappedbuffer
offset
sb-sys:with-pinned-objects
bytes
sb-kernel:system-area-ub8-copysource0
sb-sys:vector-sapbytes
0size
valuesbytest
defmethodmetal-native-teardown-closure
let*
device
metal-buffer-devicebuffer
residency-set
metal-device-residency-setdevice
native
metal-native-objectbuffer
make-gpu-retirement-sequence
lambda
unless
metal-device-residency-retired-pdevice
lambda
unless
metal-device-residency-retired-pdevice
defmethoddestroy
unless
metal-object-destroyed-pbuffer
metal-destroy-or-deferbuffer
metal-buffer-devicebuffer
values
defmethodcreate
descriptortexture-descriptor

Create one resident two-dimensional Metal texture.

ensure-live-metal-objectdevice:create-texture
let*
size
texture-descriptor-sizedescriptor
usage
texture-descriptor-usagedescriptor
native
luv.metal:new-metal-texture
metal-native-objectdevice
firstsize
secondsize
metal-resource-pixel-format
texture-descriptor-formatdescriptor
descriptor
:storage-mode:label
gpu-descriptor-labeldescriptor
unlessnative
error'metal-gpu-error:operation:create-texture:reason:texture-creation-failed:detailsdescriptor
let
resident-pnil
completed-pnil
unwind-protect
progn
luv.metal:add-metal-residency-allocation
metal-device-residency-setdevice
native
setfresident-pt
luv.metal:commit-metal-residency-set
metal-device-residency-setdevice
let
texture
make-instance'metal-gpu-texture:label
gpu-descriptor-labeldescriptor
:devicedevice:native-objectnative:owned-pt:resident-pt:sizesize:usageusage:dimensions:2d:format
texture-descriptor-formatdescriptor
setfcompleted-pt
texture
unlesscompleted-p
whenresident-p
luv.metal:remove-metal-residency-allocation
metal-device-residency-setdevice
native
luv.metal:commit-metal-residency-set
metal-device-residency-setdevice
defunportable-metal-texture-usage
nativedescriptorrole

Translate a MetalFX texture usage mask into the portable usage vocabulary.

let
unless
zerop
logandc2nativeknown
reject-metal-gpu-requestdescriptor:unsupported-metalfx-texture-usage
listrolenative
append
when'
:texture-binding
when'
:storage-binding
when'
:render-attachment
defmethodcreate
descriptortemporal-scaler-descriptor

Create one synchronous Metal4FX temporal scaler for a fixed extent.

The scaler publishes the exact native texture contract that Luft uses to construct its temporal surface cohort. #NL5J0J

ensure-live-metal-objectdevice:create-temporal-scaler
let*
input-size
canonical-texture-extent
temporal-scaler-descriptor-input-sizedescriptor
descriptor:create-temporal-scaler
output-size
canonical-texture-extent
temporal-scaler-descriptor-output-sizedescriptor
descriptor:create-temporal-scaler
color-format
temporal-scaler-descriptor-color-formatdescriptor
depth-format
temporal-scaler-descriptor-depth-formatdescriptor
motion-format
temporal-scaler-descriptor-motion-formatdescriptor
output-format
temporal-scaler-descriptor-output-formatdescriptor
nativefenceexposurescaler
completed-pnil
unless
and
=1
thirdinput-size
=1
thirdoutput-size
reject-metal-gpu-requestdescriptor:invalid-temporal-scaler-extent
unwind-protect
progn
log-event:metal"begin Metal4FX temporal scaler ~{~Dx~D~}"
subseqinput-size02
multiple-value-setq
nativefence
luv.metal:new-metal-4-temporal-scaler
metal-native-objectdevice
metal-device-compilerdevice
metal-resource-pixel-formatcolor-formatdescriptor
metal-resource-pixel-formatdepth-formatdescriptor
metal-resource-pixel-formatmotion-formatdescriptor
metal-resource-pixel-formatoutput-formatdescriptor
firstinput-size
secondinput-size
firstoutput-size
secondoutput-size
unless
andnativefence
error'metal-gpu-error:operation:create-temporal-scaler:reason:unsupported-or-creation-failed:detailsdescriptor
multiple-value-bind
native-color-usagenative-depth-usagenative-motion-usagenative-output-usage
let
color-usage
portable-metal-texture-usagenative-color-usagedescriptor:color
depth-usage
portable-metal-texture-usagenative-depth-usagedescriptor:depth
motion-usage
portable-metal-texture-usagenative-motion-usagedescriptor:motion
output-usage
portable-metal-texture-usagenative-output-usagedescriptor:output
setfexposure
createdevice
make-texture-descriptor:label"MetalFX neutral exposure":size'
11
:dimensions:2d:format:r16-float:usage'
:copy-dst:texture-binding
write-texture
make-texture-copy:textureexposure
make-array'
11
:element-type'
unsigned-byte16
:initial-element#x3c00
make-texture-data-layout:bytes-per-row2
'
11
setfscaler
make-instance'metal-gpu-temporal-scaler:label
gpu-descriptor-labeldescriptor
:native-objectnative:devicedevice:fencefence:exposure-textureexposure:input-sizeinput-size:output-sizeoutput-size:color-formatcolor-format:depth-formatdepth-format:motion-formatmotion-format:output-formatoutput-format:color-usagecolor-usage:depth-usagedepth-usage:motion-usagemotion-usage:output-usageoutput-usage
completed-ptnativenilfencenilexposurenil
log-event:metal"complete Metal4FX temporal scaler"
scaler
unlesscompleted-p
whenexposure
ignore-errors
defmethodadopt-native-texture
nativeowner
descriptortexture-descriptor
ensure-live-metal-objectdevice:adopt-native-texture
unless
reject-metal-gpu-requestdescriptor:invalid-native-texturenative
with-live-metal-device-queue
device:adopt-native-texture
let
size
texture-descriptor-sizedescriptor
usage
texture-descriptor-usagedescriptor
resident-pnil
completed-pnil
when
member:storage-bindingusage
reject-metal-gpu-requestdescriptor:unsupported-texture-usage:storage-binding
unwind-protect
progn

Metal 4 does not make an externally created MTLTexture resident merely because an argument table points at it. CVMetalTexture planes therefore need the same explicit residency membership as textures allocated by this device.

luv.metal:add-metal-residency-allocation
metal-device-residency-setdevice
native
setfresident-pt
luv.metal:commit-metal-residency-set
metal-device-residency-setdevice
let
texture
make-instance'metal-gpu-texture:label
gpu-descriptor-labeldescriptor
:devicedevice:native-objectnative:owned-pnil:resident-pt:external-ownerowner:sizesize:usageusage:dimensions:2d:format
texture-descriptor-formatdescriptor
setfcompleted-pt
texture
when
andresident-p
notcompleted-p
luv.metal:remove-metal-residency-allocation
metal-device-residency-setdevice
native
luv.metal:commit-metal-residency-set
metal-device-residency-setdevice
defmethodcreate
descriptortexture-view-descriptor
ensure-live-metal-objectdevice:create-texture-view
let
texture
texture-view-descriptor-texturedescriptor
unless
typeptexture'metal-gpu-texture
reject-metal-gpu-requestdescriptor:incompatible-texturetexture
ensure-metal-object-devicetexture
metal-texture-devicetexture
device:create-texture-view

The first Metal vocabulary exposes only complete single-mip views, so the view is a semantic wrapper over the same native texture.

make-instance'metal-gpu-texture-view:label
gpu-descriptor-labeldescriptor
:devicedevice:texturetexture:native-object
metal-native-objecttexture
defunmetal-sampler-filter
filterdescriptor
declare
ignoredescriptor
defunmetal-sampler-mip-filter
filterdescriptor
declare
ignoredescriptor
defmethodcreate
descriptorsampler-descriptor
ensure-live-metal-objectdevice:create-sampler
let
native
luv.metal:new-metal-sampler
metal-native-objectdevice
metal-sampler-filter
sampler-descriptor-min-filterdescriptor
descriptor
metal-sampler-filter
sampler-descriptor-mag-filterdescriptor
descriptor
metal-sampler-mip-filter
sampler-descriptor-mipmap-filterdescriptor
descriptor
metal-sampler-address-mode
sampler-descriptor-address-mode-udescriptor
descriptor
metal-sampler-address-mode
sampler-descriptor-address-mode-vdescriptor
descriptor
metal-sampler-address-mode
sampler-descriptor-address-mode-wdescriptor
descriptor
metal-compare-function
or
sampler-descriptor-comparedescriptor
:never
:label
gpu-descriptor-labeldescriptor
unlessnative
error'metal-gpu-error:operation:create-sampler:reason:sampler-creation-failed:detailsdescriptor
make-instance'metal-gpu-sampler:label
gpu-descriptor-labeldescriptor
:devicedevice:native-objectnative
defunnormalize-metal-bind-group-layout-entries
descriptor
let*
entries
bind-group-layout-descriptor-entriesdescriptor
bindings
mapcar
lambda
entry
getfentry:binding
entries
unless
and
listpentries
entries
every
lambda
entry
and
listpentry
typep
getfentry:binding
'
unsigned-byte32
member
getfentry:type
'
:texture:sampler:uniform-buffer:storage-buffer
entries
=
lengthbindings
length
remove-duplicatesbindings
reject-metal-gpu-requestdescriptor:unsupported-bind-group-layoutentries
entries
defmethodcreate
descriptorbind-group-layout-descriptor
ensure-live-metal-objectdevice:create-bind-group-layout
make-instance'metal-gpu-bind-group-layout:label
gpu-descriptor-labeldescriptor
:devicedevice:native-objectnil:entries
defunvalidate-metal-bind-group-entries
devicedescriptorlayout
let
entries
bind-group-descriptor-entriesdescriptor
layout-entries
metal-bind-group-layout-entrieslayout
unless
=
lengthentries
lengthlayout-entries
reject-metal-gpu-requestdescriptor:incomplete-bind-groupentries
dolist
layout-entrylayout-entries
let*
binding
getflayout-entry:binding
entry
findbindingentries:key
lambda
candidate
getfcandidate:binding
resource
andentry
getfentry:resource
unless
andentry
ecase
getflayout-entry:type
:texture
:sampler
typepresource'metal-gpu-sampler
:uniform-buffer
and
typepresource'metal-gpu-buffer
member:uniform
gpu-buffer-usageresource
:storage-buffer
and
typepresource'metal-gpu-buffer
member:storage
gpu-buffer-usageresource
reject-metal-gpu-requestdescriptor:invalid-bind-group-entrylayout-entry
ensure-metal-object-deviceresource
etypecaseresource
metal-gpu-texture-view
metal-texture-view-deviceresource
metal-gpu-sampler
metal-sampler-deviceresource
metal-gpu-buffer
metal-buffer-deviceresource
device:create-bind-group
entries
defmethodcreate
descriptorbind-group-descriptor
ensure-live-metal-objectdevice:create-bind-group
let
layout
bind-group-descriptor-layoutdescriptor
unless
reject-metal-gpu-requestdescriptor:incompatible-bind-group-layoutlayout
ensure-metal-object-devicelayout
metal-bind-group-layout-devicelayout
device:create-bind-group
make-instance'metal-gpu-bind-group:label
gpu-descriptor-labeldescriptor
:devicedevice:layoutlayout:native-objectnil:entries
defmethodenqueue
commandgpu-write-texture-command

Upload one tightly represented byte image into a shared Metal texture.

ensure-live-metal-objectqueue:write-texture
let*
copy
gpu-write-texture-command-destinationcommand
texture
texture-copy-texturecopy
layout
gpu-write-texture-command-data-layoutcommand
size
canonical-texture-extent
gpu-write-texture-command-sizecommand
command:write-texture
data
gpu-write-texture-command-datacommand
offset
texture-data-layout-offsetlayout
bytes-per-row
texture-data-layout-bytes-per-rowlayout
bytes-per-texel
and
typeptexture'metal-gpu-texture
texture-format-bytes-per-texel
gpu-texture-formattexture
element-type
and
typeptexture'metal-gpu-texture
texture-format-upload-element-type
gpu-texture-formattexture
foreign-type
casebytes-per-texel
2:uint16
4:uint32
8:uint64
unless
and
typeptexture'metal-gpu-texture
eq
metal-texture-devicetexture
metal-queue-devicequeue
member:copy-dst
gpu-texture-usagetexture
zerop
texture-copy-mip-levelcopy
equal'
000
texture-copy-origincopy
equalsize
gpu-texture-sizetexture
arraypdata
=2
array-rankdata
nth-value0
subtypep
array-element-typedata
element-type
=
array-dimensiondata0
secondsize
=
array-dimensiondata1
firstsize
typepoffset'
unsigned-byte64
zerop
modoffsetbytes-per-texel
typepbytes-per-row'
integer1*
>=bytes-per-row
*bytes-per-texel
firstsize
zerop
modbytes-per-rowbytes-per-texel
reject-metal-gpu-requestcommand:unsupported-texture-upload

A tightly packed simple array is already exactly the image Metal wants, so pin it and hand over its own storage. Staging it word by word costs tens of milliseconds on an image the size of a video frame, which is a whole frame's budget spent copying memory that did not need copying.

if
upload-can-share-storage-pdataoffsetbytes-per-rowbytes-per-texelsize
share-metal-upload-storagetexturedata
firstsize
secondsize
bytes-per-row
cffi:with-foreign-object
storage:uint8
+offset
*bytes-per-row
secondsize
dotimes
row
secondsize
let
destination
cffi:inc-pointerstorage
+offset
*rowbytes-per-row
dotimes
column
firstsize
setf
cffi:mem-arefdestinationforeign-typecolumn
row-major-arefdata
+
*row
array-dimensiondata1
column
luv.metal:replace-metal-texture-region
metal-native-objecttexture
firstsize
secondsize
cffi:inc-pointerstorageoffset
bytes-per-row
command
defunupload-can-share-storage-p
dataoffsetbytes-per-rowbytes-per-texelsize

True when data's own storage is already the exact upload image.

Sharing needs a simple array -- displaced or adjustable storage is not one contiguous block -- starting at the beginning, with no padding between rows.

declare
ignorabledataoffsetbytes-per-rowbytes-per-texelsize
#+sbcl
and
typepdata'
simple-array
unsigned-byte32
eql4bytes-per-texel
zeropoffset
=bytes-per-row
*bytes-per-texel
firstsize
#-sbclnil
#+sbcl
defunshare-metal-upload-storage
texturedatawidthheightbytes-per-row

Upload data's own pinned storage into texture without staging a copy.

sb-sys:with-pinned-objects
data
luv.metal:replace-metal-texture-region
metal-native-objecttexture
widthheight
sb-sys:vector-sap
sb-ext:array-storage-vectordata
bytes-per-row
defmethodmetal-native-teardown-closure
let*
device
metal-texture-devicetexture
residency-set
metal-device-residency-setdevice
native
metal-native-objecttexture
resident-p
metal-texture-resident-ptexture
owned-p
metal-texture-owned-ptexture
owner
metal-texture-external-ownertexture
apply#'make-gpu-retirement-sequence
append
whenresident-p
list
lambda
unless
metal-device-residency-retired-pdevice
lambda
unless
metal-device-residency-retired-pdevice
whenowner
list

New importers can couple native-plane release to their own retained lifetime with a callback. Raw CF owners remain source-compatible.

lambda
if
functionpowner
funcallowner
cffi:foreign-funcall"CFRelease":pointerowner:void
defmethoddestroy
unless
metal-object-destroyed-ptexture
metal-destroy-or-defertexture
metal-texture-devicetexture
values
defmethoddestroy
unless
metal-object-destroyed-pscaler

The scaler's native properties retain frame textures. Enqueue its teardown first, then its private exposure texture, at the same GPU completion frontier.

metal-destroy-or-deferscaler
metal-temporal-scaler-devicescaler
destroy
metal-temporal-scaler-exposure-texturescaler
values
defmethoddestroy
setf
metal-object-destroyed-pview
t
values
defmethoddestroy
unless
metal-object-destroyed-psampler
metal-destroy-or-defersampler
metal-sampler-devicesampler
values
defmethoddestroy
setf
metal-object-destroyed-playout
t
values
defmethoddestroy
setf
metal-object-destroyed-pbind-group
t
values
defunmetal-document-for-shader-module
descriptor
let
code
shader-module-descriptor-codedescriptor
language
shader-module-descriptor-languagedescriptor
caselanguage
:mathematical
unless
error'gpu-request-error:operation:create-shader-module:descriptordescriptor:reason:invalid-mathematical-shader:detailscode
:msl
unless
error'gpu-request-error:operation:create-shader-module:descriptordescriptor:reason:invalid-msl-document:detailscode
code
otherwise
error'gpu-request-error:operation:create-shader-module:descriptordescriptor:reason:unsupported-shader-language:detailslanguage
defmethodcreate
descriptorshader-module-descriptor

Lower a mathematical shader directly to MSL and compile it on device.

The complete MSL document remains attached to the returned module so native diagnostics and graph provenance stay inspectable. This is the device-owned compiler boundary of #58IDSR.

ensure-live-metal-objectdevice:create-shader-module
let*
source
luv.msl:msl-document-sourcedocument
entry-point
luv.msl:msl-entry-point-name
luv.msl:msl-document-entry-pointdocument
stage
luv.msl:msl-entry-point-stage
luv.msl:msl-document-entry-pointdocument
multiple-value-bind
librarydiagnostic
luv.metal:compile-metal-4-library
metal-device-compilerdevice
source:name
or
gpu-descriptor-labeldescriptor
entry-point
unlesslibrary
error'metal-gpu-error:operation:create-shader-module:reason:library-compilation-failed:details
list:diagnosticdiagnostic:documentdocument
let
completed-pnil
unwind-protect
luv.objective-c:with-autorelease-pool
let
unlessfunction
error'metal-gpu-error:operation:create-shader-module:reason:entry-point-not-found:details
list:entry-pointentry-point:documentdocument
unwind-protect
let
unless
=actual-typeexpected-type
error'metal-gpu-error:operation:create-shader-module:reason:entry-point-stage-mismatch:details
list:entry-pointentry-point:expectedexpected-type:actualactual-type
let
module
make-instance'metal-gpu-shader-module:label
gpu-descriptor-labeldescriptor
:native-objectlibrary:devicedevice:documentdocument:entry-pointentry-point:function-typeactual-type
setfcompleted-pt
module
defmethoddestroy
unless
metal-object-destroyed-pmodule
metal-destroy-or-defermodule
metal-shader-module-devicemodule
values
defunreject-metal-gpu-request
descriptorreason&optionaldetails
error'gpu-request-error:operation:create:descriptordescriptor:reasonreason:detailsdetails
defunensure-metal-object-device
objectactual-deviceexpected-deviceoperation
unless
eqactual-deviceexpected-device
error'gpu-device-mismatch-error:objectobject:operationoperation:expected-deviceexpected-device:actual-deviceactual-device
object
defunnormalize-metal-vertex-buffers
descriptorbuffers
unless
listpbuffers
reject-metal-gpu-requestdescriptor:invalid-vertex-buffersbuffers
loopforbufferinbuffersforbindingfrom0forstride=
getfbuffer:array-stride
forstep-mode=
or
getfbuffer:step-mode
:vertex
forattributes=
getfbuffer:attributes
unless
and
typepstride'
unsigned-byte32
pluspstride
memberstep-mode'
:vertex:instance
listpattributes
attributes
every
lambda
attribute
and
typep
getfattribute:shader-location
'
unsigned-byte32
typep
getfattribute:offset
'
unsigned-byte32
member
getfattribute:format
'
:float32x2:float32x3:float32x4
attributes
do
reject-metal-gpu-requestdescriptor:invalid-vertex-bufferbuffer
collect
list:bindingbinding:array-stridestride:step-modestep-mode:attributesattributes
defunmetal-render-pipeline-pixel-format
formatdescriptor
andformat
defmethodcreate
descriptorrender-pipeline-descriptor

Link device-owned vertex and fragment modules into a Metal 4 pipeline.

ensure-live-metal-objectdevice:create-render-pipeline
let*
layout
render-pipeline-descriptor-layoutdescriptor
vertex
render-pipeline-descriptor-vertexdescriptor
fragment
render-pipeline-descriptor-fragmentdescriptor
vertex-module
getfvertex:module
fragment-module
getffragment:module
vertex-entry-point
andvertex-module
or
getfvertex:entry-point
metal-shader-module-entry-pointvertex-module
fragment-entry-point
andfragment-module
or
getffragment:entry-point
metal-shader-module-entry-pointfragment-module
vertex-buffers
normalize-metal-vertex-buffersdescriptor
or
getfvertex:buffers
nil
targets
getffragment:targets
formats
mapcar
lambda
target
metal-render-pipeline-pixel-format
getftarget:format
descriptor
targets
blends
mapcar
lambda
target
getftarget:blend
targets
primitive
render-pipeline-descriptor-primitivedescriptor
topology
or
getfprimitive:topology
:triangle-list
depth-stencil
render-pipeline-descriptor-depth-stencildescriptor
depth-format
anddepth-stencil
getfdepth-stencil:format
depth-compare
anddepth-stencil
getfdepth-stencil:depth-compare
depth-write-enabled
anddepth-stencil
getfdepth-stencil:depth-write-enabled
unless
and
typepvertex-module'metal-gpu-shader-module
=
metal-shader-module-function-typevertex-module
luv.metal:+function-type-vertex+
string=vertex-entry-point
metal-shader-module-entry-pointvertex-module
or
and
typepfragment-module'metal-gpu-shader-module
=
metal-shader-module-function-typefragment-module
luv.metal:+function-type-fragment+
string=fragment-entry-point
metal-shader-module-entry-pointfragment-module
<=1
lengthformats
8
every#'identityformats
every
lambda
blend
memberblend'
nil:premultiplied-alpha
blends
and
nullfragment-module
nullformats
depth-stencil
membertopology'
:triangle-list:triangle-strip
or
nulldepth-stencil
and
eqdepth-format:depth32-float
memberdepth-compare'
:never:less:equal:less-or-equal:greater:not-equal:greater-or-equal:always
reject-metal-gpu-requestdescriptor:unsupported-metal-render-pipeline
list:layoutlayout:topologytopology:depth-stencildepth-stencil
ensure-metal-object-devicevertex-module
metal-shader-module-devicevertex-module
device:create-render-pipeline
whenlayout
ensure-metal-object-devicelayout
metal-bind-group-layout-devicelayout
device:create-render-pipeline
whenfragment-module
ensure-metal-object-devicefragment-module
metal-shader-module-devicefragment-module
device:create-render-pipeline
let
pipeline-statenil
depth-statenil
completed-pnil
unwind-protect
progn
multiple-value-bind
pipelinediagnostic
luv.metal:compile-metal-4-render-pipeline
metal-device-compilerdevice
metal-native-objectvertex-module
vertex-entry-point
andfragment-module
metal-native-objectfragment-module
fragment-entry-pointvertex-buffersformatsluv.metal:+primitive-topology-class-triangle+:depth-format
anddepth-format
metal-resource-pixel-formatdepth-formatdescriptor
:blendsblends:label
gpu-descriptor-labeldescriptor
unlesspipeline
error'metal-gpu-error:operation:create-render-pipeline:reason:pipeline-compilation-failed:detailsdiagnostic
setfpipeline-statepipeline
whendepth-stencil
setfdepth-state
luv.metal:new-metal-depth-stencil-state
metal-native-objectdevice
depth-write-enabled:label
and
gpu-descriptor-labeldescriptor
formatnil"~A depth state"
gpu-descriptor-labeldescriptor
unlessdepth-state
error'metal-gpu-error:operation:create-render-pipeline:reason:depth-state-creation-failed
let
pipeline
make-instance'metal-gpu-render-pipeline:label
gpu-descriptor-labeldescriptor
:native-objectpipeline-state:devicedevice:layoutlayout:vertex-buffersvertex-buffers:primitive-topologytopology:fragment-p
not
nullfragment-module
:depth-formatdepth-format:depth-stencil-statedepth-state
setfcompleted-pt
pipeline
unlesscompleted-p
whenpipeline-state
defunmetal-shader-module-workgroup-size
module
luv.shader:shader-specification-workgroup-size
luv.msl:msl-document-specification
metal-shader-module-documentmodule
defmethodcreate
descriptormesh-render-pipeline-descriptor

Link task, mesh, and fragment modules into a Metal 4 mesh pipeline.

ensure-live-metal-objectdevice:create-mesh-render-pipeline
let*
layout
mesh-render-pipeline-descriptor-layoutdescriptor
task
mesh-render-pipeline-descriptor-taskdescriptor
mesh
mesh-render-pipeline-descriptor-meshdescriptor
fragment
mesh-render-pipeline-descriptor-fragmentdescriptor
task-module
getftask:module
mesh-module
getfmesh:module
fragment-module
getffragment:module
task-entry-point
andtask-module
or
getftask:entry-point
metal-shader-module-entry-pointtask-module
mesh-entry-point
andmesh-module
or
getfmesh:entry-point
metal-shader-module-entry-pointmesh-module
fragment-entry-point
andfragment-module
or
getffragment:entry-point
metal-shader-module-entry-pointfragment-module
targets
getffragment:targets
format
and
=
lengthtargets
1
getf
firsttargets
:format
blend
getf
firsttargets
:blend
max-mesh-workgroups
mesh-render-pipeline-descriptor-max-mesh-workgroupsdescriptor
depth-stencil
mesh-render-pipeline-descriptor-depth-stencildescriptor
depth-format
anddepth-stencil
getfdepth-stencil:format
depth-compare
anddepth-stencil
getfdepth-stencil:depth-compare
depth-write-enabled
anddepth-stencil
getfdepth-stencil:depth-write-enabled
unless
and
or
nulltask-module
and
typeptask-module'metal-gpu-shader-module
=
metal-shader-module-function-typetask-module
luv.metal:+function-type-object+
string=task-entry-point
metal-shader-module-entry-pointtask-module
typepmesh-module'metal-gpu-shader-module
=
metal-shader-module-function-typemesh-module
luv.metal:+function-type-mesh+
string=mesh-entry-point
metal-shader-module-entry-pointmesh-module
typepfragment-module'metal-gpu-shader-module
=
metal-shader-module-function-typefragment-module
luv.metal:+function-type-fragment+
string=fragment-entry-point
metal-shader-module-entry-pointfragment-module
format
memberblend'
nil:premultiplied-alpha
typepmax-mesh-workgroups'
integer1#.most-positive-fixnum
or
nulldepth-stencil
and
eqdepth-format:depth32-float
memberdepth-compare'
:never:less:equal:less-or-equal:greater:not-equal:greater-or-equal:always
reject-metal-gpu-requestdescriptor:unsupported-metal-mesh-render-pipeline
list:layoutlayout:depth-stencildepth-stencil:max-mesh-workgroupsmax-mesh-workgroups
whenlayout
ensure-metal-object-devicelayout
metal-bind-group-layout-devicelayout
device:create-mesh-render-pipeline
dolist
module
removenil
listtask-modulemesh-modulefragment-module
ensure-metal-object-devicemodule
metal-shader-module-devicemodule
device:create-mesh-render-pipeline
let*
task-workgroup-size
mesh-workgroup-size
pipeline-statenil
depth-statenil
completed-pnil
unwind-protect
progn
multiple-value-bind
pipelinediagnostic
luv.metal:compile-metal-4-mesh-render-pipeline
metal-device-compilerdevice
andtask-module
metal-native-objecttask-module
task-entry-pointtask-workgroup-size
metal-native-objectmesh-module
mesh-entry-pointmesh-workgroup-size
metal-native-objectfragment-module
fragment-entry-pointmax-mesh-workgroups:blendblend:label
gpu-descriptor-labeldescriptor
unlesspipeline
error'metal-gpu-error:operation:create-mesh-render-pipeline:reason:pipeline-compilation-failed:detailsdiagnostic
setfpipeline-statepipeline
whendepth-stencil
setfdepth-state
luv.metal:new-metal-depth-stencil-state
metal-native-objectdevice
depth-write-enabled:label
and
gpu-descriptor-labeldescriptor
formatnil"~A depth state"
gpu-descriptor-labeldescriptor
unlessdepth-state
error'metal-gpu-error:operation:create-mesh-render-pipeline:reason:depth-state-creation-failed
let
pipeline
make-instance'metal-gpu-mesh-render-pipeline:label
gpu-descriptor-labeldescriptor
:native-objectpipeline-state:devicedevice:layoutlayout:vertex-buffersnil:primitive-topology:triangle-list:fragment-pt:depth-formatdepth-format:depth-stencil-statedepth-state:task-workgroup-sizetask-workgroup-size:mesh-workgroup-sizemesh-workgroup-size
setfcompleted-pt
pipeline
unlesscompleted-p
whenpipeline-state
defmethoddestroy
unless
metal-object-destroyed-ppipeline
metal-destroy-or-deferpipeline
metal-render-pipeline-devicepipeline
values
defmethodmetal-native-teardown-closure
let
depth-state
metal-render-pipeline-depth-stencil-statepipeline
native
metal-native-objectpipeline
defunprobe-metal-shader-library
specification

Compile specification through a fresh Metal device and return bounded evidence.

let
devicenil
modulenil
evidencenil
unwind-protect
progn
setfdevicemodule
createdevice
make-shader-module-descriptor:label"luvcraft MSL probe":language:mathematical:codespecification
evidence
list:device:compiler
luv.objective-c:objective-c-object-protocol-name
metal-device-compilerdevice
:library
luv.objective-c:objective-c-object-protocol-name
metal-native-objectmodule
:stage
luv.msl:msl-entry-point-stage
luv.msl:msl-document-entry-point
metal-shader-module-documentmodule
:entry-point
metal-shader-module-entry-pointmodule
:source-length
length
luv.msl:msl-document-source
metal-shader-module-documentmodule
evidence
whenmodule
destroymodule
whendevice
destroydevice
defunprobe-metal-render-pipeline
vertex-specificationfragment-specificationvertex-buffers&key
target-format:bgra8-unorm
primitive'
:topology:triangle-list
depth-stencil'
:format:depth32-float:depth-write-enabledt:depth-compare:less

Link two mathematical shaders on a fresh Metal device and return evidence.

let
devicenil
vertex-modulenil
fragment-modulenil
pipelinenil
unwind-protect
progn
setfdevicevertex-module
createdevice
make-shader-module-descriptor:label"Metal pipeline probe vertex":language:mathematical:codevertex-specification
fragment-module
createdevice
make-shader-module-descriptor:label"Metal pipeline probe fragment":language:mathematical:codefragment-specification
pipeline
createdevice
make-render-pipeline-descriptor:label"Metal 4 render pipeline probe":layoutnil:vertex`
:module,vertex-module:buffers,vertex-buffers
:fragment`
:module,fragment-module:targets
:format,target-format
:primitiveprimitive:depth-stencildepth-stencil
list:device:vertex-entry-point
metal-shader-module-entry-pointvertex-module
:fragment-entry-point
metal-shader-module-entry-pointfragment-module
:pipeline
luv.objective-c:objective-c-object-protocol-name
metal-native-objectpipeline
:depth-state
and
metal-render-pipeline-depth-stencil-statepipeline
luv.objective-c:objective-c-object-protocol-name
metal-render-pipeline-depth-stencil-statepipeline
:vertex-buffers
metal-render-pipeline-vertex-bufferspipeline
whenpipeline
destroypipeline
whenfragment-module
destroyfragment-module
whenvertex-module
destroyvertex-module
whendevice
destroydevice
defunensure-metal-render-pass-state
passoperation
unless
eq:encoding
metal-render-pass-statepass
error'gpu-invalid-state-error:objectpass:operationoperation:state
metal-render-pass-statepass
:expected-state:encoding
pass
defunmetal-attachment-texture
view
etypecaseview
metal-gpu-texture-view
gpu-texture-view-textureview
defunnormalize-metal-color-attachment
devicedescriptorattachment
whenattachment
let*
view
getfattachment:view
load-op
or
getfattachment:load-op
:clear
store-op
or
getfattachment:store-op
:store
clear-value
or
getfattachment:clear-value
0.00.00.01.0
unless
andtexture
member:render-attachment
gpu-texture-usagetexture
memberload-op'
:clear:load
memberstore-op'
:store:discard
every#'realpclear-value
reject-metal-gpu-requestdescriptor:unsupported-metal-color-attachmentattachment
ensure-metal-object-devicetexture
metal-texture-devicetexture
device:begin-render-pass
listtextureload-opstore-opclear-value
defunnormalize-metal-depth-attachment
devicedescriptorattachment
whenattachment
let*
view
getfattachment:view
load-op
or
getfattachment:depth-load-op
:clear
store-op
or
getfattachment:depth-store-op
:discard
clear-depth
or
getfattachment:depth-clear-value
1.0
unless
andtexture
eq:depth32-float
gpu-texture-formattexture
member:render-attachment
gpu-texture-usagetexture
memberload-op'
:clear:load
memberstore-op'
:store:discard
realpclear-depth
<=0clear-depth1
reject-metal-gpu-requestdescriptor:unsupported-metal-depth-attachmentattachment
ensure-metal-object-devicetexture
metal-texture-devicetexture
device:begin-render-pass
listtextureload-opstore-opclear-depth
defmethodbegin-render-pass
descriptor

Begin a Metal 4 color, depth, or color-and-depth pass.

ensure-metal-command-encoder-stateencoder:begin-render-pass
ensure-no-active-metal-passencoder:begin-render-pass
let*
attachments
render-pass-descriptor-color-attachmentsdescriptor
depth-attachment
render-pass-descriptor-depth-stencil-attachmentdescriptor
device
metal-command-encoder-deviceencoder
unless
and
listpattachments
<=
lengthattachments
8
orattachmentsdepth-attachment
reject-metal-gpu-requestdescriptor:unsupported-metal-render-pass
list:color-attachmentsattachments:depth-stencildepth-attachment
let*
colors
mapcar
lambda
attachment
normalize-metal-color-attachmentdevicedescriptorattachment
attachments
depth
normalize-metal-depth-attachmentdevicedescriptordepth-attachment
loopforcolorincolorsforattachmentinattachmentsdo
retain-metal-resourceencoder
firstcolor
let
view
getfattachment:view
whendepth
retain-metal-resourceencoder
firstdepth
let
view
getfdepth-attachment:view
let
sizes
append
mapcar
lambda
color
gpu-texture-size
firstcolor
colors
whendepth
list
gpu-texture-size
firstdepth
unless
every
lambda
size
equalsize
firstsizes
restsizes
reject-metal-gpu-requestdescriptor:mismatched-attachment-sizesizes
let
native-encoder
luv.metal:new-render-command-encoder
metal-encoder-command-bufferencoder
:color-attachments
mapcar
lambda
color
list
metal-native-object
firstcolor
fourthcolor
eq:clear
secondcolor
eq:store
thirdcolor
colors
:depth-texture
anddepth
metal-native-object
firstdepth
:clear-depth
anddepth
fourthdepth
:depth-clear-p
anddepth
eq:clear
seconddepth
:depth-store-p
anddepth
eq:store
thirddepth
unlessnative-encoder
error'metal-gpu-error:operation:begin-render-pass:reason:render-encoder-creation-failed
let
barrier
metal-encoder-pending-consumer-barrierencoder
whenbarrier
destructuring-bind
after-queue-stagesbefore-stagesvisibility-options
barrier
luv.metal:barrier-after-queue-stagesnative-encoderafter-queue-stagesbefore-stagesvisibility-options
setf
metal-encoder-pending-consumer-barrierencoder
nil
let
pass
make-instance'metal-render-pass-encoder:ownerencoder:native-encodernative-encoder:label
gpu-descriptor-labeldescriptor
setf
metal-encoder-active-passencoder
pass
pass
defmethodencode
commandgpu-prepare-texture-command
ensure-metal-command-encoder-stateencoder:prepare-texture
ensure-no-active-metal-passencoder:prepare-texture
let
texture
gpu-prepare-texture-command-texturecommand
usage
gpu-prepare-texture-command-usagecommand
device
metal-command-encoder-deviceencoder
unless
and
typeptexture'metal-gpu-texture
memberusage
gpu-texture-usagetexture
equsage:texture-binding
reject-metal-gpu-requestcommand:unsupported-texture-preparation
list:texturetexture:usageusage
ensure-live-metal-objecttexture:prepare-texture
ensure-metal-object-devicetexture
metal-texture-devicetexture
device:prepare-texture

Metal 4 queues do not perform ordinary MTLResource hazard tracking. Coalesce every texture produced by the preceding pass into the one producer-to-fragment barrier installed on the following encoder. The command encoder retains each concrete resource independently below.

unless
metal-encoder-pending-consumer-barrierencoder
retain-metal-resourceencodertexture
encoder
defunensure-metal-temporal-scaler-device
scalerdeviceoperation
unless
reject-metal-gpu-requestscaler:incompatible-temporal-scaler
ensure-metal-object-devicescaler
metal-temporal-scaler-devicescaler
deviceoperation
scaler
defmethodencode
commandgpu-signal-temporal-scaler-command
ensure-metal-render-pass-statepass:signal-temporal-scaler-inputs
let*
owner
metal-render-pass-ownerpass
device
metal-command-encoder-deviceowner
scaler
gpu-signal-temporal-scaler-command-scalercommand
ensure-metal-temporal-scaler-devicescalerdevice:signal-temporal-scaler-inputs
luv.metal:update-metal-fence
metal-render-pass-native-encoderpass
metal-temporal-scaler-fencescaler
luv.metal:+stage-fragment+
command
defmethodencode
commandgpu-wait-temporal-scaler-command
ensure-metal-render-pass-statepass:wait-temporal-scaler-output
let*
owner
metal-render-pass-ownerpass
device
metal-command-encoder-deviceowner
scaler
gpu-wait-temporal-scaler-command-scalercommand
ensure-metal-temporal-scaler-devicescalerdevice:wait-temporal-scaler-output
luv.metal:wait-for-metal-fence
metal-render-pass-native-encoderpass
metal-temporal-scaler-fencescaler
luv.metal:+stage-fragment+
command
defmethodencode
commandgpu-temporal-scale-command
ensure-no-active-metal-passencoder:temporal-scale
let*
device
metal-command-encoder-deviceencoder
scaler
gpu-temporal-scale-command-scalercommand
color
gpu-temporal-scale-command-colorcommand
depth
gpu-temporal-scale-command-depthcommand
motion
gpu-temporal-scale-command-motioncommand
output
gpu-temporal-scale-command-outputcommand
jitter
gpu-temporal-scale-command-jittercommand
reset-p
gpu-temporal-scale-command-reset-pcommand
ensure-metal-temporal-scaler-devicescalerdevice:temporal-scale
unless
and
every
lambda
texture
and
typeptexture'metal-gpu-texture
eq
metal-texture-devicetexture
device
listcolordepthmotionoutput
equal
gpu-texture-sizecolor
gpu-temporal-scaler-input-sizescaler
equal
gpu-texture-sizedepth
gpu-temporal-scaler-input-sizescaler
equal
gpu-texture-sizemotion
gpu-temporal-scaler-input-sizescaler
equal
gpu-texture-sizeoutput
gpu-temporal-scaler-output-sizescaler
eq
gpu-texture-formatcolor
metal-temporal-scaler-color-formatscaler
eq
gpu-texture-formatdepth
metal-temporal-scaler-depth-formatscaler
eq
gpu-texture-formatmotion
metal-temporal-scaler-motion-formatscaler
eq
gpu-texture-formatoutput
metal-temporal-scaler-output-formatscaler
subsetp
gpu-temporal-scaler-color-usagescaler
gpu-texture-usagecolor
subsetp
gpu-temporal-scaler-depth-usagescaler
gpu-texture-usagedepth
subsetp
gpu-temporal-scaler-motion-usagescaler
gpu-texture-usagemotion
subsetp
gpu-temporal-scaler-output-usagescaler
gpu-texture-usageoutput
typepjitter'sequence
=2
lengthjitter
every#'realpjitter
memberreset-p'
nilt
reject-metal-gpu-requestcommand:invalid-temporal-scale-frame
dolist
texture
listcolordepthmotionoutput
ensure-live-metal-objecttexture:temporal-scale
retain-metal-resourceencodertexture
let
exposure
metal-temporal-scaler-exposure-texturescaler
luv.metal:configure-metal-temporal-scaler
metal-native-objectscaler
metal-native-objectcolor
metal-native-objectdepth
metal-native-objectmotion
metal-native-objectexposure
metal-native-objectoutput
first
gpu-temporal-scaler-input-sizescaler
second
gpu-temporal-scaler-input-sizescaler
eltjitter0
eltjitter1
reset-p
luv.metal:encode-metal-temporal-scaler
metal-native-objectscaler
metal-encoder-command-bufferencoder
setf
metal-encoder-encoded-pencoder
t
command
defunrelease-metal-render-pass-argument-table
pass
let
table
metal-render-pass-argument-tablepass
whentable

MTL4RenderCommandEncoder snapshots table contents at each draw.

setf
metal-render-pass-argument-tablepass
nil
defunmetal-layout-binding-count
let
bindings
loopforentryin
andlayout
metal-bind-group-layout-entrieslayout
when
eqtype
getfentry:type
collect
getfentry:binding
ifbindings
1+
reduce#'maxbindings
0
defunconfigure-metal-pass-bind-group
passbind-group
let*
pipeline
metal-render-pass-pipelinepass
layout
andpipeline
metal-render-pipeline-layoutpipeline
table
metal-render-pass-argument-tablepass
owner
metal-render-pass-ownerpass
unlesspipeline
error'gpu-invalid-state-error:objectpass:operation:set-bind-group:state:no-pipeline:expected-state:pipeline-bound
unless
and
typepbind-group'metal-gpu-bind-group
eqlayout
metal-bind-group-layoutbind-group
reject-metal-gpu-requestbind-group:incompatible-pipeline-layoutpipeline
dolist
layout-entry
metal-bind-group-layout-entrieslayout
let*
binding
getflayout-entry:binding
entry
findbinding
metal-bind-group-entriesbind-group
:key
lambda
candidate
getfcandidate:binding
resource
getfentry:resource
when
retain-metal-resourceowner
gpu-texture-view-textureresource
ecase
getflayout-entry:type
:uniform-buffer:storage-buffer
:texture
luv.metal:set-metal-argument-table-texturetable
luv.metal:metal-texture-resource-id
metal-native-object
gpu-texture-view-textureresource
binding
retain-metal-resource
metal-render-pass-ownerpass
bind-group
setf
metal-render-pass-bind-grouppass
bind-group
bind-group
defmethodencode
commandgpu-set-pipeline-command
let*
pipeline
gpu-set-pipeline-command-pipelinecommand
owner
metal-render-pass-ownerpass
device
metal-command-encoder-deviceowner
unless
reject-metal-gpu-requestcommand:incompatible-pipelinepipeline
ensure-metal-object-devicepipeline
metal-render-pipeline-devicepipeline
device:set-pipeline
clrhash
metal-render-pass-vertex-bindingspass
let
vertex-buffers
metal-render-pipeline-vertex-bufferspipeline
let*
layout
metal-render-pipeline-layoutpipeline
buffer-count
max
ifvertex-buffers
1+
reduce#'maxvertex-buffers:key
lambda
buffer
getfbuffer:binding
0
when
plusp
+buffer-counttexture-countsampler-count
multiple-value-bind
tablediagnostic
luv.metal:new-metal-4-argument-table
metal-native-objectdevice
buffer-count:max-texture-counttexture-count:max-sampler-countsampler-count:label
formatnil"~A render arguments"
or
gpu-object-labelpipeline
"Metal pipeline"
:attribute-strides-pt
unlesstable
error'metal-gpu-error:operation:set-pipeline:reason:argument-table-creation-failed:detailsdiagnostic
setf
metal-render-pass-argument-tablepass
table
luv.metal:set-metal-render-pipeline
metal-render-pass-native-encoderpass
metal-native-objectpipeline
luv.metal:set-metal-depth-stencil-state
metal-render-pass-native-encoderpass
metal-render-pipeline-depth-stencil-statepipeline
setf
metal-render-pass-pipelinepass
pipeline
let
bind-group
metal-render-pass-bind-grouppass
whenbind-group
if
eq
metal-render-pipeline-layoutpipeline
metal-bind-group-layoutbind-group
setf
metal-render-pass-bind-grouppass
nil
command
defmethodencode
commandgpu-set-bind-group-command
unless
zerop
gpu-set-bind-group-command-indexcommand
reject-metal-gpu-requestcommand:unsupported-bind-group-index
gpu-set-bind-group-command-indexcommand
let
pipeline
metal-render-pass-pipelinepass
bind-group
gpu-set-bind-group-command-bind-groupcommand
unlesspipeline
error'gpu-invalid-state-error:objectpass:operation:set-bind-group:state:no-pipeline:expected-state:pipeline-bound
unless
typepbind-group'metal-gpu-bind-group
reject-metal-gpu-requestcommand:incompatible-bind-groupbind-group
ensure-metal-object-devicebind-group
metal-bind-group-devicebind-group
metal-render-pipeline-devicepipeline
:set-bind-group
command
defunmetal-pipeline-vertex-buffer-at
pipelineslot
findslot
metal-render-pipeline-vertex-bufferspipeline
:key
lambda
buffer
getfbuffer:binding
defmethodencode
commandgpu-set-vertex-buffer-command
ensure-metal-render-pass-statepass:set-vertex-buffer
let*
pipeline
metal-render-pass-pipelinepass
slot
gpu-set-vertex-buffer-command-slotcommand
buffer
gpu-set-vertex-buffer-command-buffercommand
offset
gpu-set-vertex-buffer-command-offsetcommand
unlesspipeline
error'gpu-invalid-state-error:objectpass:operation:set-vertex-buffer:state:no-pipeline:expected-state:pipeline-bound
unlesslayout
reject-metal-gpu-requestcommand:unsupported-vertex-buffer-slotslot
unless
typepbuffer'metal-gpu-buffer
reject-metal-gpu-requestcommand:incompatible-vertex-bufferbuffer
ensure-metal-object-devicebuffer
metal-buffer-devicebuffer
metal-render-pipeline-devicepipeline
:set-vertex-buffer
unless
member:vertex
gpu-buffer-usagebuffer
reject-metal-gpu-requestcommand:buffer-missing-vertex-usagebuffer
unless
and
typepoffset'
unsigned-byte64
zerop
modoffset4
<offset
gpu-buffer-sizebuffer
reject-metal-gpu-requestcommand:invalid-vertex-buffer-offsetoffset
luv.metal:set-metal-argument-table-buffer
metal-render-pass-argument-tablepass
+
luv.metal:metal-buffer-gpu-address
metal-native-objectbuffer
offset
getflayout:array-stride
slot
retain-metal-resource
metal-render-pass-ownerpass
buffer
setf
gethashslot
metal-render-pass-vertex-bindingspass
buffer
command
defmethodencode
commandgpu-set-scissor-command
let
values
list
gpu-set-scissor-command-xcommand
gpu-set-scissor-command-ycommand
gpu-set-scissor-command-widthcommand
gpu-set-scissor-command-heightcommand
unless
every
lambda
value
typepvalue'
unsigned-byte64
values
reject-metal-gpu-requestcommand:invalid-scissor-rectanglevalues
destructuring-bindvalues
luv.metal:set-metal-scissor-rect
metal-render-pass-native-encoderpass
list'luv.metal::xx'luv.metal::yy'luv.metal::widthwidth'luv.metal::heightheight
command
defunmetal-primitive-type
pipeline
ecase
metal-render-pipeline-primitive-topologypipeline
defmethodencode
commandgpu-draw-command
let
pipeline
metal-render-pass-pipelinepass
unlesspipeline
error'gpu-invalid-state-error:objectpass:operation:draw:state:no-pipeline:expected-state:pipeline-bound
when
reject-metal-gpu-requestcommand:vertex-draw-with-mesh-pipeline
when
and
metal-render-pipeline-layoutpipeline
null
metal-render-pass-bind-grouppass
error'gpu-invalid-state-error:objectpass:operation:draw:state:bind-group-missing:expected-state:pipeline-bind-group-and-vertex-buffers-bound
dolist
layout
metal-render-pipeline-vertex-bufferspipeline
unless
gethash
getflayout:binding
metal-render-pass-vertex-bindingspass
error'gpu-invalid-state-error:objectpass:operation:draw:state:vertex-buffer-missing:expected-state:all-vertex-buffers-bound
let
vertex-count
gpu-draw-command-vertex-countcommand
instance-count
gpu-draw-command-instance-countcommand
first-vertex
gpu-draw-command-first-vertexcommand
first-instance
gpu-draw-command-first-instancecommand
unless
and
typepvertex-count'
integer1*
typepinstance-count'
integer1*
typepfirst-vertex'
unsigned-byte64
typepfirst-instance'
unsigned-byte64
reject-metal-gpu-requestcommand:invalid-draw-range
when
metal-render-pass-argument-tablepass
luv.metal:set-metal-render-argument-table
metal-render-pass-native-encoderpass
metal-render-pass-argument-tablepass
logiorluv.metal:+render-stage-vertex+
if
metal-render-pipeline-fragment-ppipeline
luv.metal:+render-stage-fragment+0
luv.metal:draw-metal-primitives
metal-render-pass-native-encoderpass
first-vertexvertex-countinstance-countfirst-instance
command
defmethodencode
commandgpu-draw-indexed-command
let
pipeline
metal-render-pass-pipelinepass
index-buffer
gpu-draw-indexed-command-index-buffercommand
unlesspipeline
error'gpu-invalid-state-error:objectpass:operation:draw-indexed:state:no-pipeline:expected-state:pipeline-bound
when
reject-metal-gpu-requestcommand:indexed-draw-with-mesh-pipeline
when
and
metal-render-pipeline-layoutpipeline
null
metal-render-pass-bind-grouppass
error'gpu-invalid-state-error:objectpass:operation:draw-indexed:state:bind-group-missing:expected-state:pipeline-bind-group-and-vertex-buffers-bound
dolist
layout
metal-render-pipeline-vertex-bufferspipeline
unless
gethash
getflayout:binding
metal-render-pass-vertex-bindingspass
error'gpu-invalid-state-error:objectpass:operation:draw-indexed:state:vertex-buffer-missing:expected-state:all-vertex-buffers-bound
unless
typepindex-buffer'metal-gpu-buffer
reject-metal-gpu-requestcommand:incompatible-index-bufferindex-buffer
ensure-metal-object-deviceindex-buffer
metal-buffer-deviceindex-buffer
metal-render-pipeline-devicepipeline
:draw-indexed
unless
member:index
gpu-buffer-usageindex-buffer
error'gpu-usage-error:objectindex-buffer:operation:draw-indexed:required-usage:index:actual-usage
gpu-buffer-usageindex-buffer
let
index-count
gpu-draw-indexed-command-index-countcommand
instance-count
gpu-draw-indexed-command-instance-countcommand
first-index
gpu-draw-indexed-command-first-indexcommand
base-vertex
gpu-draw-indexed-command-base-vertexcommand
first-instance
gpu-draw-indexed-command-first-instancecommand
unless
and
typepindex-count'
integer1*
typepinstance-count'
integer1*
typepfirst-index'
unsigned-byte64
typepbase-vertex'
signed-byte64
typepfirst-instance'
unsigned-byte64
reject-metal-gpu-requestcommand:invalid-indexed-draw-range
multiple-value-bind
native-formatindex-size
metal-index-format
gpu-draw-indexed-command-index-formatcommand
let
offset
*first-indexindex-size
unless
<=
+offset
*index-countindex-size
gpu-buffer-sizeindex-buffer
reject-metal-gpu-requestcommand:index-buffer-range-exceeded
when
metal-render-pass-argument-tablepass
luv.metal:set-metal-render-argument-table
metal-render-pass-native-encoderpass
metal-render-pass-argument-tablepass
logiorluv.metal:+render-stage-vertex+
if
metal-render-pipeline-fragment-ppipeline
luv.metal:+render-stage-fragment+0
retain-metal-resource
metal-render-pass-ownerpass
index-buffer
luv.metal:draw-metal-indexed-primitives
metal-render-pass-native-encoderpass
index-countnative-format
+
luv.metal:metal-buffer-gpu-address
metal-native-objectindex-buffer
offset
*index-countindex-size
instance-countbase-vertexfirst-instance
command
defunmetal-size-value
size
destructuring-bindsize
defmethodencode
commandgpu-draw-mesh-command
let
pipeline
metal-render-pass-pipelinepass
unlesspipeline
error'gpu-invalid-state-error:objectpass:operation:draw-mesh:state:no-pipeline:expected-state:pipeline-bound
unless
reject-metal-gpu-requestcommand:mesh-draw-with-vertex-pipeline
when
and
metal-render-pipeline-layoutpipeline
null
metal-render-pass-bind-grouppass
error'gpu-invalid-state-error:objectpass:operation:draw-mesh:state:bind-group-missing:expected-state:pipeline-and-bind-group-bound
let
counts
list
gpu-draw-mesh-command-xcommand
gpu-draw-mesh-command-ycommand
gpu-draw-mesh-command-zcommand
unless
every
lambda
value
typepvalue'
integer1*
counts
reject-metal-gpu-requestcommand:invalid-mesh-draw-rangecounts
when
metal-render-pass-argument-tablepass
luv.metal:set-metal-render-argument-table
metal-render-pass-native-encoderpass
metal-render-pass-argument-tablepass
luv.metal:draw-metal-mesh-threadgroups
metal-render-pass-native-encoderpass
metal-size-value
or
metal-mesh-pipeline-task-workgroup-sizepipeline
'
111
metal-size-value
metal-mesh-pipeline-mesh-workgroup-sizepipeline
command
defmethodend-pass
let
owner
metal-render-pass-ownerpass
luv.metal:end-encoding
metal-render-pass-native-encoderpass
setf
metal-render-pass-statepass
:ended
metal-encoder-active-passowner
nil
metal-encoder-encoded-powner
t
values
defmethodencode
commandgpu-clear-texture-command
let
texture
gpu-clear-texture-command-texturecommand
color
gpu-clear-texture-command-colorcommand
unless
typeptexture'metal-gpu-texture
error'gpu-request-error:operation:encode:descriptorcommand:reason:foreign-texture
ensure-metal-object-devicetexture
metal-texture-devicetexture
metal-command-encoder-deviceencoder
:encode
unless
member:render-attachment
gpu-texture-usagetexture
reject-metal-gpu-requestcommand:texture-missing-render-usagetexture
unless
and
=
lengthcolor
4
every#'realpcolor
error'gpu-request-error:operation:encode:descriptorcommand:reason:invalid-clear-color:detailscolor
luv.metal:encode-clear-pass
metal-encoder-command-bufferencoder
metal-native-objecttexture
color
retain-metal-resourceencodertexture
setf
metal-encoder-encoded-pencoder
t
command
defconstant+metal-blit-read-producer-stages+"Metal stages whose texture writes can feed a subsequent blit read."
defunencode-metal-blit-read-barrier
native-encoder

Make earlier render and blit texture writes visible to a blit read.

MTL4CommandQueue ignores ordinary resource hazard tracking. A copy can consume either a render target or the destination of an earlier copy in this portable encoder, so both producer stages belong in the dependency.

defmethodencode
commandgpu-copy-texture-command
ensure-no-active-metal-passencoder:copy-texture
let
source
gpu-copy-texture-command-sourcecommand
destination
gpu-copy-texture-command-destinationcommand
unless
and
typepsource'metal-gpu-texture
typepdestination'metal-gpu-texture
equal
gpu-texture-sizesource
gpu-texture-sizedestination
eq
gpu-texture-formatsource
gpu-texture-formatdestination
member:copy-src
gpu-texture-usagesource
member:copy-dst
gpu-texture-usagedestination
reject-metal-gpu-requestcommand:incompatible-copy
listsourcedestination
let
device
metal-command-encoder-deviceencoder
ensure-metal-object-devicesource
metal-texture-devicesource
device:copy-texture
ensure-metal-object-devicedestination
metal-texture-devicedestination
device:copy-texture
let
native-encoder
luv.metal:compute-command-encoder
metal-encoder-command-bufferencoder
unlessnative-encoder
error'metal-gpu-error:operation:copy-texture:reason:compute-encoder-creation-failed
luv.metal:copy-metal-texturenative-encoder
metal-native-objectsource
metal-native-objectdestination
retain-metal-resourceencoderdestination
setf
metal-encoder-encoded-pencoder
t
command
defmethodencode
commandgpu-copy-texture-to-buffer-command
ensure-metal-command-encoder-stateencoder:copy-texture-to-buffer
ensure-no-active-metal-passencoder:copy-texture-to-buffer
let*
source
gpu-copy-texture-to-buffer-command-sourcecommand
destination
gpu-copy-texture-to-buffer-command-destinationcommand
size
and
typepsource'metal-gpu-texture
gpu-texture-sizesource
bytes-per-row
andsize
*4
firstsize
unless
andsize
member:copy-src
gpu-texture-usagesource
typepdestination'metal-gpu-buffer
member:copy-dst
gpu-buffer-usagedestination
member
gpu-texture-formatsource
'
:rgba8-unorm:rgba8-unorm-srgb:bgra8-unorm:bgra8-unorm-srgb
<=
*bytes-per-row
secondsize
gpu-buffer-sizedestination
reject-metal-gpu-requestcommand:unsupported-texture-readback
let
device
metal-command-encoder-deviceencoder
ensure-metal-object-devicesource
metal-texture-devicesource
device:copy-texture-to-buffer
ensure-metal-object-devicedestination
metal-buffer-devicedestination
device:copy-texture-to-buffer
let
native-encoder
luv.metal:compute-command-encoder
metal-encoder-command-bufferencoder
unlessnative-encoder
error'metal-gpu-error:operation:copy-texture-to-buffer:reason:compute-encoder-creation-failed
luv.metal:copy-metal-texture-to-buffernative-encoder
metal-native-objectsource
firstsize
secondsize
metal-native-objectdestination
bytes-per-row
retain-metal-resourceencoderdestination
setf
metal-encoder-encoded-pencoder
t
command