luv

Workshop wiki

main.lisp

luvcraft/main.lisp

system luvcraft/program · 19 definitions · on GitHub

in-package#:luvcraft
defunexecutable-directory
uiop:pathname-directory-pathname
truenamesb-ext:*runtime-pathname*
defunslynk-endpoint-pathname
merge-pathnames#P"luvcraft.slynk"
defunrequested-slynk-port
let
value
uiop:getenv"LUVCRAFT_SLYNK_PORT"
ifvalue
let
port
parse-integervalue:junk-allowedt
unless
andport
<=0port65535
string=value
formatnil"~D"port
error"LUVCRAFT_SLYNK_PORT must be an integer from 0 through 65535, not ~S."value
port
0
defunendpoint-owned-p
pathnamepidport
with-open-file
streampathname:if-does-not-existnil
andstream
let
*read-eval*nil
and
eqlpid
readstreamnilnil
eqlport
readstreamnilnil
defunpublish-slynk-endpoint
pathnamepidport
ensure-directories-existpathname
with-open-file
streampathname:direction:output:if-exists:supersede:if-does-not-exist:create
formatstream"~D ~D~%"pidport
defuncall-with-slynk
setfslynk:*log-output*
make-broadcast-stream
let*
pid
sb-posix:getpid
port
slynk:create-server:interface"127.0.0.1":port:dont-closet
unwind-protect
progn
publish-slynk-endpointendpointpidport
formatt"Luvcraft Slynk is ready on 127.0.0.1:~D (pid ~D).~%"portpid
formatt"Attach with ./sly --luvcraft COMMAND ...~%"
finish-output
funcallfunction
when
endpoint-owned-pendpointpidport
ignore-errors
delete-fileendpoint
defunusage
&optional
stream*standard-output*
formatstream"Usage: luvcraft [--metal | --vulkan] [--tracy] [--fullscreen] [--world FILE | --birthday]~%"
formatstream" luvcraft [--help | --smoke-test PNG | --vulkan-smoke-test PNG | --metal-smoke-test PNG | --metal-text-closeup PNG | --metal-benchmark [FRAMES [CSV [SCENARIO [DENSITY]]]]]~%"
formatstream"~%"
formatstream"With no arguments, resume the world using Metal 4 on macOS and Vulkan elsewhere.~%"
formatstream"--metal and --vulkan explicitly select an interactive backend.~%"
formatstream"--tracy exposes live frame and worker zones to Tracy 0.14.0.~%"
formatstream"--fullscreen opens the game on the whole display instead of in a window.~%"
formatstream"--world loads or creates the named persistent world.~%"
formatstream"--birthday opens directly into the persistent birthday party.~%"
formatstream"--smoke-test renders one hidden frame with the platform default and exits.~%"
formatstream"--vulkan-smoke-test renders one hidden Vulkan frame and exits.~%"
formatstream"--metal-smoke-test renders one hidden Metal 4 frame and exits.~%"
formatstream"--metal-text-closeup renders the enlarged Slug world-text proof.~%"
formatstream"--metal-benchmark measures steady or streaming Metal frames; DENSITY is standard or retina.~%"
formatstream"--serve-surface renders a hidden game into the IOSurface named on stdin.~%"
defunmake-metal-provider
#+darwin (make-instance 'luv:metal-gpu-provider)#-darwin
error"The Metal backend is only available on Darwin."
defunrun-interactive
&keyprovidertracy-pfullscreen-pbirthday-p

Run luvcraft until its native window closes.

Start before start-luvcraft creates the producer. Tracy thread names are emitted by the threads themselves as they begin, so attaching later would leave an otherwise useful worker lane anonymous.

ifbirthday-p
progn
luvcraft.birthday:celebrate-birthday:provider:fullscreen-pfullscreen-p
play:provider:tracy-ptracy-p:fullscreen-pfullscreen-p:world-pathnameworld-pathname
unwind-protect
let
session*session*

Native close begins orderly teardown beside SDL's event loop; that teardown closes the canvas last. Keep the executable alive until the native loop has observed that final close.

