luv

Workshop wiki

shader-lab.lisp

mcclim/shader-lab.lisp

system luvcraft/shader-lab · 74 definitions · on GitHub

A presentation-oriented browser for mathematical shaders and lowered SSA.

in-package#:mcluv
define-presentation-typeshader-expression-presentation
define-presentation-typeshader-instruction-presentation
define-presentation-typeshader-basic-block-presentation
define-presentation-typeshader-specification-presentation
define-presentation-typeshader-definition-presentation
define-presentation-typeblock-kind-presentation
defparameter*shader-accent-ink*
make-rgb-color0.100.380.78
defparameter*shader-call-ink*
make-rgb-color0.440.200.68
defparameter*shader-reference-ink*
make-rgb-color0.020.430.47
defparameter*shader-literal-ink*
make-rgb-color0.760.300.08
defparameter*shader-muted-ink*
make-rgb-color0.360.390.43
defparameter*shader-panel-ink*
make-rgb-color0.950.9650.98
defparameter*shader-selection-ink*
make-rgb-color0.840.911.0
define-presentation-methodpresentation-typep
defclassshader-definition-entry
role:initarg:role:readershader-definition-entry-role
stage:initarg:stage:readershader-definition-entry-stage
label:initarg:label:readershader-definition-entry-label
dependent:initarg:dependent:initformnil:readershader-definition-entry-dependent
pipeline:initarg:pipeline:initformnil:readershader-definition-entry-pipeline
specification:initarg:specification:initformnil:accessorshader-definition-entry-specification
lowering:initformnil:accessorshader-definition-entry-lowering
status:initform:uncompiled:accessorshader-definition-entry-status
diagnostic:initformnil:accessorshader-definition-entry-diagnostic
defclassshader-lab-health-report
status:initarg:status:readershader-lab-health-report-status
frame-state:initarg:frame-state:readershader-lab-health-report-frame-state
process-alive-p:initarg:process-alive-p:readershader-lab-health-report-process-alive-p
mirror-count:initarg:mirror-count:initform0:readershader-lab-health-report-mirror-count
canvas-state:initarg:canvas-state:initformnil:readershader-lab-health-report-canvas-state
latency:initarg:latency:initformnil:readershader-lab-health-report-latency
problems:initarg:problems:initformnil:readershader-lab-health-report-problems
backtrace:initarg:backtrace:initformnil:readershader-lab-health-report-backtrace
:documentation

One bounded diagnosis of frame, process, mirror, canvas, and responsiveness.

defmethodprint-object
print-unreadable-object
reportstream:typet
formatstream"~S, ~D mirror~:P, canvas ~S~@[; ~{~A~^, ~}~]"
shader-lab-health-report-statusreport
shader-lab-health-report-mirror-countreport
shader-lab-health-report-canvas-statereport
shader-lab-health-report-problemsreport
climi::define-event-classshader-lab-health-event
climi::standard-event
sheet:initarg:sheet:readerclim:event-sheet
function:initarg:function:readershader-lab-health-event-function
defmethodhandle-event
funcall
shader-lab-health-event-functionevent
defunrefresh-shader-definition-entry
entry&keyforce

Compile entry's current method without discarding its last good lowering.

