# vkvg is a Cairo-shaped 2D graphics library that draws through Vulkan

> vkvg is an open source 2D graphics library written in C with Vulkan as its backend, whose API follows the same pattern as Cairo, with new functions and original drawing mechanics allowed on top. It is in alpha development with the core API mostly stabilized, the last tagged release is from 2021, and the code has kept taking commits since, with Arch and Manjaro packages tracking a later beta.

**jpbruyere/vkvg** — Vulkan 2D graphics library

- Repository: https://github.com/jpbruyere/vkvg
- Website: https://jpbruyere.github.io/vkvg/
- Stars: 823 · Forks: 40
- Language: C
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/jpbruyere-vkvg

## Cairo's shape, Vulkan's engine

vkvg is described as an open source 2D graphics library written in C using Vulkan as backend, and the design decision that makes it recognisable is the API: it follows the same pattern as Cairo, but new functions and original drawing mechanics may be added.

That combination is the interesting part. Cairo is a CPU rasteriser with a long-established call structure, and a project that copies that structure but draws through a graphics API inherits two things at once: a familiar drawing model and a different execution model. The vector operations, the path construction, the stroke and fill semantics stay recognisable, while the work happens on the device.

The project is explicit about its maturity. vkvg is in alpha development stage and the core api is mostly stabilized, all contributions are welcome, and in progress API documentation is available online at vkvg.org. The homepage is jpbruyere.github.io/vkvg, the licence is MIT, and the repository carries a .clang-format configuration, a format.sh script, a vkvg.pc.in for pkg-config and a Findvkvg.cmake for projects that want to locate the library.

The audience is a C developer with a Vulkan device who wants a 2D drawing layer, and the repository's own samples directory, with a SampleApp, a VkvgTest, a random data helper and a samples CMakeLists, shows the intended shape of an integration.

## The status list is the honest specification

Instead of a feature matrix, the README has a Current status list, and it is worth reading line by line because it says what is finished and what is not.

Fill is there, with stencil even-odd and non-zero modes. Stroke is there. Basic painting operations are there. The font system with caching is described as operational. Linear and radial gradients are there, as are line caps and joins and dashes.

Two entries are not finished, and they are the two that matter. The first is that the context should be thread safe, with extensive tests required. The second is a work item rather than a feature: image loading and writing with the stb library.

The tests themselves are part of the status list. Testing includes SVG rendering, either with the built-in renderer or with nanoSVG, which tells you the SVG path is a real part of the project rather than a stub.

That current status list is the most useful paragraph in the file, and it is also a warning. A library whose context is not yet documented as thread safe is a library for a single-threaded renderer, and a library that still lists image loading as in progress is not yet a replacement for whatever you use today to decode images.

The performance comparison section points at a separate benchmark project, vgperf, hosted under the same organisation, which is where the comparative numbers would come from if you wanted them.

## Building it: a recursive clone and a handful of optional tools

The build is a CMake project, and the requirements split cleanly into what you need and what you can skip.

You need CMake at version 3.16 or greater, and Vulkan at version 1.1 or greater. Everything else is optional. FontConfig, without which you use vkvg_load_font_from_path. Freetype, with stb_truetype as the alternative. Harfbuzz, and the README is blunt about the consequence: without complex text shaping the result may be wrong. GLSLC, the SPIR-V compiler from the LunarG SDK, for building shaders, and xxd for generating headers with precompiled shaders. GLFW, and if it is present the tests are built.

The shaders point is a nice piece of engineering pragmatism. If glslc or xxd are not present, a precompiled version of the shaders is stored in the git tree, so the build does not require the whole Vulkan SDK on the machine.

The build itself is short:

```bash
#fetch sources from github
git clone --recursive https://github.com/jpbruyere/vkvg.git
cd vkvg
# Create build directory
mkdir build
cd build
# Run CMake configuration
cmake ..
```

and then the build step:

```bash
cmake --build .
```

The recursive flag matters, because the project uses submodules, and the README warns about the specific failure a fork produces. Since the submodule paths are relative, a fork that did not fork the submodules as well can end up with a remote not found error, and the fix is to set fallback URLs for the three submodules by name:

```bash
git config submodule.vkh.url https://github.com/jpbruyere/vkhelpers.git
git config submodule.glutess.url https://github.com/jpbruyere/glutess.git
git config submodule.vkvg-svg.url https://github.com/jpbruyere/vkvg-svg.git
```

For Windows there is a detailed tutorial in doc/windows_build_tutorial.md.

## The option matrix, from tesselation to the renderdoc layer

The CMake options are unusually well documented, and they divide into a few groups that tell you what the library is built for.

The core library options decide how geometry is filled and what the renderer is. -DVKVG_USE_GLUTESS=true uses the embedded GLU tesselator to fill polygons in non-zero mode, and if it is false a simple ear clipping algorithm is used instead. -DVKVG_SVG=true enables the experimental SVG renderer, and if it is false nanoSVG is used. -DVKVG_RECORDING=true enables experimental draw commands recording infrastructure, which is the feature you want if you intend to replay a figure. -DVKVG_BUILD_DOCS=true builds the documentation if doxygen is found.

Two options are about how the library talks to the GPU. -DVKVG_ENABLE_VK_SCALAR_BLOCK_LAYOUT=true enables VK_EXT_scalar_block_layout, which reduces structure padding for the GPU, and -VKVG_ENABLE_VK_TIMELINE_SEMAPHORE=true switches work syncing to VK_KHR_timeline_semaphore instead of fences, described as experimental.

