MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
MayaFlux Engine Configuration

settings() runs before MayaFlux::Init(). Anything you set here takes effect when the engine initialises and is locked for the lifetime of the process. Modifying config structs after Init() logs a warning and has no effect.

Defaults are intentionally reasonable: 48 kHz, 512-frame buffer, stereo output, 60 FPS, Vulkan rendering. Leave settings() empty if the defaults are adequate.


Configuration via JSON file

The entire engine configuration can be expressed as a JSON file and loaded in one call before Init(). Every config struct exposes a describe() method used by JSONSerializer; the JSON keys map directly to those field names.

void settings() {
}
bool load_config_from_file(const std::string &path)
Load engine configuration from a JSON file, applying any present fields to the pre-Init config struct...
Definition Config.cpp:189

Fields absent from the file retain their defaults.

The launcher binary loads a config file for you, so no call is needed. It uses mayaflux.json in the project source folder if that file exists, or the file named by --config path/to/file.json. The file is read before settings() runs, so values set in settings() win.

Pass --config-override (a flag, with no path) to reverse the order: settings() runs first and the file is loaded after it. The file then replaces the stream, graphics, input and network sections as a whole, so anything it does not mention returns to its default. The journal options are applied as calls on top of whatever is already set. The same behaviour can be compiled in with the MAYAFLUX_CONFIG_OVERRIDE define.

flowchart LR
subgraph N["Default: settings() wins"]
direction LR
n1["struct defaults"] --> n2["config file replaces<br/>stream, graphics, input, network"] --> n3["settings() edits on top"] --> n4["Init()"]
end
subgraph O["--config-override: the file wins"]
direction LR
o1["struct defaults"] --> o2["settings() edits"] --> o3["config file replaces<br/>stream, graphics, input, network"] --> o4["Init()"]
end

A complete file covering all four sections plus journal:

{
"stream": {
"sample_rate": 48000,
"buffer_size": 256,
"format": "FLOAT64",
"non_interleaved": false,
"output": { "enabled": true, "channels": 2, "device_id": -1, "device_name": "" },
"input": { "enabled": false, "channels": 2, "device_id": -1, "device_name": "" },
"priority": "REALTIME",
"handle_xruns": true,
"stream_latency_ms": 0.0
},
"graphics": {
"target_frame_rate": 60,
"backend_info": {
"device_preference": 0,
"device_index": -1,
"device_uuid": "",
"device_name": "",
"require_presentation": true,
"strict_device_selection": false
},
"surface_info": {
"format": "B8G8R8A8_SRGB",
"color_space": "SRGB_NONLINEAR",
"present_mode": "FIFO",
"image_count": 3,
"enable_hdr": false,
"measure_frame_time": false
},
"resource_limits": {
"max_windows": 16,
"max_staging_buffer_mb": 256,
"max_compute_buffer_mb": 1024,
"max_texture_cache_mb": 2048,
"max_descriptor_sets": 1024,
"max_pipelines": 256
},
"text_config": {
"family": "sans-serif",
"style": "",
"pixel_size": 24,
"atlas_size": 512
}
},
"input": {
"hid": { "enabled": false },
"midi": { "enabled": false },
"osc": { "enabled": false, "receive_port": 8000 },
"serial":{ "enabled": false }
},
"network": {
"udp": { "enabled": false, "default_receive_port": 8000, "default_send_port": 9000 },
"tcp": { "enabled": false, "listen_port": 0 },
"shared_memory": { "enabled": false }
},
"journal": {
"severity": "INFO",
"sink_to_console": false,
"log_file": "",
"disable_components": [],
"disable_contexts": [],
"include_components": [],
"include_contexts": []
}
}

Audio stream: <tt>GlobalStreamInfo</tt>

void settings() {
stream.sample_rate = 48000; // Hz
stream.buffer_size = 256; // frames per callback; lower = less latency, more CPU
stream.output.channels = 2; // stereo out
stream.output.device_id = -1; // -1 = system default
stream.output.device_name = ""; // empty = system default; name takes precedence over id
stream.input.enabled = false; // disabled by default
stream.input.channels = 2;
stream.priority = Core::GlobalStreamInfo::StreamPriority::REALTIME;
stream.handle_xruns = true;
stream.stream_latency_ms = 0.0; // 0 = driver default
}
Core::GlobalStreamInfo stream
Definition Config.cpp:40
Core::GlobalStreamInfo & get_global_stream_info()
Gets the stream configuration from the default engine.
Definition Config.cpp:66

The audio backend (PIPEWIRE, WASAPI, COREAUDIO) is selected at compile time and cannot be changed at runtime. Backend-specific tuning can be passed through stream.backend_options as an unordered_map<string, any>.

