MXVK is a C++20 Vulkan rendering framework with SDL3 integration, focused on practical 2D and 3D application development.
It provides a reusable window/render loop (mxvk::VK_Window), sprite and text rendering, model rendering, a small engine math library in mxvk/mxvk_math.h, optional OpenCV capture support, and a set of examples that demonstrate end-to-end usage. It is designed to be easy to use while still retaining the power that Vulkan provides.
The repository also includes MXWrite, a small FFmpeg-based video writer library for exporting RGBA frames to video files. It can be built alongside MXVK with -DWITH_MXWRITE=AUTO|ON|OFF.
- What This Project Is
- Core Dependencies
- Build
- Command Line Arguments
- VK_Window Post-Processing
- Debugging Examples
- Examples
- Recent Optimizations
- MXWrite
- MXNetwork
- Project Layout
- Early Screenshots
- A static library (
mxvk) for Vulkan-based rendering. - A small 2D/3D math and software-raster helper library used by the engine tests and examples.
- A set of examples under
examples/that exercise key features:- dynamic rendering and custom pipelines
- sprite rendering and shader effects
- text rendering
- engine math, projection, and software 3D raster tests
- Matrix-style digital rain rendering
- reusable Matrix rain texture generation
- model rendering
- game loops and input handling
- controller input, console overlays, post-processing, and audio-enabled gameplay when optional features are present
- simple gameplay examples and UI state flow
- optional OpenCV camera/video workflows
View on YouTube: https://youtu.be/Y3PyGg3qBUA
The root CMake configuration checks for and uses:
- C++20 compiler
- SDL3
- SDL3_ttf
- Vulkan 1.4+
- PNG
- ZLIB
- glm
- glslc (shader compiler)
- Optional: OpenCV (when building with
-DCV=ON) - Optional: FFmpeg for MXWrite (when building with
-DWITH_MXWRITE=AUTO|ON)
From repository root:
cmake -S . -B build
cmake --build build -jIf you clone/move the repo to a different machine or path, run a fresh configure first.
CMake-generated build files contain absolute paths and can fail with errors like
No rule to make target .../examples/.../*.frag when a previous build directory is reused.
cmake --fresh -S . -B build
cmake --build build -jIf your CMake version does not support --fresh, remove the build directory manually:
rm -rf build
cmake -S . -B build
cmake --build build -jUseful CMake options:
-DVALIDATION=ONenables Vulkan validation layers.-DDEBUG_MODE=ONenables debug compile flags.-DWITH_CUDA=AUTO|ON|OFFcontrols CUDA acceleration/interop. The default isAUTO, which enables CUDA when the toolkit is detected;ONrequires CUDA;OFFdisables it.-DWITH_MXWRITE=AUTO|ON|OFFcontrols the MXWrite FFmpeg video writer build. The default isAUTO, which builds MXWrite when FFmpeg is detected;ONrequires FFmpeg;OFFskips MXWrite.-DCV=ONenables OpenCV-based examples and capture support.-DMIXER=ONenables SDL3_mixer audio support (mxvk_sound.cpp,MXVK_WITH_MIXER).-DJPEG=ONenables JPEG image support (mxvk_jpeg.cpp,MXVK_WITH_JPEG).-DFRACTAL_ZOOM=ONenables thefractal_zoomexample and its Boost dependency.-DEXAMPLES=OFFbuilds/install only themxvklibrary and skips all examples.
Example:
cmake -S . -B build -DVALIDATION=ON -DCV=ON
cmake --build build -jAdditional configure examples:
# Build library + examples with audio and JPEG support
cmake -S . -B build -DMIXER=ON -DJPEG=ON
# Build the fractal_zoom example and its Boost dependency
cmake -S . -B build -DFRACTAL_ZOOM=ON
# Library-only build (faster CI/package build)
cmake -S . -B build -DEXAMPLES=OFFMost examples use the shared parser in mxvk/argz.hpp via proc_args(...).
Supported options:
-h- Show help and exit.
-p <path>,--path <path>- Asset root path (defaults to
.when omitted).
- Asset root path (defaults to
-r <WxH>,--resolution <WxH>- Window resolution, e.g.
-r 1280x720. - For
compute_shader, this also sets the compute canvas and recorded video size; source frames are scaled into that canvas before shader processing. When omitted for file playback, the window and compute canvas use the video frame size unless fullscreen is enabled.
- Window resolution, e.g.
-f,--fullscreen- Launch in fullscreen mode.
--filename <file>- Optional input/model/video filename used by examples that support external assets.
- For
model_example, this overrides the defaultdata/pyramid.objmesh. You can point it at a custom.obj,.mxmod, or.mxmod.zfile. - When you provide a custom model, the loader no longer assumes the built-in pyramid asset set. If the model references external textures, use
--resource <file>for a texture manifest and--resource_path <dir>for the texture directory. run.plalready passes the example asset root with-p, so--filenamecan usually be a relative path inside the repo or a full absolute path.
-o <file>,--output <file>- Optional output filename for examples that export video.
-c <value>,--crf <value>- Optional Constant Rate Factor for video export.
--encode-preset <preset>- Optional MXWrite encoder preset. For software x264 use values such as
ultrafast,superfast,veryfast,fast,medium,slow, orveryslow; for NVENC these map to NVENC preset levels.
- Optional MXWrite encoder preset. For software x264 use values such as
--encode-tune <tune>- Optional MXWrite encoder tune, such as
film,animation,grain,stillimage,fastdecode, orzerolatency.
- Optional MXWrite encoder tune, such as
--encode-codec <auto|software|nvenc>- Optional MXWrite encoder backend policy.
autoprefers NVENC when available,softwareforces x264, andnvencrequests NVENC with fallback handled by MXWrite.
- Optional MXWrite encoder backend policy.
--encode-realtime- Enable MXWrite low-latency/realtime encoder settings.
--mxwrite-block- Make MXWrite block when its internal queue is full instead of dropping frames.
--texture <file>- Optional texture filename.
-S <path>,--shader-path <path>- Shader SPIR-V folder path.
--camera <index>- Camera index for OpenCV capture examples.
General run pattern:
./<example> [options]To run a compiled example from the repository root, use run.pl:
./run.pl <example> [extra args...]run.pl looks up the built executable under build/examples/<example>/ and
passes the example's asset directory with -p automatically.
For the full core demo sweep, use ./run.pl --all. It runs the example list
sequentially by delegating to testapps.pl, forwards any extra arguments to
each run.pl invocation, and stops on the first failure or Ctrl-C.
Examples:
./run.pl sprite_example -r 1920x1080 -f
./run.pl 3dmath
./run.pl 3dmath_cube
./run.pl 3dmath_texture --filename ./examples/sprite_example/data/intro.png
./run.pl model_example
./run.pl planet
./run.pl pong
./run.pl tictactoe
./run.pl pool_demo
./run.pl fractal_zoom
./run.pl console_demo -r 1280x720
./run.pl matrix
./run.pl glitch_cube -r 1280x720
./run.pl starship
./run.pl defender
./run.pl walk
./run.pl 3dmath_masterpiece
./run.pl compute_shader --camera 0
./run.pl opencv_example --camera 0 -r 1280x720
./run.pl opencv_model --filename ./models/torus.mxmod.z --camera 0mxvk::VK_Window can render the normal scene into an offscreen color target and then draw that image through an optional full-screen fragment shader before presenting. Attach a sprite-compatible fragment shader with attachPostProcessingShader(...), pass effect parameters with setPostProcessingShaderParams(...), enable automatic elapsed-time updates for parameter 1 with setPostProcessingShaderTimeEnabled(true), and toggle the pass at runtime with setPostProcessingEnabled(...).
defender and asteroids3d use this path for the CRT shader. In both examples, press F8 to toggle the CRT post-processing effect on or off.
Use debug.pl from the repository root to launch a built example under GDB:
./debug.pl <example> [extra args...]The script resolves the executable name from examples/<example>/CMakeLists.txt, then looks for it under build/examples/<example>/. It changes into the executable directory before launching GDB so relative runtime files behave like a normal run.pl launch.
debug.pl also passes the example asset path automatically with -p. Most examples receive -p examples/<example>, while examples whose CMake file sets ASSET_DIR to the target output directory receive -p build/examples/<example>. Any extra arguments after the example name are forwarded to the program.
Internally, the script executes GDB in quiet mode and immediately starts the program:
gdb -q -ex "set confirm off" -ex "run" --args ./<executable> -p <asset_path> [extra args...]When the program crashes or hits a breakpoint, you are left at the GDB prompt. Useful commands include bt for a backtrace, frame <n> to inspect a stack frame, print <expr> to inspect values, continue to resume, and quit to exit.
Examples:
./debug.pl sprite_example -r 1920x1080
./debug.pl model_example --filename ./models/torus.mxmod.z
./debug.pl opencv_example --camera 0 -r 1280x720The examples are grouped below by what they demonstrate. Most accept the shared arguments documented above, and the per-example README.md files carry the full control maps for the larger demos.
cfg_example- config persistence smoke test. Inputs: none. Controls: none; it runs once, prints the incremented counter, and exits.hello_world- minimalmxvk::VK_Windowexample with a custom graphics pipeline and animated triangle. Inputs: common-p,-r,-f. Controls:Escapequits.skeleton- smallest practical subclass ofmxvk::VK_Window, intended as a copyable starting point for new examples. Inputs: common-p,-r,-f. Controls:Escapequits.static_example- fullscreen triangle sample that pushes window size and frame count into the shader. Inputs: common-p,-r,-f. Controls:Escapequits.sprite_example- loads a PNG sprite, renders it full-screen, and overlays text with a custom sprite shader. Inputs: common-p,-r,-f; optional texture and shader path arguments. Controls:Escapequits.text_example- compact text-rendering sample built aroundsetFont(...)andprintText(...). Inputs: common-p,-r,-f. Controls:Escapequits.rain- static helper library used by Matrix-style examples to render configurable glyph rain into an SDL surface and MXVK sprite texture. It is not launched directly throughrun.pl.
These programs are not intended as standalone applications. They are small visual tests for the engine's mxvk/mxvk_math.h math helpers, projection code, triangle drawing, filled polygons, lighting, and software texture sampling inside the MXVK render loop.
3dmath- minimal rotating triangle test usingvec4D,Mat4D,RenderList, andPipeLineprojection/drawing helpers. Inputs: common-p,-r,-f. Controls:Escapequits.3dmath_cube- rotating cube test for matrix transforms, backface culling, depth sorting, diffuse face shading, filled triangle rasterization, and line clipping. Inputs: common-p,-r,-f. Controls:Escapequits.3dmath_texture- textured rotating cube test for the same software 3D path plus PNG loading and software UV sampling. Inputs: common-p,-r,-f, plus--filename <file.png>or--texture <file.png>. Controls:Escapequits.3dmath_masterpiece- MasterPiece variant that renders the board and falling blocks as CPU-rasterized spinning 3D cubes before uploading the frame through an MXVK sprite. Inputs: common-p,-r,-f. Controls: arrow keys move,UporArotates forward,Srotates backward,Ppauses,Escapereturns to the menu.
matrix- Matrix-style digital rain rendered fromSDL_ttfglyphs and a sprite-backed framebuffer. Inputs: common-p,-r,-f. Controls:Spacerandomizes the streams,Escapequits.binary_matrix- 3D variant ofmatrixthat turns0and1glyphs into a depth-aware scene. Inputs: common-p,-r,-f. Controls:Spacerandomizes the rain, arrow keys orbit the camera,Page Up/Page Downzoom,Escapequits.fractal_zoom- fullscreen Mandelbrot-style renderer with runtime zoom, pan, palette switching, and shader-driven color output. Inputs: common-p,-r,-f. Controls: mouse wheel zoom, drag pan,W/A/S/Dor arrow keys pan,Z/Xcontinuous zoom,1/2/3presets,+/=and-iteration count,[/]palette,Rreset,Escapequit.console_demo- in-window console layered over a moving shader background. Inputs: common-p,-r,-f. Controls:F3opens or closes the console,Escapequits when the console is hidden, console commands includehelp,echo,about,quit, andexit.glitch_cube- stylized cube viewer with time-based transforms, shader-driven presentation, and runtime scale/orbit controls. Inputs: common-p,-r,-f. Controls: left mouse drag orbits, mouse wheel zooms,Spacetoggles the rotation axis,Page Up/Page Downscales the cube,Escapequits.
model_example- basicVKAbstractModelviewer for textured OBJ or MXMOD assets. By default it loadsdata/pyramid.objfrom the example asset directory.--filenameoverrides the model file,--resourcecan point at a texture manifest,--resource_pathcan override the texture lookup directory, and--binaryreplaces the model's texture with animated Matrix-style green rain while also enabling the skybox toggle. Inputs: common-p,-r,-f,--filename,--fragment,--resource,--resource_path, and--binary. Controls: left mouse drag rotates, mouse wheel zooms,Spacetoggles auto-spin,Entertoggles skybox mode when--binaryis enabled,W/A/S/Dlook around inside the skybox view,Escapequits.planet- textured Saturn scene with a ring, orbital camera, and runtime asset staging. Inputs: common-p,-r,-f,--filename. Controls: left mouse drag orbits, mouse wheel zooms,Escapequits.tux_example- layered scene that combines a textured model, an animated background sprite, and text overlays. Inputs: common-p,-r,-f. Controls:Escapequits.sprite3d_example- 3D sprite scene with a starfield, a flying saucer, and mouse-driven camera orbiting. Inputs: common-p,-r,-f. Controls: left mouse drag orbits, mouse wheel zooms,Escapequits.starship- ship viewer with Phong shading, a moving starfield, and exhaust effects. Inputs: common-p,-r,-f, plus the example asset set. Controls: mouse drag rotates the ship,Escapequits.dark- Dark Crystal Pyramid viewer with a custom beam effect and layered model/sprite/text rendering. Inputs: common-p,-r,-f, optional--filename. Controls: left mouse drag orbits, mouse wheel zooms,Escapequits.moon- moon model viewer with pyramids and a separate starfield layer. Inputs: common-p,-r,-f, optional--filenameand--fragment. Controls: left mouse drag orbits, mouse wheel zooms,Spacetoggles auto-spin,Escapequits.
asteroids- 2D Asteroids-style arcade shooter with physics, scoring, particles, and a fixed playfield. Inputs: common-p,-r,-f. Controls:Left/Rightrotate,Upthrust,Spacefire,Escapequits.asteroids3d- 3D Asteroids-style action game with ship, asteroids, projectiles, and console commands. Inputs: common-p,-r,-f. Controls:SpaceorEnterstarts from the intro,F1toggles the debug HUD,F2toggles inverted controls,F3opens the console,F8toggles CRT post-processing,Left/Rightyaw,W/Spitch,A/Droll,Up/Downspeed,Spacefires,Escapereturns to the intro or quits.defender- side-scrolling 3D starfield shooter with model-based ship and asteroids, animated UFO sprites, radar/HUD, controller support, console commands, Matrix-rain intro, CRT post-processing, and optional SDL3_mixer audio. Inputs: common-p,-r,-f. Controls:EnterorSpacestarts,Zthrusts,Dboosts,Xreverses,W/UpandDownmove vertically,A/Sroll,Spacefires,F3toggles the console,F4toggles FPS,F8toggles CRT,Escapequits.pong- 3D-styled Pong demo with paddle/ball gameplay and real-time state updates. Inputs: common-p,-r,-fplus the example data directory. Controls: arrow keys move the paddle,W/A/S/Drotate the view,Qresets rotation,Rresets the game,Spacetoggles wireframe,Enterresets the camera,Escapequits.tictactoe- mouse-driven tic-tac-toe against a simple computer opponent. Inputs: common-p,-r,-f. Controls: mouse click places a mark,Rresets,Escapequits.walk- first-person maze and exploration sample with procedural generation, collision, collectibles, and combat. Inputs: common-p,-r,-f. Controls:W/A/S/Dmove, mouse or right stick look,Left Shiftsprint,Left Ctrlcrouch,Spacejump, left click or right shoulder fire,Ftoggles the FPS overlay,Escapereleases the mouse or quits.pool_demo(Pool3D) - 3D billiards game with menus, high scores, cue-ball placement, and shot logic. Inputs: common-p,-r,-f. Controls: menus useEnter,Space,Escape, andBack; in-game controls include arrow keys,Spaceto charge a shot,Enterto confirm cue-ball placement, mouse drag for aiming, right mouse drag to rotate the camera, and wheel or pinch to zoom.puzzle- Acid Drop, a falling-block puzzle with menus, scores, options, credits, and name entry. Inputs: common-p,-r,-f. Controls:Up/Downnavigate menus,Left/Rightmove blocks,Spacerotates,Ppauses,Escapebacks out or quits, and text entry usesBackspace/Enter.masterpiece(MasterPiece) - port of the originalMasterPiece.SDLblock puzzle game with updated assets. Inputs: common-p,-r,-f. Controls: menu navigation usesUp/Down/Enter/Escape; in game useLeft/Rightmove,Downsoft drop,AorUprotate forward,Srotate backward,Ppause,Escapereturn to menu, with typed input for high-score entry.tetris- 3D Tetris with a title flow, high scores, credits, and optional network multiplayer. Inputs: common-p,-r,-f. Controls: menus useUp/Down/Enter/Escape; in game useLeft/Rightmove,Downsoft drop,Uprotate,Zhard drop,Rrestart,Escapemenu, camera controls useW/A/S/D,Q/E,Page Up/Page Down, and multiplayer usesHto host andJ/Enterto join.
compute_shader- OpenCV capture or video-file playback through selectable Vulkan compute shaders. Inputs: requires-DCV=ON; accepts--camera,--filename,--output,--crf,--shader-path, and compute-related options. Controls:Up/Downswitch shaders,Left/Rightchange theacidcam_filtersselector,Escapequits.opencv_example- displays camera or video frames on a sprite in real time. Inputs: requires-DCV=ON; accepts--cameraand--filename. Controls:Escapequits.opencv_model- maps a live camera feed onto a textured 3D model. Inputs: requires-DCV=ON; accepts--camera,--filename, and standard example arguments. Controls: left mouse drag orbits, mouse wheel zooms, arrow keys rotate the model,Escapequits.
If you want a quick tour of the core demos, ./run.pl --all executes the default example sweep used by testapps.pl.
- Sprite and 3D sprite paths now keep more GPU state alive across frames, track dirty state, and support instanced sprite batches. This reduces repeated descriptor/pipeline work in sprite-heavy demos such as
binary_matrix,defender,starship, andpong. - Text rendering caches uploaded glyph/text textures and evicts old entries instead of recreating Vulkan images for repeated strings every frame. HUD-heavy examples use this path for steadier frame times.
compute_shadernow presents the Vulkan compute output through a full-screen sampled draw, avoiding a readback or sprite upload for display. When CUDA interop is available, GPU capture frames can be copied directly into the Vulkan compute input image; otherwise the CPU fallback path remains available.fractal_zoomuses cached adaptive reference-orbit data, throttled rebuilds while the view is changing, and a direct shader path while coordinates are still safe for f32. Deep zooms switch to perturbation data only when needed.- Matrix rain is factored into the reusable
rainlibrary somatrix,binary_matrix,model_example,planet, anddefendercan share glyph loading, tinting, resize handling, and texture sync code.
MXWrite is the FFmpeg-based video writer library included in this repository. It is useful when you want to export RGBA frames to a video file from a C++20 application without building a separate project.
MXWrite is included from the root CMake build and follows the same auto-detect pattern as other optional components:
cmake -S . -B build -DWITH_MXWRITE=AUTO
cmake --build build -jUse -DWITH_MXWRITE=ON to require FFmpeg, or -DWITH_MXWRITE=OFF to skip MXWrite entirely.
Consumer code includes MXWrite/mxwrite.hpp and links against mxwrite. The public API provides Writer for frame-based or timestamp-based output, plus EncodeOptions for preset, codec, CRF, realtime, and HDR settings.
#include "mxwrite.hpp"
Writer writer;
EncodeOptions opts;
opts.codec = "auto";
opts.crf = 18;
if (writer.open("output.mp4", 1280, 720, 30.0f, opts)) {
writer.write(rgba_frame_ptr);
writer.close();
}When built through MXVK, the library exports MXWRITE_ENABLED=1 on the mxwrite target so consumers can gate MXWrite-specific code consistently.
MXNetwork is the small C++20 socket library included in this repository. It provides a C-compatible low-level socket API plus a move-only C++ RAII wrapper for IPv4/IPv6 TCP and UDP, plus Unix-domain socket workflows.
MXNetwork is included from the root CMake build as the static mxnetwork library. The root build disables MXNetwork's standalone examples and uses the library where needed, such as the optional multiplayer path in tetris.
cmake -S . -B build
cmake --build build -jTo build MXNetwork directly with its own examples, configure the MXNetwork subdirectory:
cmake -S MXNetwork -B build-mxnetwork
cmake --build build-mxnetwork -jMXNetwork's standalone build includes TCP, UDP, Unix-domain socket, relay, and file-download examples. TCP and UDP examples use the same wrapper methods that are available to IPv4 and IPv6 socket types. Use -DMXNETWORK_EXAMPLES=OFF when building that subdirectory if you only want the library.
Consumer code includes MXNetwork/include/mxnetwork/socket.hpp and links against libmxnetwork::mxnetwork when using this repository directly. Installed consumers can use find_package(mxnetwork REQUIRED) and link against mxnetwork::mxnetwork.
The C++ API provides mxnetwork::Socket for move-only socket ownership, plus mxnetwork::MXNetworkInit for platform socket initialization and cleanup.
#include "mxnetwork/socket.hpp"
#include <iostream>
#include <string>
int main() {
mxnetwork::MXNetworkInit network_init;
mx_socket_ignore_pipe_signal();
mxnetwork::Socket socket(mxnetwork::SocketType::TYPE_INET);
if (!socket.connect("127.0.0.1", "8080")) {
std::cerr << "connect failed\n";
return 1;
}
const std::string message = "hello";
socket.write_all(message.data(), message.size());
}The wrapper supports IPv4 TCP sockets, IPv6 TCP sockets, IPv4 UDP datagrams, IPv6 UDP datagrams, Unix-domain stream sockets, and Unix-domain datagrams where the platform supports them. Common helpers include connect, listen, accept, bind, setblocking, read, write, read_all, write_all, sendto, recvfrom, valid, and close.
IPv6 uses dedicated socket types while keeping the same method names as IPv4:
mxnetwork::SocketType::TYPE_INET6for IPv6 TCP sockets.mxnetwork::SocketType::TYPE_INET6_DGRAMfor IPv6 UDP sockets.
For example, an IPv6 TCP connection only changes the socket type and address:
mxnetwork::Socket socket(mxnetwork::SocketType::TYPE_INET6);
if (!socket.connect("::1", "8080")) {
std::cerr << "IPv6 connect failed\n";
return 1;
}For IPv6 UDP, construct TYPE_INET6_DGRAM; bind(port), connect(host, port), sendto, and recvfrom dispatch through MXNetwork's IPv6 datagram helpers.
mxvk/- Engine source, headers, built-in shaders, and the
mxvk/mxvk_math.hmath helpers used by the 3D math tests.
- Engine source, headers, built-in shaders, and the
examples/- Runnable examples and sample assets.
models/- Model assets used by model-based examples.
volk/- Vulkan function loader submodule/source.
- The example CMake files copy required runtime assets into each example's output directory after build.
- If you run an example from a custom working directory, prefer passing
-pwith the correct asset root.