VexelRay
VexelRay framework · 0.1

Desktop software, drawn live on the GPU.

You write Java 25 and ship a native executable for Windows or Linux that draws with Vulkan. Everything between the two is built to be fast, deterministic and easy to observe.

0fpswhen nothing changes and the window is in the background
1.03msmedian from waking to the first frame, starting from idle
1drawcall for a whole window when it shows no images
577nsfor a clock handoff, measured in the native-image build
01 GUI

A retained tree, drawn immediately, only on demand.

You change widgets through thread-safe handles from any thread. The GUI thread takes those changes once per frame and draws the whole window with one SDF uber-shader. If nothing is moving and no input arrives, the loop sleeps and draws nothing.

  • 140 → 0 fpsA still window drops to 5 fps when focused and 0 fps in the background
  • 1.03 msMedian wake to first frame (p95 1.6 ms)
  • 1 draw callShadows, lighting and text are all in that one call
  • Build-failingArchitecture rules are tests: palette, layering, model writers, sync seams
vexelray-gui
Frame loop · live
idle
0frames / s

Move your pointer over this panel. The meter only draws a frame when there's input or something is animating, the same way the loop does.

02 Concurrency

Multithreaded by default. Checked by the compiler.

There are exactly five lanes. The main thread keeps Vulkan, the window and the present, and nothing else. App logic runs on component threads, disk work on a bounded offload lane, and time on its own timeline. The annotation processor decides placement at compile time, so the binary has no scheduler and no work stealing.

  • 5 lanesmain, timeline, component, handler, offload. The list is closed
  • 33 rules19 of them are enforced by a test or the type system. A blocking cycle in the message graph is a compile error
  • WatchdogA lane that hangs is reported by name. It takes only its own thread down, never the window
  • Compute queueA Vulkan compute queue can be lent to one component, so physics never blocks a frame
vexelray-framework
Lanes
watchdog: all lanes responsive

Illustration. All lanes are platform threads, and placement is fixed in the binary.

03 Agent tooling

Ottermate. The agent looks at its own work.

Most of the stack was written with Claude Code, Anthropic's coding agent, working alongside its author. An agent that only checks that the code compiled hasn't really checked anything. Debug builds have an automation port, and ottermate uses it to launch the app, click, type and wait for it to settle, then take a screenshot with the app's own GPU.

  • --automation=0Chooses a free port and prints it, so parallel runs never collide
  • Loopback onlyOff by default, and linked only into debug builds
  • By role, not pixelNodes are addressed by role, name or landmark. The pointer moves across the screen, so hover fires
  • settleWaits for the frame loop and the animation timeline to go quiet, so no screenshot is stale
  • CLAUDE.mdThe framework and the GUI carry one with the rules the code doesn't show, and every generated project starts with one
Building with an LLM
agent session

        

An example session, shortened.

04 Rendering

Shaders built from code. Themes made of looks.

Shaders are written as SupirVast IR in Java and lowered to SPIR-V at build time. That same IR also runs on the CPU, and a test suite checks that the CPU and GPU agree. The uber-shader is assembled from shadelets, a chain of source, modifiers, painters and composite. A look is one such chain with its styles. Hover and pressed are simply different looks.

  • 4 techniquesCanvas, panel, mesh and SDF ray-march, composited into one frame on one device
  • 27 floatsA fixed vertex size, however many effects an app uses
  • 4×10⁻⁶The largest difference between CPU and GPU results across the differential suite
  • 9 numbersA palette is nine authored values. Hover and press are one signed lightness step in Oklab
supirvast
One element · three looks
Box→filloutlineglowshadowemboss→composite→clip

Mimicked in CSS on this page. In VexelRay each look is a set of painters inside the one uber-shader.

05 Time

Kronometer. A clock you can unit-test.

