hal/vulkan/validation.lisp
Whether to install luv's own debug messenger on a new Vulkan instance.
The messenger only ever hears from a layer that is loaded, so leaving this true costs nothing in a run without VK_LOADER_LAYERS_ENABLE. Bind it to NIL to keep a provider quiet even when the layer is present.
Whether the callback captures a Lisp backtrace for each message.
The backtrace is the whole value of catching the message where it happens: the text names the Vulkan call, and only the stack names the code that made it. Turning this off leaves the message with nothing but its own words.
One thing the validation layer said, and where Lisp was when it said it.
What the validation layer said during one operation.
The validation layer rejected a call made during OPERATION.
The API call itself returned normally -- a layer message is not a result code -- so this is signalled at the first safe point after it, carrying the backtrace captured while the offending frames were still on the stack.
The validation layer warned about a call made during OPERATION.
Receive one message from the Vulkan layer stack.
This runs inside the call that produced the message, so it says its piece to the log immediately -- a run that then wedges in the driver still leaves the complaint behind -- and retains it for the enclosing extent to signal.
Signal whatever the current extent collected, then forget it.
An error outranks a warning: when the layer rejected anything at all, that is the condition worth having, and the warnings are carried along inside it rather than raised separately.
Run body, then signal what the validation layer said while it ran.
body leaving by its own error is left alone: that error is the news, and the
layer's account of it is already in the log.
((&optional operation) &body body)Run BODY, then signal what the validation layer said while it ran. BODY leaving by its own error is left alone: that error is the news, and the layer's account of it is already in the log.
Whether to install luv's own debug messenger on a new Vulkan instance. The messenger only ever hears from a layer that is loaded, so leaving this true costs nothing in a run without VK_LOADER_LAYERS_ENABLE. Bind it to NIL to keep a provider quiet even when the layer is present.
Whether the callback captures a Lisp backtrace for each message. The backtrace is the whole value of catching the message where it happens: the text names the Vulkan call, and only the stack names the code that made it. Turning this off leaves the message with nothing but its own words.
Logical conjunction of tests and raw truth values.
Whether the current dynamic extent retains messages for a later check.
Messages retained by the innermost WITH-VULKAN-VALIDATION extent.
(condition stream)What the validation layer said during one operation.
The validation layer rejected a call made during OPERATION. The API call itself returned normally -- a layer message is not a result code -- so this is signalled at the first safe point after it, carrying the backtrace captured while the offending frames were still on the stack.
The validation layer warned about a call made during OPERATION.
(message)Receive one message from the Vulkan layer stack. This runs inside the call that produced the message, so it says its piece to the log immediately -- a run that then wedges in the driver still leaves the complaint behind -- and retains it for the enclosing extent to signal.
(&optional (depth *canvas-failure-backtrace-depth*))The current backtrace as text, from the frame that asked for it down to the pump: forms abbreviated, the frames of the capture itself left out.
(category control &rest arguments)Write one timestamped line about CATEGORY, formatted from CONTROL. CATEGORY is a keyword naming the subsystem -- :canvas, :watchdog, :vulkan -- so a reader can tell at a glance which machine is talking.
(operation)Signal whatever the current extent collected, then forget it. An error outranks a warning: when the layer rejected anything at all, that is the condition worth having, and the warnings are carried along inside it rather than raised separately.
(operation function)
Validation as conditions.
The Khronos validation layer is the only thing that ever says a Vulkan call was wrong. Without it the driver simply does something -- usually the thing you meant, sometimes nothing, occasionally a command buffer that never completes -- and the mistake surfaces hours later as a black frame or a wedged present. Its messages therefore deserve the same standing as any other error in the image, rather than a line of text on a stream nobody is reading.
Two moments matter, and they are not the same moment:
The layer calls back on the thread that made the offending call, with that call's Lisp frames still on the stack. That is the only instant at which the culprit can be named, so the callback logs the message and captures a backtrace right there.
The callback returns into the middle of a Vulkan driver. Unwinding from there -- which is what signalling an error would do -- leaves the driver holding whatever it was holding. So nothing is signalled until a safe point outside the call, where
with-vulkan-validationturns whatever the extent collected into one condition.The layer is not loaded unless someone asks for it, so all of this costs nothing in an ordinary run:
VK_LOADER_LAYERS_ENABLE='
*validation*' ./sly start