luv

Workshop wiki

tests.lisp

hal/vulkan/tests.lisp

system luv/test · 37 definitions · on GitHub

in-package#:luv.tests
deftestvulkan-temporal-motion-format-is-r16g16-sfloat
let
descriptor
luv:make-texture-descriptor:size'
44
:dimensions:2d:format:rg16-float:usage:render-attachment
ok
eq:r16g16-sfloat
luv::vulkan-gpu-format:rg16-floatdescriptor
ok
=83
cffi:foreign-enum-value'lvk::format:r16g16-sfloat
deftestvulkan-render-pass-cache-keys-the-whole-color-cohort
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
original-create
symbol-functioncreate-symbol
native-formats'
descriptor
luv:make-render-pass-descriptor:label"MRT cache probe"
unwind-protect
progn
setf
symbol-functioncreate-symbol
lambda
native-deviceformats&keydepth-formatdepth-store-op
declare
ignorenative-devicedepth-formatdepth-store-op
push
coerceformats'list
native-formats
list:render-pass
lengthnative-formats
let
first
luv::vulkan-render-pass-for-formatdevice'
:rgba16-float:rg16-float
descriptor
same
luv::vulkan-render-pass-for-formatdevice'
:rgba16-float:rg16-float
descriptor
reversed
luv::vulkan-render-pass-for-formatdevice'
:rg16-float:rgba16-float
descriptor
ok
eqfirstsame
ok
not
eqfirstreversed
ok
equal'
:r16g16-sfloat:r16g16b16a16-sfloat
:r16g16b16a16-sfloat:r16g16-sfloat
native-formats
setf
symbol-functioncreate-symbol
original-create
defclassvulkan-retirement-probe
attempts:initarg:attempts:readervulkan-retirement-probe-attempts
fail-p:initarg:fail-p:readervulkan-retirement-probe-fail-p
defmethodluv::vulkan-native-teardown-closure

Capture only the test's explicit state boxes, as a real Vulkan teardown captures raw handles rather than its public wrapper.

let
attempts
vulkan-retirement-probe-attemptsprobe
fail-p
vulkan-retirement-probe-fail-pprobe
luv::make-gpu-retirement-sequence
lambda
incf
firstattempts
lambda
incf
secondattempts
when
carfail-p
setf
carfail-p
nil
error"injected Vulkan retirement failure"
lambda
incf
thirdattempts
defunmake-vulkan-submit-probe-texture
devicehandle&keysemaphoresemaphore-state
semaphore-value0
submittedowner
layout:general
let
texture
make-instance'luv::vulkan-gpu-texture:label"Vulkan submit probe texture":size'
441
:usage'
:texture-binding
:dimensions:2d:format:r8-unorm:vk-format:r8-unorm:handlehandle:devicedevice:owned-pnil:layoutlayout:external-semaphoresemaphore:external-semaphore-statesemaphore-state:external-semaphore-valuesemaphore-value:external-ownerowner:external-submittedsubmitted
#+sbcl
sb-ext:cancel-finalizationtexture
texture
defunmake-vulkan-submit-probe-command-buffer
devicehandle&keyresourcestexturesfinal-layouts
let
command-buffer
make-instance'luv::vulkan-gpu-command-buffer:label"Vulkan submit probe command buffer":handlehandle:devicedevice:command-pool:fake-command-pool:initial-texture-layoutsnil:final-texture-layoutsfinal-layouts:texturestextures:resourcesresources:native-resourcesnil
#+sbcl
sb-ext:cancel-finalizationcommand-buffer
command-buffer
deftestvulkan-destroy-transfers-before-invalidation-and-retries
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:fake-queue:devicedevice:family0:timeline:fake-timeline
attempts
list000
fail-p
listt
probe
make-instance'vulkan-retirement-probe:handle:fake-resource:attemptsattempts:fail-pfail-p
original-frontier
symbol-functionfrontier-function
setf
luv::vulkan-device-queuedevice
queue
unwind-protect
progn

Keep this ownership test backend-free: queue maintenance sees a completed frontier without asking a Vulkan loader or device.