let
dependent
shader-definition-entry-dependententry
when
multiple-value-bind
revisionevent
ifdependent
values0nil
declare
ignoreevent
setf
shader-definition-entry-statusentry
:compiling
handler-case
let*
specification
ifdependent
luv.shader:shader-specification-for
shader-definition-entry-roleentry
shader-definition-entry-stageentry
shader-definition-entry-specificationentry
setf
shader-definition-entry-specificationentry
specification
shader-definition-entry-loweringentry
lowering
shader-definition-entry-statusentry
:ready
shader-definition-entry-diagnosticentry
nil
error
condition
setf
shader-definition-entry-statusentry
:failed
shader-definition-entry-diagnosticentry
condition
entry
defunmake-live-shader-definition-entry
rolestagelabelpipeline
let*
entry
make-instance'shader-definition-entry:rolerole:stagestage:labellabel:dependentdependent:pipelinepipeline
defunmake-static-shader-definition-entry
specification&keylabel
let
entry
make-instance'shader-definition-entry:role:stage
luv.shader:shader-specification-stagespecification
:label
orlabel
string-upcase
symbol-name
:specificationspecification
defunrelease-shader-definition-entry
entry
let
dependent
shader-definition-entry-dependententry
nil
define-application-frameshader-lab
lowering:initarg:lowering:initform:accessorshader-lab-lowering
definitions:initarg:definitions:readershader-lab-definitions
current-definition:initarg:current-definition:accessorshader-lab-current-definition
materials:initarg:materials:initform:readershader-lab-materials
atlas:initform:readershader-lab-atlas
process:initformnil:accessorshader-lab-process
health-report:initformnil:accessorshader-lab-last-health-report
selection:initformnil:accessorshader-lab-selection
:menu-barnil
:panes
materials:application:display-function'display-shader-materials:scroll-barsnil:default-text-style
make-text-style:sans-serifnil:normal
source:application:display-function'display-shader-source:scroll-bars:vertical:default-text-style
make-text-style:fixnil:normal
:text-margins'
:left12:right12:top10:bottom10
ssa:application:display-function'display-shader-ssa:scroll-bars:vertical:default-text-style
make-text-style:fixnil:normal
:text-margins'
:left12:right12:top10:bottom10
details:application:display-function'display-shader-selection:scroll-barsnil:default-text-style
make-text-style:fixnil:normal
:text-margins'
:left12:right12:top8:bottom8
:layouts
default
vertically
:width1120:height820:spacing8
1/5materials
3/5
horizontally
:spacing8
1/2source
1/2ssa
1/5details
defunshader-lab-specifications

Return the current successfully compiled shader method results in frame.

mapcar#'shader-definition-entry-specification
shader-lab-definitionsframe
defunselected-shader-expression
let
selection
shader-lab-selectionframe
cond
selection
typepselection'luv.spir-v:instruction
first
gethashselection
luv.spir-v:shader-lowering-instruction-expressions
shader-lab-loweringframe
defunselected-shader-instructions
let
selection
shader-lab-selectionframe
cond
gethashselection
luv.spir-v:shader-lowering-expression-instructions
shader-lab-loweringframe
typepselection'luv.spir-v:instruction
listselection
defunshader-type-label
string-downcase
symbol-name
luv.shader:shader-type-nametype
defunwrite-shader-name
namestream
write-string
string-downcase
symbol-namename
stream
defunshader-infix-operator-p
operator

Shader operators are ordinary symbols; arithmetic is CL's own.