StreamPriority options: LOW, NORMAL, HIGH, REALTIME.


Graphics: <tt>GlobalGraphicsConfig</tt>

void settings() {
gfx.target_frame_rate = 60;
// Surface defaults inherited by all windows; individual windows can override.
gfx.surface_info.present_mode = Core::GraphicsSurfaceInfo::PresentMode::FIFO;
gfx.surface_info.format = Core::GraphicsSurfaceInfo::SurfaceFormat::B8G8R8A8_SRGB;
gfx.surface_info.image_count = 3; // triple buffering
gfx.surface_info.enable_hdr = false;
// Default font for Portal::Text
gfx.text_config.family = "sans-serif";
gfx.text_config.pixel_size = 24;
gfx.text_config.atlas_size = 512;
// Resource budgets
gfx.resource_limits.max_texture_cache_mb = 2048;
gfx.resource_limits.max_compute_buffer_mb = 1024;
gfx.resource_limits.max_windows = 16;
}
Core::GlobalGraphicsConfig & get_global_graphics_config()
Gets the graphics configuration from the default engine.
Definition Config.cpp:74

PresentMode options: FIFO (vsync), IMMEDIATE (no vsync), MAILBOX (triple buffer), FIFO_RELAXED.

SurfaceFormat options: B8G8R8A8_SRGB (default), R8G8B8A8_SRGB, R16G16B16A16_SFLOAT (HDR), A2B10G10R10_UNORM, others.

The windowing backend (COCOA on macOS, WAYLAND on Linux, WINDOWS on Windows) is selected at compile time. WindowingBackend::NONE disables windowing entirely for headless/offline use and must be set if no windows are created.

Key repeat timing for native backends (Wayland, Win32, Cocoa) is in gfx.key_repeat_config.

GPU selection

On a machine with more than one GPU, gfx.backend_info decides which one the engine runs on. Every enumerated device is logged during startup with the information needed to pin it: (example)

GPU [0] AMD Radeon RX 7900 XTX (RADV NAVI31) | type=DiscreteGpu driver=MesaRadv (radv)
api=1.4.354 | uuid=00000000030000000000000000000000 | gfx=0 compute=1 transfer=0 |
present=gfx:yes mask:0x7 mesh=yes vram=24560MB pci_bus=3 | score=4623

Devices that cannot be used are listed too, with the reason: no graphics queue family, an API version below 1.3, no VK_KHR_swapchain, or no presentation support on the graphics queue family.

void settings() {
// Prefer a device class. AUTO scores discrete above integrated above virtual.
gfx.backend_info.device_preference =
Core::GraphicsBackendInfo::DevicePreference::DISCRETE;
// Or pin one exactly, by the uuid from the startup log.
gfx.backend_info.device_uuid = "00000000030000000000000000000000";
// Or by a case-insensitive substring of the device name.
gfx.backend_info.device_name = "7900";
// Fail at startup rather than falling back if the selector matches nothing.
gfx.backend_info.strict_device_selection = true;
}

Selectors apply in precedence order: device_index, device_uuid, device_name, then device_preference as a scoring bias. device_index is an index into enumeration order, which is loader and driver dependent, so it is a debugging escape hatch rather than a durable setting. device_uuid is the only selector stable across driver updates and enumeration reordering.

DevicePreference options: AUTO, DISCRETE, INTEGRATED, VIRTUAL, EXTERNAL. In JSON these are integers in that order, since the enum does not currently serialise to a string.

EXTERNAL is a heuristic rather than a device class. Vulkan reports a Thunderbolt eGPU as a discrete GPU, indistinguishable from a built-in one, so EXTERNAL means discrete weighted toward the highest PCI bus number, on the reasoning that an externally attached device sits behind a PCIe switch well above the root complex. It needs VK_EXT_pci_bus_info, which is common on Linux and rare elsewhere; without it, EXTERNAL behaves as DISCRETE.

Set require_presentation to false for headless and compute-only work, including any run with windowing_backend set to NONE. With it true, a device whose graphics queue family cannot present is rejected.

MAYAFLUX_GPU overrides the config at runtime without a rebuild. An all-digits value is an index, anything else a name substring:

MAYAFLUX_GPU=1 ./my_piece
MAYAFLUX_GPU=intel ./my_piece

Selection composes below driver-level filtering rather than overriding it. VK_DRIVER_FILES, MESA_VK_DEVICE_SELECT, DRI_PRIME, and __NV_PRIME_RENDER_OFFLOAD all act before the engine sees the device list, so if a GPU is missing from the startup log entirely, one of those is the reason.

Device extensions