setf
symbol-functionfrontier-function
lambda
queue
declare
ignorequeue
0
handler-bind
luv::vulkan-destroy-or-deferprobedevice
lambda
ok
eqprobe
luv::gpu-retirement-entry-resource
first
luv::gpu-retirement-ledger-entries
luv::vulkan-queue-retirement-ledgerqueue
setf
luv::vulkan-object-destroyed-pprobe
t
#+sbcl
sb-ext:cancel-finalizationprobe
ok
luv::vulkan-object-destroyed-pprobe
ok
equal'
110
attempts
ok
=1
length
luv::gpu-retirement-ledger-entries
luv::vulkan-queue-retirement-ledgerqueue
ok
eqqueue
gethash
luv::vulkan-queue-retirement-ledgerqueue
luv::*gpu-retirement-ledger-custodians*

The cached production closure resumes at its failed native call.

ok
equal'
121
attempts
ok
null
luv::gpu-retirement-ledger-entries
luv::vulkan-queue-retirement-ledgerqueue
ok
not
nth-value1
gethash
luv::vulkan-queue-retirement-ledgerqueue
luv::*gpu-retirement-ledger-custodians*
setf
symbol-functionfrontier-function
original-frontier
deftestvulkan-device-queues-non-gpu-native-owners-through-the-generic
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:fake-queue:devicedevice:family0:timeline:fake-timeline
original-frontier
symbol-functionfrontier-symbol
attempts0
invalidated-pnil
fail-pt
setf
luv::vulkan-device-queuedevice
queue
unwind-protect
progn
setf
symbol-functionfrontier-symbol
lambda
queue
declare
ignorequeue
0
handler-bind
luv::retire-gpu-native-ownerdevice:video-importer
lambda
incfattempts
whenfail-p
setffail-pnil
error"injected importer close failure"
lambda
setfinvalidated-pt
okinvalidated-p
ok
=1attempts
ok
equal'
:video-importer
mapcar#'luv::gpu-retirement-entry-resource
luv::gpu-retirement-ledger-entries
luv::vulkan-queue-retirement-ledgerqueue
ok
=2attempts
ok
null
luv::gpu-retirement-ledger-entries
luv::vulkan-queue-retirement-ledgerqueue
setf
symbol-functionfrontier-symbol
original-frontier
deftestvulkan-custodian-service-retires-an-unobserved-completion
let*
frontier0
native-submits0
original-frontier
symbol-functionfrontier-symbol
original-submit
symbol-functionsubmit-symbol
unwind-protect
progn
setf
symbol-functionfrontier-symbol
lambda
queue
declare
ignorequeue
frontier
symbol-functionsubmit-symbol
lambda
&restarguments
declare
ignorearguments
incfnative-submits
multiple-value-bind
weak-queueledgerattempts
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:fake-queue:devicedevice:family0:timeline:fake-timeline
attempts
list000
probe
make-instance'vulkan-retirement-probe:handle:fake-resource:attemptsattempts:fail-p
listnil
command-buffer
make-vulkan-submit-probe-command-bufferdevice:fake-command-buffer:resources
listprobe
setf
luv::vulkan-device-queuedevice
queue
#+sbcl
sb-ext:cancel-finalizationdevice
#+sbcl
sb-ext:cancel-finalizationqueue
ok
=1
luv:submitqueuecommand-buffer
luv::vulkan-destroy-or-deferprobedevice
lambda
setf
luv::vulkan-object-destroyed-pprobe
t
#+sbcl
sb-ext:cancel-finalizationprobe
ok
equal'
000
attempts
let
ledger
luv::vulkan-queue-retirement-ledgerqueue

From here no caller retains queue/device/resource access.