memberoperator'
defunshader-operator-label
operator
string-downcase
symbol-nameoperator
defunshader-lab-current-specification
luv.spir-v:shader-lowering-specification
shader-lab-loweringframe
defunblock-material-preview-tile
block
let
tiles
luvcraft:block-kind-face-tilesblock
or
getftiles:top
getftiles:all
getftiles:side
defunpacked-block-ink
word
make-rgb-color
/
ldb
byte80
word
255.0
/
ldb
byte88
word
255.0
/
ldb
byte816
word
255.0
defundraw-block-atlas-tile
streamatlastilelefttop&key
let
dotimes
y16
dotimes
x16
draw-rectangle*stream
+left
+left
+top
:ink
packed-block-ink
arefatlasy
+x
*offset16
defundraw-shader-tab
framestreamdefinitionlefttop
let
selected-p
eqdefinition
shader-lab-current-definitionframe
with-output-as-presentation
draw-rectangle*streamlefttop
+left188
+top25
:ink
draw-rectangle*streamlefttop
+left188
+top25
:ink:fillednil:line-thickness
ifselected-p21
draw-text*stream
shader-definition-entry-labeldefinition
+left10
+top6
:ink
ifselected-p*shader-accent-ink*+black+
:align-y:top
defundraw-block-material-card
framestreamblocknumberlefttop
let*
selected-p
eqblock
shader-lab-selectionframe
with-output-as-presentation
streamblock'block-kind-presentation:single-boxt
draw-rectangle*streamlefttop
+left132
+top88
:ink
draw-block-atlas-tilestream
shader-lab-atlasframe
tile
+left8
+top8
draw-rectangle*stream
+left7
+top7
+left57
+top57
:ink:fillednil:line-thickness
ifselected-p21
draw-text*stream
formatnil"~D ~(~A~)"number
luvcraft:block-kind-nameblock
+left8
+top66
:ink
ifselected-p*shader-accent-ink*+black+
:align-y:top
defundisplay-shader-materials
framestream
draw-text*stream"LUVCRAFT MATERIAL WORKBENCH"145:ink*shader-accent-ink*:align-y:top:text-style
make-text-style:sans-serif:bold:normal
draw-text*stream"choose a live shader"1430:ink*shader-muted-ink*:align-y:top
loopfordefinitionin
shader-lab-definitionsframe
forindexfrom0do
loopforblockin
shader-lab-materialsframe
fornumberfrom1forleft=
+14
*
1-number
144
do
draw-block-material-cardframestreamblocknumberleft62
defunquantity-factors-label
factors
iffactors
formatnil"~{~A~^ ~}"
mapcar
lambda
factor
if
=1
cdrfactor
string-downcase
symbol-name
carfactor
formatnil"~(~A~)^~A"
carfactor
cdrfactor
factors
"1"
defunquantity-specification-label
specification
ifspecification
formatnil"~@[~(~A~) · ~]~@[kind ~(~A~) · ~]~A [~A] · ~A · ~A"
luv.arithmetic:quantity-specification-namespecification
luv.arithmetic:quantity-specification-kindspecification
quantity-factors-label
luv.arithmetic:dimension-factors
luv.arithmetic:quantity-specification-dimensionspecification
quantity-factors-label
luv.arithmetic:unit-expression-factors
luv.arithmetic:quantity-specification-unitspecification
case
luv.arithmetic:quantity-specification-tensor-orderspecification
0"scalar"
1"vector"
otherwise
formatnil"tensor order ~D"
luv.arithmetic:quantity-specification-tensor-orderspecification
if"point""difference"
"unannotated"
defunquantity-projection-lanes-label
positions
coerce
mapcar
lambda
or
nthposition'
#\x#\y#\z#\w
#\?
positions
'string
defunquantity-layout-label
whenlayout
formatnil"packed {~{~A~^; ~}}"
mapcar
lambda
projection
formatnil"~A -> ~A"
quantity-projection-lanes-label
luv.arithmetic:quantity-projection-positionsprojection
quantity-specification-label
luv.arithmetic:quantity-projection-specificationprojection
luv.arithmetic:quantity-layout-projectionslayout
defunwrite-shader-expression
expressionstreamframe

Render expression as nested selectable mathematical presentations.

