atagen

monolith

public
Star0
Watch0
189b5d01e76ff8c5598e821788f769777debeb30
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git
research/wry-assessment.mdMarkdown118 lines8.6 KB

What monolith should take from jay/wry

Companion to wry-reports.md, which holds the raw findings and citations.

The async runtime

Don’t port it. Port the phase discipline.

Why it doesn’t pay off inside a smithay compositor.

  • Most of jay’s I/O is client sockets. In smithay those belong to wayland-backend, which reads and writes through its own readiness loop in dispatch_clients/flush_clients. Moving to io_uring would leave only DRM events, udev, libinput and timers on the ring, a handful of completions per frame.
  • Even inside jay the raw speed win is small. A frame costs on the order of tens to low hundreds of syscalls, well under 1% of a 6.9 ms frame at 144 Hz. Input-to-photon latency is decided by when you render, not by how cheaply you wake up.
  • Tasks can’t hold &mut State, so jay runs on Rc<State> with Cell/CloneCell/CopyHashMap everywhere. Smithay’s handler traits hand you &mut D. Running both models means fighting every delegate.
  • There is no fallback when io_uring is unavailable (kernel.io_uring_disabled, hardened kernels, some sandboxes). Jay exits.
  • Every smithay helper that is a calloop EventSource (DrmDeviceNotifier, LibinputInputBackend, XWayland, DrmSyncPointSource, DmabufSource, the socket listener) would need rewrapping.

What it does well, and the calloop equivalent.

jay featurereal benefitin monolith
Four ordered phases fed by dirty queuesN events collapse into one layout and one render per pass, with deterministic orderingFixed stages in the post-dispatch closure (layout, derived state, animation tick, render, flush), each with a dirty set and a scheduled flag
now() frozen per passEvery animation computed in a pass sees one timestampStore an Instant in State at the top of the post-dispatch closure
Async fns for sequential flows (present loop, xwm, dbus, pipewire)Readable state machinesExplicit enum for the present loop, calloop’s executor for portal and screencast flows, and x11rb/zbus/pipewire-rs for the protocols
Cancel-on-drop tasksStructured lifetimesasync_task::Task also cancels on drop
Linked timeouts on client sendmsgA stuck client can’t stall the compositorwayland-backend flushes nonblocking already

Worth taking, ranked

1. Deadline frame scheduler

src/backends/metal/present.rs, flip handling in src/backends/metal/video.rs.

Biggest latency payoff, and it slots straight into smithay because DrmCompositor leaves timing to the caller. Sleep until next_vblank - pre_margin - post_margin, then latch, render and commit.

  • pre_margin is a decaying per-second max of measured wakeup-to-latch CPU time.
  • post_margin grows 500 µs per second that saw a missed flip and decays toward the device minimum otherwise.
  • Vblank timestamps come from queued CRTC_SEQUENCE events, with emulation when the driver returns EOPNOTSUPP.

This is an algorithm port, a few hundred lines. With a Vulkan renderer, GPU time needs to be covered too, either through post_margin misses as jay does or with timestamp queries.

2. Async shm upload pipeline

src/cpu_worker.rs, src/gfx_apis/vulkan/transfer.rs, src/clientmem.rs.

Smithay’s GLES renderer uploads shm synchronously inside import_shm_buffer on the main thread. Jay keeps the commit blocked while a worker thread memcpys only damaged rows into a staging buffer, and the GPU finishes the copy on the transfer queue. Sealed memfds (F_SEAL_SHRINK plus a large enough size) let the worker read client memory without the thread-local SIGBUS dance. foot, software-rendered toolkits and Xwayland without glamor all take this path. Build it into monolith’s ImportMemWl as a smithay Blocker.

3. Vulkan renderer internals as a reference

Smithay has no Vulkan renderer, so monolith writes one either way. Jay’s ~10k lines are coupled to cmm, theme, State, the ring and the cpu worker, so lift modules and ideas rather than the crate.

  • fp16 linear blend buffer with a resolve pass. Blending is correct and HDR-ready, and color transforms happen in one place.
  • Op list sorted and batched by pipeline key, one queue_submit2 per frame.
  • Vertex data via buffer device address in push constants, instanced draws.
  • Specialization constants for EOTF, matrix and alpha mode instead of runtime branches.
  • Descriptor heap, then descriptor buffer, then push descriptor tiers.
  • Timeline semaphores mapped to DRM syncobj points, sync_file import/export for implicit sync.
  • Global-priority graphics and transfer queues (src/gfx_apis/vulkan/device.rs:448-528).
  • Offline shaderc compilation with hash tracking.