values#+sbcl
sb-ext:make-weak-pointerqueue
#-sbclnilledgerattempts
#+sbcl
progn
sb-ext:gc:fullt
ok
sb-ext:weak-pointer-valueweak-queue
setffrontier1
ok
=1native-submits
ok
equal'
111
attempts
ok
null
luv::gpu-retirement-ledger-entriesledger
setf
symbol-functionfrontier-symbol
original-frontier
symbol-functionsubmit-symbol
original-submit
deftestvulkan-custodian-service-does-no-ffi-after-admission-closes
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:fake-queue:devicedevice:family0:timeline:fake-timeline
original-frontier
symbol-functionfrontier-symbol
frontier-calls0
setf
luv::vulkan-device-queuedevice
queue
luv::vulkan-device-retiring-pdevice
t
luv::retain-gpu-retirement-ledger-custodian
luv::vulkan-queue-retirement-ledgerqueue
queue
unwind-protect
progn
setf
symbol-functionfrontier-symbol
lambda
queue
declare
ignorequeue
incffrontier-calls
0
ok
zeropfrontier-calls
setf
symbol-functionfrontier-symbol
original-frontier
deftestvulkan-submit-publishes-before-fallible-owner-callbacks-and-retries
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:fake-queue:devicedevice:family0:timeline:queue-timeline
state
luv::make-vulkan-external-semaphore-state:semaphore:external-timeline:value4:references2
first-attempts0
second-attempts0
fail-first-pt
first-values'
second-values'
first-texture
make-vulkan-submit-probe-texturedevice:plane-0:semaphore:external-timeline:semaphore-statestate:submitted
lambda
layoutvalue
declare
ignorelayout
incffirst-attempts
whenfail-first-p
setffail-first-pnil
error"injected plane callback failure"
pushvaluefirst-values
second-texture
make-vulkan-submit-probe-texturedevice:plane-1:semaphore:external-timeline:semaphore-statestate:submitted
lambda
layoutvalue
declare
ignorelayout
incfsecond-attempts
pushvaluesecond-values
command-buffer
make-vulkan-submit-probe-command-bufferdevice:fake-command-buffer:resources
listfirst-texturesecond-texture
:textures
listfirst-texturesecond-texture
:final-layouts
list
consfirst-texture:shader-read-only-optimal
conssecond-texture:shader-read-only-optimal
frontier0
native-submits0
native-waitsnil
native-signalsnil
original-frontier
symbol-functionfrontier-symbol
original-submit
symbol-functionsubmit-symbol
setf
luv::vulkan-device-queuedevice
queue
luv::vulkan-queue-external-semaphore-statesqueue
liststate
unwind-protect
progn
setf
symbol-functionfrontier-symbol
lambda
queue
declare
ignorequeue
frontier
symbol-functionsubmit-symbol
lambda
native-queuenative-command-buffers&keywait-semaphoressignal-semaphores
declare
ignorenative-queuenative-command-buffers
incfnative-submits
setfnative-waitswait-semaphoresnative-signalssignal-semaphores
ok
signals
luv:submitqueuecommand-buffer
'luv::vulkan-gpu-error

Native work, portable state, dependencies, and the retry closure are all queue-owned before the injected owner callback escapes.

