Home

Awesome

vpp

A vulkan abstraction and utility library written in modern C++.

Does not aim to be a framework or full-sized graphics engine, but rather focuses on providing some useful features that make programming vulkan applications in C++ more convenient and less repetitive while not introducing unreasonable overhead. It does not force you to use shared pointers for all your resources, automagically synchronizes pools or implicitly submits to the device. Think of vpp more like an independently usable set of utilities.

Things vpp provides:

Things vpp does not provide:

You can build vpp using meson. Linux (android as well) and Windows are supported and tested. Needs a solid C++17 compiler, msvc does currently not implement enough of the standard correctly. MinGW-w64 works on windows.

Any contributions (feature requests, issues and ideas as well) are appreciated.

Examples

This example implements the hello-world-triangle using a cross-platform window abstraction and vpp. Below a couple of idiomatic usages of the rather high-level interfaces. You could also check out the tests to see basic usage of those classes with expected results. For more information on any of them, just check out the usually well-documented header files.

Initialization

// Create instance and debugCallback
vk::InstanceCreateInfo iniInfo = {  ...  };
vpp::Instance instance(iniInfo);
vpp::DebugMessenger debugMessenger(instance); // debug_utils extension must be enabled

auto surface = /* use your favorite window abstraction to create a surface */

// Let vpp choose a default physical device, present, graphics and compute queue
// Note that while this usually works and is convenient at the beginning,
// you can still just choose your own physical device or pass
// your own DeviceCreateInfo with chosen queue families.
const vpp::Queue* presentQueue;
vpp::Device device(instance, surface, present);

Submission batches

// vpp::QueueSubmitter allows to bundle multiple queue submissions
// and then track the submission state.
vpp::QueueSubmitter submitter(queue);
auto id = submitter.add({submitInfo1, submitInfo2, submitInfo3});
submitter.submit(id);
submitter.wait(id);

Deferred initialization

// Create initializers for a couple of memory resources.
// They will already reserve as much memory as they need.
// The api can also be used manually (via vpp::Buffer/Image constructors
// and the init method), without the vpp::Init helper
vpp::Init<vpp::Buffer> initBuf1(device, bufferCreateInfo1);
vpp::Init<vpp::Buffer> initBuf2(device, bufferCreateInfo2);
vpp::Init<vpp::Image> iniImg1(device, imgCreateInfo1);

// Finish deferred initialization for all resources
// If posssible (due to vulkan MemoryRequirements) will allocate all resources
// on a single device memory (respecting alignments etc)
buffer1 = initBuf1.init();
buffer2 = initBuf2.init();
image1 = initImg1.init();

SharedBuffer and BufferAllocator

// Create a bufferAllocator (we could also use the device's default allocator) 
// and allocate a bunch of mappable uniform buffer objects.
// Since we reserve the needed storage, only one buffer will be created.
// Alternatively, we could have directly created one vpp::SharedBuffer.
vpp::BufferAllocator bufAlloc(device);

auto hostBits = device.hostMemoryTypes(); // memory types that are hostVisible
auto usage = vk::BufferUsageBits::uniformBuffer;
auto uboSize = 64u;

bufAlloc.reserve(1024, usage, hostBits); // reserve enough for all ubos

vpp::SubBuffer ubo1(bufAlloc, 64u, usage, hostBits);
vpp::SubBuffer ubo2(bufAlloc, 64u, usage, hostBits);
vpp::SubBuffer ubo3(bufAlloc, 64u, usage, hostBits);

Image filling/retrieving

// Some helpers to fill or read images.
auto subres = vk::ImageSubresource{vk::AspectBits::color};
vpp::fillMap(commandBuffer, img1, img1Size, dataToWrite, subres);

// Creates a stage buffer and copies from/to it via the given
// commandBuffer. The stage buffer must be kept alive until the
// command buffer has finished.
auto stageBuffer = vpp::fillStaging(commandBuffer, img2,
	img2Format, img2Layout, img2Size, dataToWrite, subres);
auto stageBuffer = vpp::retrieveStaging(commandBuffer, img3,
	img3Format, img3Layout, img3Size, subres);

Testing

To run all tests with valgrind leak checks, execute (in build dir):

meson test \
	--print-errorlogs \
	--wrapper 'valgrind
		--leak-check=full
		--error-exitcode=1
		--suppressions=../docs/valgrind.supp'