Implement smithay’s Renderer, Frame, Bind<Dmabuf>, Offscreen, ImportDma, ImportMemWl and ExportMem so that DrmCompositor, OutputDamageTracker and the element system work unmodified. Frame calls append to the op list and finish records and submits. Jay stops at rounded rects, so blur and shadows are new work. They would be extra op kinds or custom RenderElements.

4. Commit blocker taxonomy

Smithay already has per-client transaction queues and Blocker. Jay’s contribution is the list of things a commit waits on, all treated uniformly.

  • implicit dmabuf fences
  • syncobj acquire points
  • shm upload completion
  • prime copy completion
  • fifo-v1 barrier
  • commit-timing-v1 deadline, released by the scheduler’s before-latch hook
  • layout transaction serial

Each becomes a smithay Blocker or pre-commit hook. The commit-timing integration with the deadline scheduler is the subtle one.

5. Two-timeline tree, transactions, multiphase animations

SplitView/TreeLink, LiveTL/RenderTL, src/transactions.rs and src/tree_serial_groups.rs are upstream jay. src/presentation/ is yours.

LiveTL is what clients have been configured to and RenderTL is what is on screen. RenderTL advances only when every affected client has acked and committed, or after a 50 ms timeout. Animations are transaction effects that diff the pre and post trees at publication time. Tags are a natural fit. A tag switch changes the visibility and size of many windows at once, which is exactly the case transactions exist for.

  • multiphase.rs is near-pure geometry with 1.7k lines of tests. Lift it almost verbatim.
  • Retained snapshots from layout_animation.rs, where the old texture is scaled to the animated rect while the client catches up, port as a concept onto smithay elements.
  • Reimplement transactions and configure serial groups against smithay’s xdg-shell configure/ack and Blockers.

6. Integration test harness

src/it/.

An in-process compositor on a headless backend, real-socket clients, zeroed timeouts, tree-invariant verification after every idle point, and golden-pixel QOI comparisons. Use wayland-client or smithay-client-toolkit in place of jay’s wl_usr. An animation-heavy compositor needs this from the start.

7. Small items

  • SCHED_RR with SCHED_RESET_ON_FORK, with CAP_SYS_NICE parked on a helper thread (src/utils/nice.rs, src/pr_caps.rs).
  • Tracy zones named per task.
  • KMS hygiene. Reset unknown properties to defaults at init, retry device init with features disabled, TEST_ONLY before modesets, roll back on failure.
  • VRR cursor throttling (src/output_schedule.rs), so cursor motion doesn’t pin VRR at max refresh.
  • Lazy Xwayland startup on the first X connection.

Skip

  • Bespoke wire protocol, codegen and wl_usr. Smithay owns this layer.
  • Homegrown xcon, dbus and pipewire stacks. Use x11rb via smithay’s X11Wm, zbus and pipewire-rs.
  • Forker process. std::process::Command uses posix_spawn and is safe from a threaded process. Set env, rlimits and sched policy on the Command.
  • The Rc plus cell utility collection, which only exists because of jay’s executor.
  • Jay’s plane assignment, which never uses overlays. DrmCompositor already assigns overlays.
  • metal_cm KMS color pipelines for now. It is large and driver-quirky. Keep the renderer’s color math shaped so it can slot in later.
  • SQLite session manager, unless session restore becomes a goal.

Gaps smithay leaves

  • No tearing/async page flip control in DrmCompositor. Needs an upstream patch or a custom commit path.
  • No KMS color pipeline, CTM/gamma or HDR metadata handling.
  • No tearing-control-v1 or color-management-v1 protocol helpers.

License

jay and wry are GPL-3.0-only. Copying code from them makes monolith GPL-3.0. Smithay is MIT, which is compatible with that. src/presentation/ is your own new code and can be relicensed freely. Jay-authored code (scheduler, shaders, transfer path) can only be reimplemented from the design if monolith is meant to be permissive.