ok
=1native-submits
ok
=1
luv::vulkan-queue-submission-counterqueue
ok
eq:submitted
luv::vulkan-command-buffer-statecommand-buffer
ok
=1
length
luv::vulkan-queue-live-submissionsqueue
ok
eqqueue
gethash
luv::vulkan-queue-retirement-ledgerqueue
luv::*gpu-retirement-ledger-custodians*
ok
=1first-attempts
ok
=1second-attempts
ok
equal'
5
second-values
ok
=4
third
arefnative-waits0
ok
=5
third
arefnative-signals0
setffrontier1
ok
=1native-submits
ok
=2first-attempts
ok
=1second-attempts
ok
equal'
5
first-values
ok
null
luv::vulkan-queue-live-submissionsqueue
setf
symbol-functionfrontier-symbol
original-frontier
symbol-functionsubmit-symbol
original-submit
deftestvulkan-shared-external-timeline-advances-across-plane-subsets
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:fake-queue:devicedevice:family0:timeline:queue-timeline
same-state
first-values'
second-values'
first-texture
make-vulkan-submit-probe-texturedevice:plane-0:semaphore:shared-timeline:semaphore-statestate:submitted
lambda
layoutvalue
declare
ignorelayout
pushvaluefirst-values
second-texture
make-vulkan-submit-probe-texturedevice:plane-1:semaphore:shared-timeline:semaphore-statesame-state:submitted
lambda
layoutvalue
declare
ignorelayout
pushvaluesecond-values
both
make-vulkan-submit-probe-command-bufferdevice:both:resources
listfirst-texturesecond-texture
:textures
listfirst-texturesecond-texture
:final-layouts
list
consfirst-texture:shader-read-only-optimal
conssecond-texture:shader-read-only-optimal
first-only
make-vulkan-submit-probe-command-bufferdevice:first-only:resources
listfirst-texture
:textures
listfirst-texture
:final-layouts
list
consfirst-texture:general
second-only
make-vulkan-submit-probe-command-bufferdevice:second-only:resources
listsecond-texture
:textures
listsecond-texture
:final-layouts
list
conssecond-texture:general
frontier0
native-frontiers'
original-frontier
symbol-functionfrontier-symbol
original-submit
symbol-functionsubmit-symbol
ok
eqstatesame-state
setf
luv::vulkan-device-queuedevice
queue
unwind-protect
progn
setf
symbol-functionfrontier-symbol
lambda
queue
declare
ignorequeue
frontier
symbol-functionsubmit-symbol
lambda
native-queuenative-command-buffers&keywait-semaphoressignal-semaphores
declare
ignorenative-queuenative-command-buffers
push
list
third
arefwait-semaphores0
third
arefsignal-semaphores0
native-frontiers
ok
=1
luv:submitqueueboth
ok
=2
luv:submitqueuefirst-only
ok
=3
luv:submitqueuesecond-only

Both planes share one generation state. A subset advances it for its absent sibling, so rejoining never repeats a timeline signal.

ok
equal'
1011
1112
1213
nreversenative-frontiers
ok
equal'
1211
first-values
ok
equal'
1311
second-values
setffrontier3
ok
null
luv::vulkan-queue-live-submissionsqueue
ok
null
luv::vulkan-queue-external-semaphore-statesqueue

Reusing the same raw handle starts a fresh state generation.