It is built like ChucK's clock and Vue's graph. A Shred runs in zero logical time between advance(ms(250)) calls, so it can't drift and can't race. Signals form a dependency graph, and each knows how far ahead its value is fixed, so a pure animation is computed in advance and reading it at now is just a buffer index. Swap in the virtual clock and a ten-minute UI scenario runs in microseconds.

  • 577 nsA handoff under native-image, about 2,900 of them in a tenth of a 60 Hz frame
  • 0 handoffsfor ten thousand animations written as Signals
  • Exact ratiosNested tempos use exact Ratios, not doubles. Eases land exactly on 0 and 1
  • Rate domainsFixed, dynamic, 48 kHz audio with lookahead, and dilated worlds that slow down instead of skipping
kronometer
Kron.virtual()

Three easings driven by one logical clock. Each run is identical, frame for frame.

06 Messaging

Atchung. One topic, any transport.

Inside the VM, messages go over a zero-copy bus with versioned, lock-free state snapshots. When a message has to leave the process, elektro-Q carries the same topic over TCP, a Unix socket or UDP, with codecs generated at compile time from @Message records. The fast in-VM path never pays for the network.

  • 4 transportsin-VM, TCP, Unix domain sockets, and UDP netcode with sequencing, acks and a network simulator
  • 5 policiesFor backpressure: drop oldest, drop newest, coalesce latest, block or fail
  • 0 reflectionNo dependencies. Delivery is inline, async or pumped
  • BridgedElektroBridge carries a local topic across the wire in both directions, with loop prevention
atchung
Topic<Frame>
Topic @Message record in-VM0-copy TCP Unix socket UDP netcode
07 Toolchain

Develop on the JVM. Ship a native executable.

You write ordinary Java 25 with dependency injection in the Spring Boot style. An annotation processor does the wiring at compile time, so there is no reflection and the app starts as fast as a hand-written main. GraalVM native-image then turns it into one native executable, for Windows or Linux. The bindings to Win32, X11 and Vulkan use Panama FFM directly, with no LWJGL, GLFW or SDL.

  • Java 25Maven and the JVM while you develop, GraalVM native-image when you release
  • 0 reflectionInjection is generated by the annotation processor, so native-image needs no configuration for it
  • 5 MB heapStays flat under load, with 17 threads throughout
  • 30–40 sFor a native build of an application
Getting started
Build
1
Java 25 source@Configuration · @Provides · @Component
you
2
Annotation processingwiring, lanes, message graph and codecs
javac
3
SupirVast → SPIR-Vshaders and MSDF font atlases built by Maven plugins
mvn
4
GraalVM native-imageone native executable, with Panama FFM bindings to Win32 or X11, and to Vulkan; sizes on Windows
calculator 38.4 MBpix 41.5 MBvexplore 43.6 MBfluid-sim 57.7 MB
native
08 Distribution

One line installs. The same line updates.

The installer generator writes each app's installer, updater and uninstaller from a single installer.json, and writes the suite's one-line install as well. Installs are per user and need no administrator. Each app gets its own entry in Settings. The apps find and launch each other through the install registry.

  • SHA-256Every download is checked, and nothing is written to disk until all of them pass
  • No adminInstalls under your user only, and the uninstaller removes exactly what was installed
  • Re-run = updateEach executable's version is compared, and an app that is already current is left alone
  • GeneratedInstallers, manifests and this site's install page all come from one generator
vexelray-installer
Windows · PowerShell
irm https://sibarum.github.io/install.ps1 | iex
manifest.json fetched
install.ps1 matches manifest SHA-256
release binary matches SHA-256
all downloads verified, writing
shortcuts, PATH, Settings › Apps

Windows 10 or 11, 64-bit, with a Vulkan driver. What it changes. On Linux, one line of sh installs the snapshot builds: get it here.

09 Data

Intrabuf. Binary, at nanosecond speed.

An annotation processor writes a straight-line codec for each record, with no reflection, so it works under native-image. Fields are stored by position with no tags. Integers are zigzag varints, and nulls and booleans share one bitset. A structural fingerprint catches schema drift. Every payload also has a readable text form.

  • ~14 / 12 nsTo encode / decode a 63-byte record
  • 8 BHeader in BACKWARD and FULL modes (12 B in STRICT)
  • 3 modesSTRICT, BACKWARD and FULL compatibility, plus snapshot drift detection
  • CLIA native intrabuf inspector, and fromBytes accepts either form