loopuntil
eq:closed
luv:canvas-state
luvcraft-session-canvassession
do
sleep0.05
let
failure
luv::sdl-canvas-startup-error
luvcraft-session-canvassession
whenfailure
errorfailure

Native teardown reports through the controller rather than from its worker thread. Surface that exact result in the executable.

unless
eq:running
stop-controller-state
luvcraft-session-stop-controllersession
wait-for-controlled-stop
luvcraft-session-stop-controllersession
defunparse-interactive-options
arguments
let
providernil
tracy-pnil
fullscreen-pnil
birthday-pnil
world-option-pnil
loopwhileargumentsforargument=
poparguments
do
cond
string=argument"--metal"
string=argument"--vulkan"
string=argument"--tracy"
setftracy-pt
string=argument"--fullscreen"
setffullscreen-pt
string=argument"--birthday"
setfbirthday-pt
string=argument"--world"
unlessarguments
error"--world requires a pathname."
setfworld-option-ptworld-pathname
pathname
poparguments
t
return-fromparse-interactive-options
valuesnilnilnilnilnilnil
when
andbirthday-pworld-option-p
error"--birthday uses its own persistent party world and cannot be combined with --world."
valuesproviderworld-pathnametracy-pfullscreen-pbirthday-pt
defunrun-smoke-test
pathname&optionalprovider
formatt"Rendering ~A~%"pathname
formatt"Wrote ~A~%"
truenamepathname
defunrun-metal-text-closeup
pathname
formatt"Rendering Slug text close-up ~A~%"pathname
formatt"Wrote ~A~%"
truenamepathname
defunparse-frame-count
argument
let
count
parse-integerargument:junk-allowedt
unless
andcount
pluspcount
string=argument
formatnil"~D"count
error"Frame count must be a positive integer, not ~S."argument
count
defunparse-benchmark-scenario
argument
cond
or
nullargument
string=argument"steady"
:steady
string=argument"streaming"
:streaming
t
error"Benchmark scenario must be steady or streaming, not ~S."argument
defunparse-benchmark-density
argument
cond
or
nullargument
string=argument"standard"
nil
string=argument"retina"
t
t
error"Benchmark density must be standard or retina, not ~S."argument
defunrun-metal-benchmark
&optionalframe-countpathnamescenariodensity
benchmark-luvcraft-frame-performance:frame-count
ifframe-count120
:scenario:high-pixel-density-p:csv-pathname
or
andpathname
pathnamepathname
#P"build/luvcraft-metal-benchmark.csv"
defundispatch
arguments
cond

Started inside a playing game's terminal wall: be its child.

and
nullarguments
#+darwin(luvcraft-parent-socket-path)#-darwinnil
and
=
lengtharguments
1
member
firstarguments
'
"--help""-h"
:test#'string=
and
=
lengtharguments
2
string=
firstarguments
"--smoke-test"
run-smoke-test
pathname
secondarguments
and
=
lengtharguments
2
string=
firstarguments
"--metal-smoke-test"
and
=
lengtharguments
2
string=
firstarguments
"--vulkan-smoke-test"
and
=
lengtharguments
2
string=
firstarguments
"--metal-text-closeup"
and
=
lengtharguments
1
string=
firstarguments
"--serve-surface"
#+darwin(serve-luvcraft-mirror)#-darwin
error"--serve-surface needs IOSurface, which is Darwin only."
and
<=1
lengtharguments
5
string=
firstarguments
"--metal-benchmark"
run-metal-benchmark
secondarguments
thirdarguments
fourtharguments
fiftharguments
t
multiple-value-bind
providerworld-pathnametracy-pfullscreen-pbirthday-pinteractive-p
ifinteractive-p
run-interactive:providerprovider:tracy-ptracy-p:fullscreen-pfullscreen-p:birthday-pbirthday-p:world-pathnameworld-pathname
progn
usage*error-output*
error"Invalid luvcraft arguments: ~{~A~^ ~}"arguments
defunmain
handler-case
call-with-slynk
lambda
luv:call-with-sdl-main-thread
lambda
dispatch
uiop:command-line-arguments
finish-output*standard-output*
finish-output*error-output*
error
condition
format*error-output*"luvcraft: ~A~%"condition
finish-output*error-output*