let
ok
not
eqreusedstate
ok
=2
luv::vulkan-external-semaphore-state-valuereused
setf
symbol-functionfrontier-symbol
original-frontier
symbol-functionsubmit-symbol
original-submit
deftestvulkan-leak-warning-nonlocal-exit-cannot-preempt-custody
let
luv::*gpu-finalizer-retirement-ledger*
luv::make-gpu-retirement-ledger
attempts0
fail-pt
handler-bind
ok
signals
handler-bind
luv:gpu-resource-leaked
lambda
condition
declare
ignorecondition
error"promoted leak warning"
luv::retire-vulkan-leaked-native-owner'vulkan-gpu-texture"leaked probe"nil:leaked-owner
lambda
incfattempts
whenfail-p
error"injected native close failure"
'simple-error
ok
=1attempts
ok
equal'
:leaked-owner
mapcar#'luv::gpu-retirement-entry-resource
luv::gpu-retirement-ledger-entriesluv::*gpu-finalizer-retirement-ledger*
setffail-pnil
ok
=2attempts
ok
null
luv::gpu-retirement-ledger-entriesluv::*gpu-finalizer-retirement-ledger*
deftestvulkan-post-device-texture-destroy-runs-device-independent-tail
let*
device
make-instance'luv::vulkan-gpu-device:handle:retired-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:retired-queue:devicedevice:family0:timeline:retired-timeline
state
luv::make-vulkan-external-semaphore-state:semaphore:retired-external-timeline:value7:references1
owner-releases0
texturenil
setf
luv::vulkan-device-queuedevice
queue
luv::vulkan-queue-external-semaphore-statesqueue
liststate
texture
make-vulkan-submit-probe-texturedevice:external-plane:semaphore:retired-external-timeline:semaphore-statestate:owner
lambda
incfowner-releases
luv::vulkan-device-retiring-pdevice
tt
ok
=1owner-releases
ok
zerop
luv::vulkan-external-semaphore-state-referencesstate
ok
null
luv::vulkan-queue-external-semaphore-statesqueue
ok
luv::vulkan-object-destroyed-ptexture
deftestvulkan-render-pass-cache-rechecks-admission-under-queue-lock
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:fake-queue:devicedevice:family0:timeline:fake-timeline
original-create
symbol-functioncreate-symbol
native-creates0
descriptor
luv:make-texture-descriptor:size'
44
:dimensions:2d:format:rgba8-unorm:usage:render-attachment
setf
luv::vulkan-device-queuedevice
queue
luv::vulkan-device-retiring-pdevice
t
unwind-protect
progn
setf
symbol-functioncreate-symbol
lambda
&restarguments
declare
ignorearguments
incfnative-creates
:impossible-render-pass
ok
zeropnative-creates
ok
zerop
hash-table-count
luv::vulkan-device-render-passesdevice
setf
symbol-functioncreate-symbol
original-create
deftestvulkan-finish-retains-ended-encoder-ownership-on-wrapper-failure
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:fake-queue:devicedevice:family0:timeline:fake-timeline
encoder
make-instance'luv::vulkan-gpu-command-encoder:label"finish handoff probe":devicedevice:command-pool:fake-command-pool:command-buffer:fake-command-buffer
wrappernil
symbols
listend-symboldestroy-pool-symbolfrontier-symbolconstructor-symbol
originals
mapcar#'symbol-functionsymbols
ends0
pool-destroys0
fail-construction-pt
setf
luv::vulkan-device-queuedevice
queue
unwind-protect
progn
setf
symbol-functionend-symbol
lambda
command-buffer
declare
ignorecommand-buffer
incfends
symbol-functiondestroy-pool-symbol
lambda
native-devicepool
declare
ignorenative-devicepool
incfpool-destroys
symbol-functionfrontier-symbol
lambda
queue
declare
ignorequeue
0
symbol-functionconstructor-symbol
let
original
fourthoriginals
lambda
&restarguments
whenfail-construction-p
setffail-construction-pnil
error"injected command-buffer wrapper failure"
applyoriginalarguments
ok
signals
luv:finishencoder
'simple-error
ok
=1ends
ok
eq:ended
luv::vulkan-command-encoder-stateencoder
ok
eq:fake-command-pool
luv::vulkan-command-encoder-command-poolencoder
setfwrapper
luv:finishencoder
ok
=1ends
ok
eq:finished
luv::vulkan-command-encoder-stateencoder
ok
null
luv::vulkan-command-encoder-command-poolencoder
setfwrappernil
ok
=1pool-destroys
whenwrapper
loopforsymbolinsymbolsfororiginalinoriginalsdo
setf
symbol-functionsymbol
original
deftestvulkan-device-destroy-resumes-native-progress-after-ledger-barrier
let*
device
make-instance'luv::vulkan-gpu-device:handle:fake-device:instance:fake-instance:physical-device:fake-physical-device:queue-family0
queue
make-instance'luv::vulkan-gpu-queue:handle:fake-queue:devicedevice:family0:timeline:fake-timeline
symbols
listfrontier-symbolwait-symbolsemaphore-symbolrender-pass-symboldevice-symbolinstance-symbol
originals
mapcar#'symbol-functionsymbols
waits0
semaphores0
render-a0
render-b0
native-devices0
instances0
external-releases0
fail-ledger-pt
fail-render-b-pt
fail-instance-pt
setf
luv::vulkan-device-queuedevice
queue

Production installs both shared closures before any render-pass cache entries exist. The pass drain must therefore snapshot lazily.