intrabuf
Wire layout
record SensorReading(long id, Double temp, boolean ok, String unit)
headernull + bool bitsetzigzag varintfixed / bytes
~14 nsencode, 63 B
~12 nsdecode, 63 B

Illustrative layout, not a byte-exact dump. The timings come from a quick loop rather than JMH, so read them as orders of magnitude.

10 And more

Deeper in the stack.

More of the things the stack does underneath that you wouldn't expect from a desktop framework.

Enclosure

Plots that can't lie

Curves are evaluated with interval arithmetic into an enclosure that provably contains every value. The arithmetic finds poles and asymptotes, so a plot never draws a line through one.

6,580 glyphs

MSDF text, one draw

Noto Sans and Noto Mono are baked into MSDF atlases at build time. Shadow, lit edges and letterpress are transfer functions over one rounded-box SDF, with no textures and no extra passes.

2 queues

Physics on its own queue

The fluid sim is two-fluid MLS-MPM, with water riding on mercury at 13.6:1. Rigid bodies use XPBD with Coulomb friction, at 1.2 ms a step for 4,096 spheres. Both run on a second Vulkan queue.

Proved

Determinism, in Lean

Lean proofs cover the fluid's fixed-point particle-to-grid scatter. It produces the same grid under any atomic ordering, and its quantised shares conserve mass and momentum exactly.

15+ formats

Decoded onto the GPU

Images from PNG to QOI and SVG. Video in H.264, HEVC, VP9 and AV1. Meshes in OBJ, PLY and STL. The codec is optional, so an app with no pictures links no decoders.

Flip model

Resizes without stalls

Vulkan draws and a D3D12 flip-model DXGI swapchain presents. Resizing reallocates nothing, which avoids the multi-second stalls hybrid-GPU laptops are known for.

11 Built with

Standing on remarkable shoulders.

VexelRay would not exist without three pieces of other people's work, and we're grateful for each of them.

Anthropic

Claude Code

Most of VexelRay was written with Claude Code, Anthropic's coding agent, working alongside its author: the engine, the framework, the GUI and the applications. Ottermate exists so Claude can see the windows it builds.

Oracle

GraalVM

Oracle GraalVM's Native Image compiles every application ahead of time into a single native executable, for Windows or Linux, that runs without a JVM. Truffle, from the same project, runs SupirVast's shader IR on the CPU.

The Khronos Group

Vulkan

Every pixel VexelRay draws goes through Vulkan, the open, cross-platform graphics and compute API, and every shader is compiled to SPIR-V. The simulations run their physics on Vulkan compute queues.

VexelRay is independent and not affiliated with or endorsed by Anthropic, Oracle or the Khronos Group. The fonts, libraries and other third-party software in the applications are listed with their licenses on the licenses page.

12 Specifications

Spec sheet.

LanguageJava 25, built with Maven
Release binaryGraalVM native-image, one executable per app for each platform (38–68 MB on Windows)
GraphicsVulkan, presented through a DXGI flip-model swapchain. Bindings use Panama FFM directly
ShadersSupirVast IR → SPIR-V at build time. The same IR runs on the CPU through Truffle
GUIRetained node tree, a single SDF uber-shader, flex layout in rem, em, dp, % and viewport units, zoom from 0.5× to 3×
Frame loopDraws on demand. 0 fps when idle, 1.03 ms median wake to frame
Threading5 lanes placed at compile time, platform threads, a watchdog per lane
ClockKronometer: realtime, virtual (deterministic) and driven clocks, and 4 slip policies
MessagingAtchung in-VM bus. elektro-Q across processes over TCP, Unix sockets or UDP
SerializationIntrabuf: generated codecs, positional varint format, text form
AutomationLoopback automation port in debug builds, driven by the ottermate CLI
InstallOne line, PowerShell on Windows or sh on Linux, per user, SHA-256 verified, and re-running it updates
PlatformsWindows 10 and 11, 64-bit, and 64-bit Linux on X11 or XWayland. The macOS backend is not finished
Status0.1.1, an experimental prerelease, with 0.1.2 snapshots on Linux. Nothing in it is stable yet

See it run.

Nine applications built on the framework, installed with one line. Or build your own from the template, with an agent or without one.