The text options are on by default but disabled if the library is not found: -DVKVG_USE_FONTCONFIG=true resolves font names, -DVKVG_USE_FREETYPE=true renders glyphs and stb_truetype takes over when it is false, and -DVKVG_USE_HARFBUZZ=true enables text shaping.

The test options are -DVKVG_BUILD_TESTS=true to build all tests in the tests folder and -DVKVG_TEST_DIRECT_DRAW=true to draw directly on the swapchain images.

And then the debug options, available when the build type is Debug: -DENABLE_VALIDATION=true turns on the Vulkan validation layer, -DENABLE_DBG_UTILS=true enables the Vulkan debug utilities extensions, -DENABLE_RENDERDOC=true enables the renderdoc layer, -DENABLE_WIRED_FILL=true renders in wired mode with the mode controlled by the global variable vkvg_wired_debug, -DENABLE_PROFILING=true adds -pg to the compile options, and -DVKVG_DBG_STATS=true stores context statistics that are fetchable with vkvg_device_get_stats().

## The alternative, and what the text stack costs you

Cairo is the alternative the project itself names, and the difference in approach is the reason the project exists.

Cairo rasterises on the CPU. It is mature, it is everywhere, and it does not care about your graphics driver. vkvg keeps Cairo's call structure but moves the work onto the device through Vulkan, which is the point on a machine where the rasteriser is the bottleneck, and it explicitly allows new functions and original drawing mechanics where the GPU path needs them.

The cost of that choice shows up in the dependency list. A Cairo program needs a CPU and a font stack. A vkvg program needs a Vulkan driver, a SPIR-V toolchain or the precompiled shaders, and a choice of text backend.

Text is where that is most visible, and it is worth being precise about because the README is. FontConfig is optional, and without it you load a font by path with vkvg_load_font_from_path, which is fine for an application with a fixed font set and awkward for a desktop application that should follow the user's font preferences. Freetype is optional, with stb_truetype as the substitute. HarfBuzz is optional too, and the README says that without complex text shaping the result may be wrong, which is the one warning in the requirements list that should stop you: Arabic, Indic scripts and other scripts that need shaping are the reason HarfBuzz exists, so shipping without it means shipping broken text for those users.

The project also credits the AGG project for its recursive bezier algorithm, which is a reminder that the curve maths in a GPU rasteriser is where the subtle bugs live.

## Packages, releases and the gap between them

The distribution story is better than the release story.

There is an AUR package for Arch Linux, and a package in the Manjaro repository at version 0.3.0-beta, and both are linked from the README. For a library whose users are, in practice, Linux developers with a Vulkan stack, that is a practical path that skips the build from source entirely.

The release history is where the gap sits. The published tags are v0.1-alpha from 2020-08-14 and v0.2.1, described as 0.2.1 beta, from 2021-12-21. The default branch, however, received a push on 2026-10-19, and the packaging version in the Manjaro repository is 0.3.0-beta, so work has continued for years past the last tag without a new release.

That combination is workable but it has a cost. If you take the packaging, you take a beta build that may be years ahead of the last tag, and the documentation at vkvg.org is described as in progress, so the reference documentation is expected to move under you. If you build from source you are closer to the branch, and you get the choice of the debug options and the test suite.

The repository is open to contributions, with a contribution guide, a Matrix channel for questions, a donation badge and a FUNDING.yml, and the code of conduct and issue tracker are the normal routes for anything you find.

## Conclusion

Adopt vkvg when you are writing C, you already have a Vulkan-capable device, and you want a Cairo-shaped 2D drawing API that can run on the GPU. Do not adopt it for a project that needs a stable, documented API today, because the project states it is in alpha development, and the newest tagged release is 0.2.1 from 2021-12-21 even though commits continue. Before you start, read the current status list in the README, which still lists thread safety as a goal rather than a finished feature, decide which text backend you will use, since HarfBuzz and FontConfig are optional and complex shaping may be wrong without them, and try the Arch or Manjaro package before building from source.

## FAQ

### What is vkvg?

It is an open source 2D graphics library written in C using Vulkan as its backend, with an API that follows the same pattern as Cairo although new functions and original drawing mechanics may be added. The project is MIT licensed and describes itself as in alpha development with the core API mostly stabilized.

### What do I need to build vkvg?

CMake 3.16 or newer and Vulkan 1.1 or newer. FontConfig, Freetype, Harfbuzz, the GLSLC SPIR-V compiler, xxd and GLFW are all optional, and if glslc or xxd are absent a precompiled version of the shaders is used from the git tree.

### How do I build vkvg from source?

Clone it recursively with git clone --recursive, create a build directory, run cmake .. and then cmake --build . If you work on a fork, the README explains that relative submodule paths can fail and gives the git config commands that set fallback URLs for the vkh, glutess and vkvg-svg submodules. A Windows tutorial is provided in doc/windows_build_tutorial.md.

### Is vkvg packaged for Linux distributions?

There is an AUR package for Arch Linux and a package in the Manjaro repository, which the badges show at version 0.3.0-beta. The README also links a Matrix channel for questions and a PayPal donation badge for the project.

## Sources

- [jpbruyere/vkvg on GitHub](https://github.com/jpbruyere/vkvg)
- [License: MIT](https://github.com/jpbruyere/vkvg/blob/master/LICENSE)
- [Project website](https://jpbruyere.github.io/vkvg/)
- [README](https://github.com/jpbruyere/vkvg/blob/master/README.md)
- [Releases](https://github.com/jpbruyere/vkvg/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jpbruyere-vkvg