labels
write-body
etypecaseexpression
luv.shader:shader-map-application
write-string"project-point["stream
write-shader-name
luv.shader:shader-object-name
luv.shader:shader-map-application-definitionexpression
stream
write-string"]("stream
write-shader-expression
luv.shader:shader-map-application-pointexpression
streamframe
write-string"; rows "stream
loopforrowin
luv.shader:shader-map-application-rowsexpression
forfirst-p=tthennilunlessfirst-pdo
write-string", "stream
do
write-char#\)stream
luv.shader:shader-map-projection
write-string"project-sample("stream
write-shader-expression
luv.shader:shader-map-projection-applicationexpression
streamframe
write-char#\)stream
luv.shader:shader-representation
write-string"representation("stream
write-char#\)stream
luv.shader:shader-call
let
cond
eqoperator:swizzle
write-shader-expression
firstoperands
streamframe
formatstream".~(~A~)"
write-char#\(stream
loopforoperandinoperandsforfirst-p=tthennilunlessfirst-pdo
formatstream" ~A "
do
write-char#\)stream
t
write-stringstream
write-char#\(stream
loopforoperandinoperandsforfirst-p=tthennilunlessfirst-pdo
write-string", "stream
do
write-char#\)stream
defundisplay-shader-interface
write-string" "stream
with-drawing-options
stream:ink
if
eq:input
luv.shader:shader-interface-directiondeclaration
*shader-reference-ink**shader-call-ink*
:text-face:bold
formatstream"~(~A~)"
luv.shader:shader-interface-directiondeclaration
write-char#\Spacestream
formatstream" : ~A [~A] · meaning ~A~%"
shader-type-label
luv.shader:shader-declaration-typedeclaration
if
luv.shader:shader-interface-built-indeclaration
formatnil"built-in ~(~A~)"
luv.shader:shader-interface-built-indeclaration
formatnil"location ~D"
luv.shader:shader-interface-locationdeclaration
quantity-semantics-label
luv.shader:shader-declaration-quantity-specificationdeclaration
luv.shader:shader-declaration-quantity-layoutdeclaration
defundisplay-shader-resource
streamresource
write-string" resource "stream
formatstream" : ~A [set ~D, binding ~D]~%"
shader-type-label
luv.shader:shader-declaration-typeresource
luv.shader:shader-resource-descriptor-setresource
luv.shader:shader-resource-bindingresource
when
or
luv.shader:shader-resource-sample-quantity-specificationresource
luv.shader:shader-resource-sample-quantity-layoutresource
formatstream" sample meaning ~A~%"
quantity-semantics-label
luv.shader:shader-resource-sample-quantity-specificationresource
luv.shader:shader-resource-sample-quantity-layoutresource
when
dolist
member
luv.shader:shader-uniform-block-membersresource
formatstream" ~2D "
luv.shader:shader-uniform-member-offsetmember
formatstream" : ~A · meaning ~A~%"
shader-type-label
luv.shader:shader-declaration-typemember
quantity-semantics-label
luv.shader:shader-declaration-quantity-specificationmember
luv.shader:shader-declaration-quantity-layoutmember
defundisplay-shader-source
framestream
let*
lowering
shader-lab-loweringframe
specification
luv.spir-v:shader-lowering-specificationlowering
definition
shader-lab-current-definitionframe
dependent
shader-definition-entry-dependentdefinition
pipeline
shader-definition-entry-pipelinedefinition
with-drawing-options
stream:text-size:large:text-face:bold
with-drawing-options
write-string
string-downcase
stream
formatstream" ~(~A~)~2%"
luv.shader:shader-specification-stagespecification
formatstream"definition ~(~A~)/~(~A~) · source ~(~A~)"
shader-definition-entry-roledefinition
shader-definition-entry-stagedefinition
shader-definition-entry-statusdefinition
when
write-string" · changed"stream
terpristream
whenpipeline
formatstream"GPU ~(~A~) · installed revision ~D~%"
luv:live-shader-pipeline-statuspipeline
luv:live-shader-pipeline-installed-revisionpipeline
let
diagnostic
or
shader-definition-entry-diagnosticdefinition
andpipeline
luv:live-shader-pipeline-diagnosticpipeline
whendiagnostic
with-drawing-options
formatstream"diagnostic: ~A~%"diagnostic
terpristream
with-drawing-options
stream:text-face:bold
write-string"interface"stream
terpristream
dolist
declaration
append
luv.shader:shader-specification-inputsspecification
luv.shader:shader-specification-outputsspecification
dolist
resource
luv.shader:shader-specification-resourcesspecification
terpristream
with-drawing-options
stream:text-face:bold
write-string"mathematical bindings"stream
terpristream
dolist
binding
luv.shader:shader-specification-bindingsspecification
write-string" "stream
with-drawing-options
stream:text-face:bold
let
formatstream" : ~A · meaning ~A = "
shader-type-label
luv.shader:shader-expression-typeexpression
terpristream
terpristream
dolist
statement
luv.shader:shader-specification-statementsspecification
write-string" output "stream
with-drawing-options
stream:text-face:bold
write-shader-name
luv.shader:shader-object-name
luv.shader:shader-assignment-outputstatement
stream
write-string" = "stream
write-shader-expression
luv.shader:shader-assignment-valuestatement
streamframe
terpristream
defunwrite-spir-v-form
formstream
let
*package*
find-package'#:luv.spir-v
*print-pretty*nil
*print-case*:downcase
prin1formstream
defundisplay-shader-ssa
framestream
with-drawing-options
stream:text-size:large:text-face:bold:ink*shader-accent-ink*
write-string"lowered SSA"stream
formatstream"~%CLOS functions and basic blocks~2%"
let
module
luv.spir-v:shader-lowering-module
shader-lab-loweringframe
let
constants
remove-if-not
luv.spir-v:spir-v-module-global-declarationsmodule
whenconstants
write-string"module constants"stream
terpristream
dolist
constantconstants
write-string" "stream
terpristream
terpristream
dolist
function
luv.spir-v:spir-v-module-function-definitionsmodule
formatstream"function ~A~%"
luv.spir-v:spir-v-function-result-idfunction
dolist
block
luv.spir-v:spir-v-function-basic-blocksfunction
with-output-as-presentation
streamblock'shader-basic-block-presentation:single-boxt
if
eqblock
shader-lab-selectionframe
with-drawing-options
stream:ink*shader-accent-ink*:text-face:bold
formatstream" block ~A"
luv.spir-v:spir-v-basic-block-labelblock
formatstream" block ~A"
luv.spir-v:spir-v-basic-block-labelblock
terpristream
dolist
instruction
luv.spir-v:spir-v-basic-block-instructionsblock
write-string" "stream
terpristream
defundisplay-shader-selection
framestream
let*
selection
shader-lab-selectionframe
lowering
shader-lab-loweringframe
with-drawing-options
stream:text-face:bold
with-drawing-options
write-string"selection"stream
cond
nullselection
write-string" — click a material, mathematical expression, SSA instruction, or block"stream
typepselection'luvcraft:block-kind
let*
materials
shader-lab-materialsframe
number
positionselectionmaterials:test#'eq
formatstream" — material ~A ~(~A~)~%"
ifnumber
1+number
"?"
luvcraft:block-kind-nameselection
formatstream"atlas tile ~D · number key ~A in luvcraft · right click places · middle click picks"tile
ifnumber
1+number
"?"
formatstream" — representation ~A · meaning ~A · source "
shader-type-label
luv.shader:shader-expression-typeselection
let
instructions
gethashselection
luv.spir-v:shader-lowering-expression-instructionslowering
formatstream"~%~D associated SSA instruction~:P: "
lengthinstructions
loopforinstructionininstructionsforfirst-p=tthennilunlessfirst-pdo
write-string" · "stream
do
typepselection'luv.spir-v:instruction
write-string" — SSA instruction "stream
formatstream"~%~D associated source expression~:P"
length
gethashselection
luv.spir-v:shader-lowering-instruction-expressionslowering
formatstream" — basic block ~A, ~D instruction~:P"
luv.spir-v:spir-v-basic-block-labelselection
length
luv.spir-v:spir-v-basic-block-instructionsselection
define-shader-lab-command
com-select-shader-expression:namenil
expression'shader-expression-presentation:gesture:select
setf
shader-lab-selection*application-frame*
expression
redisplay-frame-panes*application-frame*:force-pt
define-shader-lab-command
com-select-shader-instruction:namenil