required_extensions and optional_extensions on gfx.backend_info request Vulkan device extensions beyond what the engine enables itself. A required extension the device does not support fails at startup with the name; an unsupported optional one is skipped with a warning.

gfx.backend_info.optional_extensions = { "VK_EXT_memory_budget" };

Input: <tt>GlobalInputConfig</tt>

Input backends are all disabled by default. Enable only what you need.

void settings() {
input.midi.enabled = true;
input.osc.enabled = true;
input.osc.receive_port = 8000;
input.hid.enabled = true;
// input.hid.filters to restrict to specific device types
// Convenience factory methods:
// auto input = Core::GlobalInputConfig::with_midi();
// auto input = Core::GlobalInputConfig::with_osc(8000);
// auto input = Core::GlobalInputConfig::with_gamepads();
// auto input = Core::GlobalInputConfig::with_all_hid();
}
Core::GlobalInputConfig input
Definition Config.cpp:42
Core::GlobalInputConfig & get_global_input_config()
Gets the input configuration from the default engine.
Definition Config.cpp:82

Network: <tt>GlobalNetworkConfig</tt>

void settings() {
net.udp.enabled = true;
net.udp.default_receive_port = 8000;
net.udp.default_send_port = 9000;
net.tcp.enabled = true;
net.tcp.listen_port = 0; // 0 = OS-assigned
// Convenience factory methods:
// auto net = Core::GlobalNetworkConfig::with_udp(8000, 9000);
// auto net = Core::GlobalNetworkConfig::with_tcp();
// auto net = Core::GlobalNetworkConfig::with_osc(8000, 9000);
}
Core::GlobalNetworkConfig & get_global_network_config()
Gets the network configuration from the default engine.
Definition Config.cpp:90

Journal (logging)

void settings() {
// Severity threshold: TRACE, DEBUG, INFO, WARN, ERROR, FATAL
// Sinks (additive; cannot be removed after being added)
MayaFlux::Config::store_journal_entries("run.log"); // also sets severity to TRACE
// Per-component or per-context filtering
{ MayaFlux::Journal::Context::AudioProcessing }, false);
}
void set_journal_component_filter(const std::vector< Journal::Component > &component, bool enabled)
Enables or disables logging for specific journal components.
Definition Config.cpp:143
void store_journal_entries(const std::string &file_name)
Stores journal entries to a file by adding a FileSink to the Archivist.
Definition Config.cpp:178
void set_journal_severity(Journal::Severity severity)
Sets the minimum severity level for journal entries to be logged.
Definition Config.cpp:138
void sink_journal_to_console()
Outputs journal entries to the console by adding a ConsoleSink to the Archivist NOTE: This records th...
Definition Config.cpp:184
void set_journal_context_filter(const std::vector< Journal::Context > &context, bool enabled)
Enables or disables logging for specific journal contexts.
Definition Config.cpp:155
@ Vruta
Coroutines, schedulers, clocks, task management.
@ Buffers
Buffers, Managers, processors and processing chains.

Via JSON the same fields are in the "journal" key. "disable_components", "disable_contexts", "include_components", and "include_contexts" take string names matching the enum values (case-insensitive). Empty include lists allow all values; nonempty lists allow only their entries, subject to the disable lists.

Journal configuration is the only part of settings() that takes effect immediately rather than at Init().


Reading config at runtime

After Init(), config values are readable from anywhere:

void compose() {
}
uint32_t get_buffer_size()
Gets the buffer size from the default engine.
Definition Config.cpp:120
uint32_t get_sample_rate()
Gets the sample rate from the default engine.
Definition Config.cpp:111
uint32_t get_num_out_channels()
Gets the number of output channels from the default engine.
Definition Config.cpp:129

The full structs are also accessible via get_global_stream_info() etc., but writing to them after Init() logs a warning and will not take effect.


Common configurations

Low-latency performance:

void settings() {
stream.sample_rate = 48000;
stream.buffer_size = 128;
stream.output.channels = 2;
gfx.surface_info.present_mode = Core::GraphicsSurfaceInfo::PresentMode::MAILBOX;
gfx.target_frame_rate = 120;
}

Audio input enabled:

void settings() {
stream.sample_rate = 48000;
stream.buffer_size = 512;
stream.input.enabled = true;
stream.input.channels = 2;
}

Headless / offline (no window):

void settings() {
stream.buffer_size = 4096;
gfx.windowing_backend = Core::GlobalGraphicsConfig::WindowingBackend::NONE;
}

OSC + MIDI input:

void settings() {
input.osc.enabled = true;
input.osc.receive_port = 9000;
input.midi.enabled = true;
}

Load all settings from file, then override one value:

void settings() {
// Override just the buffer size regardless of what the file says
}
uint32_t buffer_size
Number of samples per processing block.