setf
gethash:a
luv::vulkan-device-render-passesdevice
:render-a
gethash:b
luv::vulkan-device-render-passesdevice
:render-b
luv::enqueue-gpu-retirement
luv::vulkan-queue-retirement-ledgerqueue
:barrier0
lambda
whenfail-ledger-p
setffail-ledger-pnil
error"injected ledger barrier failure"
unwind-protect
progn
setf
symbol-functionfrontier-symbol
lambda
queue
declare
ignorequeue
0
symbol-functionwait-symbol
lambda
native-device
declare
ignorenative-device
incfwaits
symbol-functionsemaphore-symbol
lambda
native-devicesemaphore
declare
ignorenative-devicesemaphore
incfsemaphores
symbol-functionrender-pass-symbol
lambda
native-devicerender-pass
declare
ignorenative-device
ecaserender-pass
:render-a
incfrender-a
:render-b
incfrender-b
whenfail-render-b-p
setffail-render-b-pnil
error"injected render-pass failure"
symbol-functiondevice-symbol
lambda
native-device
declare
ignorenative-device
incfnative-devices
symbol-functioninstance-symbol
lambda
instance
declare
ignoreinstance
incfinstances
whenfail-instance-p
setffail-instance-pnil
error"injected instance failure"

The first attempt completes the idle call but cannot close admission while a ledger owner remains failed.

ok
=1waits
ok
not
luv::vulkan-device-retiring-pdevice
ok
zeropsemaphores

The next attempt reuses the completed wait, drains the barrier, closes admission, and stops at one native render-pass failure.

ok
signals'simple-error
ok
=1waits
ok
luv::vulkan-device-retiring-pdevice
ok
=1semaphores

Model the wrapper being dropped here: its installed finalizer owns the exact native progress sequence already advanced by explicit destroy. Its own idle step is safe and runs once, then retirement resumes at the failed pass rather than at semaphore.

ok
signals
funcall
luv::vulkan-device-finalizer-teardowndevice
'simple-error
ok
=2waits
ok
=1render-a
ok
=2render-b
ok
=1native-devices
ok
=1instances
ok
not
luv::vulkan-object-destroyed-pdevice

A texture finalized in this post-vkDestroyDevice window still runs its non-device owner callback while guarded Vk calls skip.

let
texture
make-instance'luv::vulkan-gpu-texture:size'
111
:usage'
:texture-binding
:dimensions:2d:format:r8-unorm:handle:retired-image:devicedevice:vk-format:r8-unorm:owned-pnil:external-owner
lambda
incfexternal-releases
ok
=1external-releases

Retrying that same durable finalizer closure resumes at the failed instance call without repeating its idle or device steps.

funcall
luv::vulkan-device-finalizer-teardowndevice
ok
=2waits
ok
=1semaphores
ok
=1render-a
ok
=2render-b
ok
=1native-devices
ok
=2instances
ok
luv::vulkan-object-destroyed-pdevice
ok
luv::vulkan-object-destroyed-pqueue
loopforsymbolinsymbolsfororiginalinoriginalsdo
setf
symbol-functionsymbol
original
deftestdefault-provider-prefers-the-native-apple-backend#+darwin (ok (typep luv:*gpu-provider* 'luv:metal-gpu-provider))#-darwin
deftestrenderer-readbacks-use-compressed-png-output
let
pixels
make-array
*64644
:element-type'
unsigned-byte8
:initial-element255
uiop:with-temporary-file
:pathnamepathname:prefix"luv-readback-":suffix".png"
luv:write-rgba-pngpathnamepixels6464:rgba8-unorm
with-open-file
streampathname:element-type'
unsigned-byte8
ok
<
file-lengthstream
1024
deftestcadence-clock-wakes-before-deadlines-and-preserves-phase
let*
timestampsnil
clock
luv:make-cadence-clock
lambda
canvastimestamp
declare
ignorecanvas
pushtimestamptimestamps
:frames-per-second60
ok
equaltimestamps'
10d0

The millisecond SDL wait must wake before the fractional deadline.

An ordinary late wake does not move the cadence's original phase.

luv:service-canvas-clockclocknil10.017d0
ok
ok
<
abs
-
luv::cadence-clock-next-frame-timeclock
+10d0
/2d060d0
1d-12

A long pause skips missed frames rather than replaying them.