Keep the machine occurrence selected. selected-shader-expression follows reverse provenance so the source view still lights up at the same time.

setf
shader-lab-selection*application-frame*
instruction
redisplay-frame-panes*application-frame*:force-pt
define-shader-lab-command
com-select-shader-basic-block:namenil
block'shader-basic-block-presentation:gesture:select
setf
shader-lab-selection*application-frame*
block
redisplay-frame-panes*application-frame*:force-pt
define-shader-lab-command
com-select-shader-definition:namenil

Recompile on the frame's command thread. A broken edit remains visible as diagnostic state while ENTRY retains its previous successful lowering.

setf
shader-lab-current-definition*application-frame*
definition
shader-lab-lowering*application-frame*
shader-definition-entry-loweringdefinition
shader-lab-selection*application-frame*
nil
redisplay-frame-panes*application-frame*:force-pt
define-shader-lab-command
com-select-block-kind:namenil
block'block-kind-presentation:gesture:select
setf
shader-lab-selection*application-frame*
block
redisplay-frame-panes*application-frame*:force-pt
defunpipeline-for-shader-definition
rolestagepipelines
find-if
lambda
pipeline
ecasestage
:vertex
eqrole
luv:live-shader-pipeline-vertex-rolepipeline
:fragment
and
eqrole
luv:live-shader-pipeline-rolepipeline
eqstage
luv:live-shader-pipeline-stagepipeline
pipelines
defunmake-default-shader-definitions
pipelines
loopfor
rolestagelabel
in'
:block-surface:vertex"BLOCK GEOMETRY"
:block-surface:fragment"BLOCK SURFACE"
:block-crosshair:fragment"CROSSHAIR INK"
collect
defunrefresh-shader-lab-now
let
current
shader-lab-current-definitionframe
when
shader-definition-entry-loweringcurrent
setf
shader-lab-loweringframe
shader-definition-entry-loweringcurrent
redisplay-frame-panesframe:force-pt
frame
defuncall-in-shader-lab-process

