In-process Multi-process Vulkan backend

Architecture Overview

System topology, runtime modes, project structure, and core design decisions.

Visual architecture maps

Diagrams for multiproc IPC, render pipeline, data model, and runtime modes.

View all diagrams

Visual Overview

Full-size diagrams for runtime topology, rendering, data model, and live topics.

Data Model

Stable object graph from App through Figure, 2D/3D axes, and series types. Python proxies mirror this hierarchy over IPC.

Spectra data model hierarchy from App through Figure to Axes and Series types

Render Pipeline

State mutations on the app thread become draw lists on the render thread. Uploads, SPIR-V shaders, and ImGui share the Vulkan swapchain pass.

Spectra render pipeline from state change through Renderer and VulkanBackend to GPU

High-Level Layers

API Layer

  • Easy API one-liners
  • Object API: App / Figure / Axes / Series
  • Python proxies over IPC

UI + Interaction

  • Input handling and gestures
  • Docking, tabs, split view
  • Command / undo / workspace systems

Rendering Backend

  • Vulkan command pipeline
  • Per-window swapchain contexts
  • Headless and on-screen rendering

System Topology

How components are arranged in the default in-process binary versus the multiproc daemon + agent layout.

Inproc Mode (default)

One build/spectra process owns UI managers, plot state, and the Vulkan render thread. Best for desktop apps and lowest latency.

Spectra inproc runtime: UI, plot state, and render thread inside a single App process

Multiproc Mode (IPC)

Clients connect over Unix sockets to spectra-backend; window agents handle Vulkan and ImGui. Default for Python show() and orchestrated sessions.

Spectra multiproc topology with backend daemon and window agents

Runtime Modes

ModeDescriptionWhen to Use
In-process UI, renderer, and plotting state in one process Desktop apps, low-latency interactive use
Multi-process Backend daemon + window/agent processes via IPC protocol Isolation, orchestration, Python-driven sessions

Mode Selection

ConditionMode
AppConfig::socket_path is setMultiproc (connects to spectra-backend)
SPECTRA_SOCKET env var is setMultiproc
NeitherInproc (default, single-process)
Both code paths are always compiled — mode is selected at runtime (no #ifdef).

Mode selection flow

SPECTRA_RUNTIME_MODE, AppConfig::socket_path, or SPECTRA_SOCKET pick inproc vs multiproc at startup.

Spectra runtime mode selection: inproc single binary or multiproc backend and agents

Key Design Decisions

  • Vulkan 1.2+ — Explicit memory management, headless rendering, async buffer uploads, depth buffer for 3D, MSAA
  • Screen-space SDF rendering — Lines and markers use signed-distance-field anti-aliasing; resolution-independent at any zoom
  • GPU-accelerated styling — Dash patterns and 18 marker types rendered entirely in fragment shaders
  • GPU text pipeline — Vulkan text rendering with stb_truetype atlas, depth-tested 3D labels
  • Lock-free threading — SPSC ring buffer decouples the user's app thread from the GPU render thread
  • No global state — All managers are stack-allocated and passed by pointer; thread-safe via std::mutex
  • No primary window — All OS windows are peer-equivalent, managed uniformly by WindowManager
  • Stable figure IDsFigureId typedef with FigureRegistry replaces positional indexing
  • Runtime dual-mode — Inproc vs multiproc selected at runtime, both code paths always compiled
  • Header-only math — Self-contained vec3/vec4/mat4/quat library (~350 LOC); no GLM dependency
  • Workspace backward compat — v4 format loads v1/v2/v3 files with sensible defaults
  • IPC protocol — Versioned TLV binary protocol with request_id correlation, seq ordering, snapshot + diff

Rendering Safety Principles

  • Fence-aware frame lifecycle — never destroy resources without waiting on fences
  • Swapchain recreation paths for resize / VK_ERROR_OUT_OF_DATE_KHR
  • No per-frame pipeline rebuilds or descriptor pool allocations in hot paths
  • No vkDeviceWaitIdle() inside the frame loop
  • Safe resize sequence: wait fences → destroy → recreate swapchain → recreate framebuffers → update projection → re-record
  • Validation-focused CI with golden regression tests via lavapipe

Project Structure

spectra/
├── include/spectra/       # Public headers: spectra.hpp, easy.hpp, math3d.hpp,
│                          #   plot_style.hpp, axes.hpp, axes3d.hpp, series.hpp,
│                          #   series3d.hpp, fwd.hpp, ...
├── src/
│   ├── core/             # Figure, Axes, Axes3D, Series, Series3D, layout, coords
│   ├── render/           # Renderer, TextRenderer, abstract Backend interface
│   │   └── vulkan/       # VulkanBackend, device, swapchain, pipeline, buffers,
│   │                     #   WindowContext
│   ├── gpu/shaders/      # GLSL 450: line, scatter, grid, text, surface3d, mesh3d
│   ├── anim/             # Animator, easing, frame scheduler, frame profiler
│   ├── ui/               # App, WindowManager, FigureManager, DockSystem,
│   │                     #   ThemeManager, CommandRegistry, ShortcutManager,
│   │                     #   UndoManager, TransitionEngine, TimelineEditor,
│   │                     #   KeyframeInterpolator, AnimationCurveEditor,
│   │                     #   CameraAnimator, ModeTransition, Inspector,
│   │                     #   DataInteraction, AxisLinkManager, DataTransform,
│   │                     #   RecordingExport, Workspace, PluginAPI, CsvLoader
│   ├── ipc/              # IPC protocol: message types, TLV codec, transport
│   ├── daemon/           # spectra-backend: FigureModel, SessionGraph,
│   │                     #   ClientRouter, ProcessManager
│   └── agent/            # spectra-window: agent main loop, snapshot→Figure
├── python/
│   ├── spectra/          # Python package: Session, Figure, Axes, Series,
│   │                     #   easy API, codec, transport
│   ├── examples/         # Python example scripts
│   └── tests/            # Python test suite (50+ tests)
├── examples/             # 40+ C++ example programs
├── tests/
│   ├── unit/             # 1,200+ unit tests (Google Test)
│   ├── golden/           # Golden image tests (2D + 3D phases)
│   ├── bench/            # Performance benchmarks (100+)
│   └── util/             # MultiWindowFixture, ValidationGuard, GpuHangDetector
├── docker/               # Docker Compose + Dockerfile
├── packaging/            # AppImage, AUR, Homebrew, shell completions
├── third_party/          # stb_image, stb_image_write, stb_truetype, VMA
├── plans/                # Architecture plans, roadmap, UI redesign spec
├── cmake/                # CompileShaders, EmbedShaders, EmbedAssets, config
├── .github/workflows/    # CI + Release pipeline
├── version.txt           # Single source of truth: 0.1.0
├── Makefile              # Developer workflow shortcuts
└── CMakeLists.txt        # Root build configuration

Deep Dives

Contributing Guidelines

The codebase is organized into independent modules — see plans/agents_plan.md for the module decomposition.

  1. C++20 — No global state, RAII throughout, thread-safe via std::mutex
  2. Public headers — Keep include/spectra/ minimal; implementation in src/
  3. Tests required — Add unit tests for new functionality; run ctest before submitting
  4. No speculative fixes — Measure first (add instrumentation, capture timing) before optimizing
  5. Vulkan safety — Never destroy resources without waiting on fences; follow the safe resize sequence
  6. Window independence — No "primary window" assumptions; all windows must behave identically
# Development workflow
make build test     # Build + run tests
make format         # clang-format
make pip-dev        # Python dev install
cd docker && docker compose up --build spectra-xvfb