- 🖼️ Graphical support for any device with Vulkan, Metal, or WebGPU.
- 🦑 Portable GPU acceleration for compute: NVIDIA (CUDA), Apple (Metal), Raspberry Pi (Vulkan), etc.
- 🔋 Runtime configurable flowgraph pipeline with heterogeneously-accelerated modular blocks.
- 🧳 Hackable and easy to use as a library or as a standalone application.
- 🧊 Installation-free fully-featured web application powered by WebAssembly and WebGPU.
- 🤯 Low-latency remote interface for headless servers and edge devices.
Warning
CyberEther is in Alpha. Expect bugs, missing features, and breaking changes.
CyberEther provides a flowgraph interface to build and run compute-intensive pipelines. The interface is engineered to provide a closely coupled integration between the graphical and compute blocks providing leading-edge visualization capabilities. CyberEther is built on top of Vulkan, Metal, CUDA, and WebGPU, which allows it to run on virtually any modern device. CyberEther is also designed to be easily extended with new blocks and backends. It is a great tool for prototyping and testing new ideas.
The flowgraph enables the user to build a pipeline by connecting blocks. Each block provides a set of inputs and outputs. The inputs and outputs are connected with edges. The edges are used to transfer data between blocks. The blocks can be accelerated with any combination of backends. The user can build a pipeline with blocks that run on different devices. For example, the user can build a pipeline with a block accelerated with Vulkan followed by a block accelerated with Metal. The scheduler will transparently take care of the synchronization and memory management between the blocks and everything will run like magic!
CyberEther can run in virtually any modern device with a GPU. The build system will automatically choose between the three graphical backends available (Metal, Vulkan, or WebGPU) depending on the target device. The same process applies to the compute blocks, which can be accelerated with CUDA, Metal, or Vulkan. Here is a summary of the compatible devices and backends:
Device | Graphics | Compute | |
---|---|---|---|
âś… | Apple Silicon (iPad, iPhone, Mac) | Metal, Vulkan, WebGPU | CPU, Metal |
âś… | Linux (NVIDIA) | Vulkan, WebGPU | CPU, Vulkan, CUDA* |
âś… | Linux (AMD, Intel) | Vulkan, WebGPU | CPU, Vulkan |
âś… | Raspberry Pi (4 or later) | Vulkan, WebGPU | CPU, Vulkan |
âś… | Browser (Chrome) | WebGPU | CPU, WebGPU* |
âś… | Windows (NVIDIA, AMD, Intel) | WebGPU, Vulkan | CPU, WebGPU*, Vulkan* |
âś… | Android | WebGPU, Vulkan* | CPU, WebGPU*, Vulkan* |
*
: Planned for the future.
Please note that the compatibility table above is not exhaustive. Compute implementations for blocks are being added constantly. Feel free to open an issue if you want to request a specific block or device. Or even better, open a pull request with the implementation!
These are some examples of CyberEther running on the field. Do you have a cool demo? Tweet it with the hashtag #CyberEther and mention @luigifcruz.
This is a simple demo showing how to create a new flowgraph in CyberEther. The flowgraph is a simple pipeline with a Soapy block streaming data from an RTL-SDR dongle and a Spectroscope block visualizing the data with a waterfall and line plot.
cyberether-new-flowgraph.mp4
This is a screen capture of CyberEther running on a MacBook Pro with an M1 Pro chip. The Metal backend is being used for the graphical and compute blocks. The flowgraph is a wideband spectrum analyzer with a bandwidth of 122 MHz streaming from an RFNM software-defined radio.
rfnm-spectrum-analyzer-demo.mp4
A fan favorite demo from my 2019 project called CyberRadio. As the name suggests, the flowgraph is a multi-channel FM receiver. The SDR streams 2 MHz worth of the FM broadcast band and the flowgraph filters, resamples, and demodulates the signal. This flowgraph is available by default in the graphical interface examples.
cyberether-multi-fm.mp4
This demo is running as a native iOS app and illustrates how portable CyberEther can be. The flowgraph implements a standard spectrum analyzer with waterfall and lineplot. It is running on an iPad Pro with an M2 chip. But it also runs on any iPhone and Mac with Apple Silicon and iOS 14 or later. The demo also shows seamless switching between the CPU and Metal backends for individual blocks while the flowgraph is running. Bonus: CyberEther can also run in the browser!
cyberether-ipad.mp4
The only way to use CyberEther at the moment is by compiling it from the source. But don't worry, it is not difficult! Follow the Build From Source instructions below to compile it on your system.
This shouldn't be difficult because of the low number of dependencies. CyberEther requires a C++20 compiler (>GCC-11 or >Clang 14.0), the Meson build system, and Ninja Build. Follow the instructions below to install the dependencies and build CyberEther from source. There are also Docker files available in the docker directory that can be used to build and run CyberEther in a container.
Core dependencies (you probably already have them).
$ pacman -S git base-devel cmake pkg-config ninja meson git zenity
Graphical dependencies.
$ pacman -S glslang [glfw-x11 or glfw-wayland]
$ yay -S spirv-cross
Vulkan backend dependencies (you probably already have them).
$ pacman -S vulkan-icd-loader vulkan-validation-layers
Optional dependencies.
# For SoapySDR block with RTL-SDR support.
$ pacman -S soapysdr soapyrtlsdr
# For Remote capabilities.
$ pacman -S gstreamer gst-plugins-base gst-libav
$ pacman -S gst-plugins-good gst-plugins-bad gst-plugins-ugly
# For examples metadata.
$ pacman -S python-yaml
Core dependencies (you probably already have them).
$ apt install git build-essential cmake pkg-config ninja-build meson git zenity
Graphical dependencies.
$ apt install spirv-cross glslang-tools libglfw3-dev
Vulkan backend dependencies (you probably already have them).
$ apt install mesa-vulkan-drivers libvulkan-dev vulkan-validationlayers
Optional dependencies.
# For SoapySDR block with RTL-SDR support.
$ apt install libsoapysdr-dev soapysdr-module-rtlsdr
# For Remote capabilities.
$ apt install libgstreamer1.0-dev gstreamer1.0-libav
$ apt install gstreamer1.0-plugins-base libgstreamer-plugins-bad1.0-dev
$ apt install libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev
$ apt install gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly
# For examples metadata.
$ apt install python3-yaml
This assumes Homebrew is installed. Older versions of macOS might work but installing a newer Clang compiler (14+) will be necessary. Metal on Intel-based Macs is not supported by CyberEther. As a workaround, make sure to install the optional Vulkan dependencies listed below.
Core dependencies (you probably already have them).
$ brew install cmake pkg-config ninja meson
Graphical dependencies.
$ brew install spirv-cross glslang glfw
Optional dependencies.
# For SoapySDR block with RTL-SDR support.
$ brew install soapysdr soapyrtlsdr
# For Remote capabilities.
$ brew install gstreamer
# For examples metadata.
$ python -m pip install PyYAML
# For Vulkan backend (required for Intel-based Macs).
$ brew install molten-vk vulkan-tools vulkan-headers
All CyberEther runtime dependencies for the browser are included in the repository. You only need to make sure you have Python 3, Emscripten, and Rust Cargo installed.
All CyberEther dependencies for iOS are included in the repository. You only need to make sure you have the latest Xcode installed.
Clone the repository from GitHub.
$ git clone https://github.com/luigifcruz/CyberEther.git
$ cd CyberEther
Follow the instructions below to build and install CyberEther on your system.
Build and install.
$ meson setup -Dbuildtype=debugoptimized build && cd build
$ ninja install
Done! The executable will be installed in the default terminal path. For usage instructions, run cyberether --help
.
Build project with cross-compilation to WebAssembly.
$ meson setup --cross-file crosscompile/emscripten.ini -Dbuildtype=debugoptimized build-browser && cd build-browser
$ ninja
Copy dependencies to the build directory.
$ cp ../resources/cyberether.html .
$ cp ../resources/cyberether.png .
Start the web server and navigate to http://localhost:8000/cyberether.html.
$ python ../tools/local_server.py
Build the project with cross-compilation to iOS and install binaries in the Xcode project.
$ meson setup --cross-file crosscompile/ios.ini \
--prefix $(pwd)/apps/ios/CyberEtherMobile/Library \
-Dbuildtype=debugoptimized build-ios && cd build-ios
$ ninja install
After the build is complete, open the Xcode project and run it on your device.
The graphical interface of CyberEther can be launched from the terminal by running ./cyberether
. The command-line interface also offers other options that can be used to configure the application. For example, enabling the headless remote interface, or running the benchmark tool. The full list of options can be found below.
$ ./cyberether --help
Usage: ./cyberether [options] [flowgraph]
Options:
--headless Enable headless mode.
--endpoint [endpoint] Set the endpoint of the headless viewport (`1.1.1.1:8000`, `./vid.mp4`, etc). Default: `/tmp/cyberether`
--backend [backend] Set the preferred backend (`Metal`, `Vulkan`, or `WebGPU`).
--framerate [value] Set the framerate of the headless viewport (FPS). Default: `60`
--codec [codec] Set the video codec of the headless viewport. Default: `FFV1`
--size [width] [height] Set the initial size of the viewport. Default: `1920 1080`
--scale [scale] Set the scale of the render window. Default: `1.0`
--benchmark [type] Run the benchmark and output the results (`markdown`, `json`, or `csv`). Default: `markdown`
--no-hw-acceleration Disable hardware acceleration. Enabled otherwise.
Other Options:
--staging-buffer [size] Set the staging buffer size (MB). Default: `32`
--device-id [id] Set the physical device ID. Default: `0`
--no-validation Disable Vulkan validation layers. Enabled otherwise.
--no-vsync Disable vsync. Enabled otherwise.
Other:
--help, -h Print this help message.
--version, -v Print the version.
The graphical interface is where the fun is! It is a fully-featured application that can be used to build and run flowgraphs. Building a flowgraph is very familiar to anyone who has used GNU Radio Companion. Just drag the block icon from the right panel and drop it in the canvas. The color of the block icon indicates which backend to pick. For example, the Yellow block will run on the CPU, Purple on Metal, etc. Each block can be connected by dragging edges from the output of one block to the input of another. There is no start or stop button, blocks will start running as soon as they are connected. Flowgraphs can be exported and imported as readable YAML files. Example flowgraphs with helpful notes can be found pre-loaded in the application.
CyberEther can be used as a remote interface for headless servers and edge devices. The remote interface is a low-latency interface that allows the user to control the flowgraph remotely. The remote interface is built on top of gstreamer and uses UDP and TCP for communication. Other than video, the remote interface also sends keyboard and mouse events to the server. The example flowgraph Remote Instance
(see image below) is available by default in the graphical interface and is a good example of how to use the remote interface.
At this time, software video encoding will be used on most platforms. Work is being done to enable hardware encoding in more devices, but this requires a lot of experimentation. Exceptions to this are NVIDIA GPUs, which will use the NVENC hardware encoder with a zero-copy framebuffer encoding, making it very nice and efficient. The Raspberry Pi will also use hardware encoding by default.
To initialize a remote instance of CyberEther, run the command below on the server. If you want lossless video, use the --codec ffv1
option instead. The lossless video will use quite a lot of bandwidth, so make sure you have a good connection.
$ ./cyberether --headless --endpoint 0.0.0.0:5002 --codec h264
Note: This block will use two ports, the first one is shown in the block below (TCP:5002) for telemetry, and control and the second one (UDP:5003) for data streaming. Fun fact, you can use gstreamer to receive the video stream. Detailed instructions on how to do this can be found here.
CyberEther comes with a neat runtime benchmark tool that can be used to compare the performance of different backends and modules. There are two ways to use it, either through the graphical interface or by running the command line tool. The graphical interface is the easiest way to use it. To access it, click on the Developer
menu and then click on Open Benchmarking Tool
. A new window will open (see image below) and the benchmark can be started by clicking on the Run Benchmark
button. The results will be displayed in a table.
The benchmarking tool can also be run from the command line in headless mode. To do this, run the command below. The results will be printed in the terminal. The format of the results can be changed by specifying csv
, json
, or markdown
after the --benchmark
option. For example, --benchmark csv
.
$ JST_DEBUG=2 ./cyberether --benchmark
Another option other than using the graphical interface is to use CyberEther as a library for your application. The library is designed to be easily integrated and hackable. The examples directory contains a few examples to get you started. At the moment, the main focus of the project is to continue to improve the graphical interface, but the standalone features will be improved in the future as things stabilize.
No. CyberEther is a native application that can run on any modern device. It does not use a Browser, Electron, Qt, or any other multi-platform framework. It is built on top of low-level APIs such as Vulkan, Metal, and WebGPU. The CyberEther version that runs in the browser is a fully-featured application that is compiled to WebAssembly and runs on top of WebGPU. It is not a web-based application in the traditional sense and it does not use JavaScript for the core functionality.
The short answer to this question is that compatibility is king. The longer answer is that one of the design choices is to be as low-level as possible. This allows me to have full control over the code and to be able to optimize it for a specific platform without being locked down by a framework. That is why CyberEther can run inside the browser while being able to scale towards a supercomputer. Currently, one of the problems with other languages is that they have too many wrappers and abstractions that make it difficult to debug and optimize the code. I expect this to change in the future as first-party support grows but for now, C++ is the best option. As John Carmack once said, "[...] externalities that can overwhelm the benefits of a language [...]". I am also a big fan of Rust and I am looking forward to finding a good project to use it in the future.
The code is riddled with TODO comments. These are a good place to start. Another way to contribute is by implementing new blocks and modules.
At the beginning of the project, CyberEther was meant to be only an application that utilized Jetstream as a library. But as the project evolved, the two things became one. In the end, I decided to keep Jetstream as the name of the library and CyberEther as the name of the application.
First of all, GNU Radio is an amazing project. It is a very powerful tool and it is used by many people and institutions around the world. Developing CyberEther as a separate project without the burden of backward compatibility and legacy code allowed me to explore new ideas that would be time-consuming to implement in GNU Radio. I think of CyberEther as a playground for new ideas that can be later integrated into GNU Radio if they prove to be useful. Beyond radio, CyberEther has the potential to be used in other domains such as machine learning, computer vision, and robotics. The goal is to make CyberEther a general-purpose acceleration tool for compute-intensive pipelines.
The plans for CyberEther include adding unit tests, improving documentation, and implementing new blocks and modules. The goal is to continue expanding the capabilities of CyberEther beyond radio communications and make it a powerful tool for accelerating compute-intensive pipelines in various domains.
There are no minimum requirements, only minimum expectations.
There are no easter eggs in CyberEther. I promise.
CyberEther was created in 2021 by Luigi Cruz as a personal project. The project is still in its early stages and it is being developed in the open and contributions are welcome. Regular talks about CyberEther were given at previous GNU Radio Conference editions and are available here.
Contributions are welcome! Pull requests are the best way to propose changes to the codebase. We actively welcome your pull requests and invite you to submit pull requests directly in this repository. The library follows the Google C++ Code Style Guide. The default line length is 88. This can be overridden if necessary. Please, be sensible. Also keep in mind that since this project is still in its early stages, the API is not stable and it is subject to change. More details on how to contribute can be found here.
CyberEther is distributed under the MIT license. See LICENSE for details. All contributions to the project are considered to be licensed under the same terms. The list of acknowledgements and third-party software used in this project can be found here.
If your company is utilizing CyberEther in its software solutions, we encourage you to consider contributing to the CyberEther project. Your support and contributions not only help in the continuous improvement and sustainability of the project but also ensure that CyberEther remains a robust and cutting-edge tool for the community. For more details on how your company can contribute, please contact me.