Queue function through frame's ordinary event loop, with a bounded wait.

let
process
shader-lab-processframe
if
nullprocess
handler-case
valuest
funcallfunction
nil
error
condition
valuestnilcondition
let
completion
sb-thread:make-semaphore:count0
resultnil
conditionnil
handler-case
let
sheet
frame-top-level-sheetframe
climi::queue-append
climi::frame-event-queueframe
make-instance'shader-lab-health-event:sheetsheet:function
lambda
unwind-protect
handler-case
setfresult
funcallfunction
error
caught
setfconditioncaught
sb-thread:signal-semaphorecompletion
error
caught
setfconditioncaught
sb-thread:signal-semaphorecompletion
if
sb-thread:wait-on-semaphorecompletion:timeouttimeout
valuestresultcondition
valuesnilnilnil
defunshader-lab-window-snapshot

Inspect frame's actual top-level mirror and native canvas on its process.

let*
sheet
frame-top-level-sheetframe
port
andsheet
portsheet
mirrors
and
typepport'luv-port
port-mirrorsport
direct-mirror
andsheet
sheet-direct-mirrorsheet
canvas
and
typepdirect-mirror'luv-mirror
mirror-targetdirect-mirror
problemsnil
unlesssheet
push"no top-level sheet"problems
unless
typepport'luv-port
push"frame is not on a luv port"problems
unless
=
lengthmirrors
1
push
formatnil"expected one mirror, found ~D"
lengthmirrors
problems
unless
anddirect-mirror
memberdirect-mirrormirrors:test#'eq
push"direct mirror is not registered on the port"problems
unless
typepdirect-mirror'luv-mirror
push"top-level sheet has no luv mirror"problems
unlesscanvas
push"mirror has no native canvas"problems
when
push
formatnil"canvas is ~S"
problems
when
push"canvas event handler is not its mirror"problems
list:mirror-count
lengthmirrors
:canvas-state:problems
nreverseproblems
defuncapture-shader-lab-process-backtrace
process&key
timeout0.25

Best-effort bounded backtrace capture for an unresponsive frame process.

when
andprocess
sb-thread:thread-alive-pprocess
let
completion
sb-thread:make-semaphore:count0
backtracenil
handler-case
sb-thread:interrupt-threadprocess
lambda
unwind-protect
setfbacktrace
sb-debug:list-backtrace:count30
sb-thread:signal-semaphorecompletion
when
sb-thread:wait-on-semaphorecompletion:timeouttimeout
backtrace
defunshader-lab-health
frame&key
timeout0.5

Return a status and structured frame/process/mirror/canvas health report.

check-typeframeshader-lab
let*
state
frame-stateframe
process
shader-lab-processframe
alive-p
or
nullprocess
sb-thread:thread-alive-pprocess
start
get-internal-real-time
units
coerceinternal-time-units-per-second'double-float
report
if
eq:disownedstate
make-instance'shader-lab-health-report:status:closed:frame-statestate:process-alive-palive-p
multiple-value-bind
completed-psnapshotcondition
let*
latency
/
-
get-internal-real-time
start
units
problems
andsnapshot
getfsnapshot:problems
status
cond
condition:unresponsive
notcompleted-p
:unresponsive
problems:degraded
t:responsive
make-instance'shader-lab-health-report:statusstatus:frame-statestate:process-alive-palive-p:mirror-count
or
andsnapshot
getfsnapshot:mirror-count
0
:canvas-state
andsnapshot
getfsnapshot:canvas-state
:latencylatency:problems
appendproblems
whencondition
list
princ-to-stringcondition
:backtrace
when
eqstatus:unresponsive
setf
shader-lab-last-health-reportframe
report
values
shader-lab-health-report-statusreport
report
defunrefresh-shader-lab
frame&key
timeout1.0