ok
=3
lengthtimestamps
ok
>
luv::cadence-clock-next-frame-timeclock
10.1d0
deftestlazy-clock-gives-one-time-to-a-whole-turn
let
samples'
10d020d030d0
calls0
let
clock
luv:make-lazy-clock:source
lambda
incfcalls
popsamples
ok
=1calls
ok
=3calls
deftestcadence-presentation-time-is-the-following-display-beat
let*
clock
luv:make-lazy-clock:source
lambda
10d0
cadence
luv:make-cadence-clock
lambda
canvastimestamp
declare
ignorecanvastimestamp
:frames-per-second60
canvas
luv:make-sdl-canvas:clockcadence:timeclock
deftestpresentation-clock-asks-once-and-leaves-pacing-to-the-frame
let*
timestampsnil
clock
luv:make-presentation-clock
lambda
canvastimestamp
declare
ignorecanvas
pushtimestamptimestamps
ok
equaltimestamps'
4d0
deftestcanvas-loop-failure-preserves-the-actionable-condition
let*
root-cause
make-condition'simple-error:format-control"event dispatch failed"
request
luv::make-sdl-canvas-request:function#'identity
setf
luv::sdl-canvas-startup-errorcanvas
root-cause
luv::sdl-canvas-requestscanvas
listrequest
ok
eqroot-cause
luv::sdl-canvas-request-errorrequest
ok
null
luv::sdl-canvas-requestscanvas
deftestslug-formats-retain-the-exact-vulkan-abi-values
ok
=81
cffi:foreign-enum-value'lvk::format:r16g16-uint
ok
=97
cffi:foreign-enum-value'lvk::format:r16g16b16a16-sfloat
deftestvideo-planes-retain-the-exact-vulkan-abi-values
ok
=9
cffi:foreign-enum-value'lvk::format:r8-unorm
ok
=16
cffi:foreign-enum-value'lvk::format:r8g8-unorm
ok
=#x10
cffi:foreign-bitfield-value'lvk::image-aspect-flags'
:plane-0
ok
=#x20
cffi:foreign-bitfield-value'lvk::image-aspect-flags'
:plane-1
ok
=#x20
cffi:foreign-bitfield-value'lvk::queue-flags'
:video-decode
deftestpremultiplied-alpha-retains-the-exact-vulkan-blend-factor
ok
=7
cffi:foreign-enum-value'lvk::blend-factor:one-minus-src-alpha
deftestsampled-texture-layouts-do-not-require-a-sampler
let*
entries'
:binding0:type:texture
:binding1:type:texture
:binding2:type:uniform-buffer
descriptor
luv:make-bind-group-layout-descriptor:entriesentries
deftestdefinitions-retain-abi-metadata-without-call-classes
let
ok
equal
getfdescription:foreign-name
"vkCreateInstance"
ok
eq
getfdescription:return-type
'lvk::checked-result
ok
equal
mapcar#'first
getfdescription:arguments
'
lvk::create-infolvk::allocatorlvk::instance
ok
not
getfdescription:command-p
ok
null
find-class'vk:create-instancenil
deftestvulkan-device-contract-includes-shader-int64
let
description
lvk:vulkan-function-description'vk:get-physical-device-features
ok
equal
getfdescription:foreign-name
"vkGetPhysicalDeviceFeatures"
ok
=
*55
cffi:foreign-type-size:uint32
cffi:foreign-type-size'
ok
<
cffi:foreign-slot-offset''lvk::shader-float64
cffi:foreign-slot-offset''lvk::shader-int64
deftestpresent-timing-abi-is-explicit-and-inspectable
let
description
lvk:vulkan-function-description'vk:get-past-presentation-timing-ext
ok
equal
getfdescription:foreign-name
"vkGetPastPresentationTimingEXT"
ok
equal
mapcar#'first
getfdescription:arguments
'
ok
=16
cffi:foreign-type-size'
ok
=32
cffi:foreign-type-size'
ok
=#x240
cffi:foreign-bitfield-value'lvk::swapchain-create-flags'
:present-id-2-khr:present-timing-ext
deftestpresentation-timing-commands-use-device-procedure-dispatch
let
original
symbol-function'lvk::device-procedure
lookupsnil
unwind-protect
progn
setf
symbol-function'lvk::device-procedure
lambda
devicename
push
listdevicename
lookups
let
device
cffi:make-pointer42
ok
eq:success
vk:get-past-presentation-timing-extdevice
cffi:null-pointer
cffi:null-pointer
ok
equal`
,device"vkGetPastPresentationTimingEXT"
lookups
setf
symbol-function'lvk::device-procedure
original
deftestpresentation-timeline-correlates-predictions-with-display-results
let
timeline
make-instance'luv::vulkan-presentation-timeline:stage:image-first-pixel-visible
setf
luv::vulkan-presentation-timeline-statustimeline
:recording
luv::vulkan-presentation-timeline-time-domaintimeline
:clock-monotonic
luv::vulkan-presentation-timeline-time-domain-idtimeline
7
luv::vulkan-presentation-timeline-refresh-durationtimeline
16666667
luv::vulkan-presentation-timeline-refresh-intervaltimeline
16666667
dotimes
index3
let
present-id
1+index
luv::note-vulkan-presentation-submissiontimelinepresent-id
+10d0
/index60d0
+9.99d0
/index60d0
ok
luv::note-vulkan-presentation-resulttimelinepresent-id
+1000000000
*index16666667
:clock-monotonic7
let*
observations
coerce
luv:presentation-timing-snapshot-observationssnapshot
'list
ok
eq:recording
luv:presentation-timing-snapshot-statussnapshot
ok
equal'
123
mapcar#'luv:presentation-timing-observation-present-idobservations
ok
=2
lengthintervals
ok
every
lambda
value
<
abs
-value16.666667d0
1d-9
intervals
ok
<
abs
car
lastdrift
1d-3
deftestpresentation-prediction-marches-over-native-display-beats
let
timeline
make-instance'luv::vulkan-presentation-timeline:stage:image-first-pixel-visible:absolute-time-pt
setf
luv::vulkan-presentation-timeline-statustimeline
:recording
luv::vulkan-presentation-timeline-time-domaintimeline
:present-stage-local-ext
luv::vulkan-presentation-timeline-time-domain-idtimeline
7
luv::vulkan-presentation-timeline-refresh-durationtimeline
16666667

Present 7 targeted 1.000 s but appeared one refresh later. Native scheduling catches up from the actual display beat, while the unrelated host animation prediction remains untouched.

luv::note-vulkan-presentation-submissiontimeline710d09.99d01000000000
ok
luv::note-vulkan-presentation-resulttimeline71016666667:present-stage-local-ext7
multiple-value-bind
hosttarget
ok
=host99d0
ok
=target1016666667
multiple-value-bind
hosttarget
ok
=host100d0
ok
=target1016666667

Feedback for 7 may still be the newest result when frame 9 is queued. The queued target, not a cross-clock lateness estimate, owns cadence.

multiple-value-bind
hosttarget
ok
=host101d0
ok
=target1033333334

Frame 8 then misses its target by one whole refresh. That lateness is diagnostic feedback; it must not turn frame 9 into another 33 ms gap.

ok
luv::note-vulkan-presentation-resulttimeline81033333334:present-stage-local-ext7
multiple-value-bind
hosttarget
ok
=host102d0
ok
=target1033333334
deftestpresentation-timeline-ring-retains-only-its-newest-minute
let
timeline
make-instance'luv::vulkan-presentation-timeline:stage:image-first-pixel-out
loopforpresent-idfrom1todo
luv::note-vulkan-presentation-submissiontimelinepresent-id
floatpresent-id1d0
floatpresent-id1d0
let
observations
luv:presentation-timing-snapshot-observations
ok
=6
luv:presentation-timing-observation-present-id
arefobservations0
ok
=
luv:presentation-timing-observation-present-id
arefobservations
1-
lengthobservations
deftestreal-loader-calls-allocate-events-only-in-an-explicit-trace
let
trace
let
ok
=
lengthevents
2
dolist
eventevents
ok
equal
lvk:vulkan-call-event-foreign-nameevent
"vkEnumerateInstanceExtensionProperties"
ok
eq
lvk:vulkan-call-event-statusevent
:returned