Refresh definitions on frame's process, returning frame and a health state.

check-typeframeshader-lab
if
eq:disowned
frame-stateframe
valuesframe:closed
multiple-value-bind
completed-presultcondition
declare
ignoreresult
cond
condition
valuesframe:unresponsivecondition
completed-p
valuesframe:refreshednil
t
valuesframe:unresponsivenil
defuncapture-shader-lab-screenshot
framepathname&key
timeout10.0

Redisplay frame and capture its direct-GPU McCLIM presentation.

check-typeframeshader-lab
multiple-value-bind
completed-presultcondition
call-in-shader-lab-processframe
lambda
redisplay-frame-panesframe:force-pt
let*
sheet
frame-top-level-sheetframe
mirror
andsheet
sheet-direct-mirrorsheet
unless
typepmirror'luv-gpu-mirror
error"Shader lab requires a direct-GPU McCLIM mirror."
repaint-gpu-mirrormirror:present-pnil
timeout
cond
condition
errorcondition
notcompleted-p
error"Shader lab screenshot timed out after ~,2F seconds."timeout
tresult
defuncapture-default-shader-lab-screenshot
pathname&keyspecification
server-path'
:luv-gpu
title"Luv mathematical shader browser"

Open a callback-only shader lab, capture it, and tear it down.

let*
current-definition
ifspecification
firstdefinitions
seconddefinitions
port
find-port:server-pathserver-path
manager
or
first
climi::frame-managersport
make-instance'luv-frame-manager:portport
unwind-protect
progn

This frame only needs to paint once. Avoid starting a durable command loop merely to photograph its real mirror texture.

setfframe
make-application-frame'shader-lab:frame-managermanager:definitionsdefinitions:current-definitioncurrent-definition:lowering
shader-definition-entry-loweringcurrent-definition
:enablet
setf
frame-pretty-nameframe
title
whenframe
destroy-frameframe
defunopen-shader-lab
&keyspecificationspecificationspipelines
server-path'
:luv-gpu
startup-timeout10.0
title"Luvcraft material and shader workbench"

Open a live-definition, expression, and SSA workbench on luv's backend.

pipelines may contain a running demo's live shader artifacts; their installed revision and last diagnostic then appear alongside the source definition.

whenspecification
check-typespecificationluv.shader:shader-specification
let*
current-definition
firstdefinitions
port
find-port:server-pathserver-path
manager
or
first
climi::frame-managersport
make-instance'luv-frame-manager:portport
startup-errornil
startup-signaled-pnil
startup-completion
sb-thread:make-semaphore:count0
labels
run
handler-case
progn

Presentation gestures are read by the application frame's command loop, not SDL's native event thread. Construct and run the frame in one durable process.

setfframe
make-application-frame'shader-lab:frame-managermanager:definitionsdefinitions:current-definitioncurrent-definition:lowering
shader-definition-entry-loweringcurrent-definition
setf
frame-pretty-nameframe
title
setfstartup-signaled-pt
sb-thread:signal-semaphorestartup-completion
unwind-protect
run-frame-top-levelframe
when
frame-managerframe
disown-framemanagerframe
error
condition
unlessstartup-signaled-p
setfstartup-errorcondition
sb-thread:signal-semaphorestartup-completion
errorcondition
let
process
clim-sys:make-process#'run:name"Luvcraft material and shader workbench"
unless
sb-thread:wait-on-semaphorestartup-completion:timeoutstartup-timeout
ignore-errors
clim-sys:destroy-processprocess
error"Shader lab did not create its frame within ~,2F seconds."startup-timeout
whenstartup-error
errorstartup-error
setf
shader-lab-processframe
process
frame
defunclose-shader-lab

Destroy an open-shader-lab frame and its luv canvas.

check-typeframeshader-lab
unless
eq:disowned
frame-stateframe
let
process
shader-lab-processframe
ifprocess
clim-sys:process-interruptprocess
lambda
frame-exitframe
destroy-frameframe
nil