![]() |
VPP
0.8
A high-level modern C++ API for Vulkan
|
Computation is another application for GPUs besides image rendering. Because of high capabilities of modern GPUs this is very viable alternative to traditional CPU computing, at least in areas where large precision is not needed.
Up till now, there existed several proprietary GPU computation technologies, most known being CUDA and OpenCL. VPP differs from them in following ways:
GLCompute
execution model. While lacking certain features of the Kernel
mode (used for OpenCL), it is also supported by large variety of hardware. That means, your GPU routines will be able to run on anything that supports Vulkan (desktop, mobile, etc.).This chapter shows how to write computational programs using VPP. There can be two possible approaches, depending on how much control you want to have over the entire process.
The easy method is to use vpp::ComputationEngine and vpp::Computation classes. They offer a way to execute a GPU program by just calling a function from C++.
The more involved way, giving more control, is to use the vpp::ComputePass along with vpp::CommandBufferRecorder, vpp::CommandBuffer and vpp::Queue in order to schedule Vulkan commands manually. This method is harder but much more flexible, allowing to integrate multiple computation and rendering processes into single engine.
For both methods, the basic premises and computation model are the same.
First of all, you must make one or more computation pipeline classes. Derive these classes from vpp::ComputePipelineConfig base class. Compute pipelines are nearly identical to rendering pipelines, but they are not associated with processes in a render graph and can't use any attachments. Note that compute pipelines may also access and/or produce images, although not through attachments but only sampled/storage images.
The only kind of shader allowed in computation pipelines are compute shaders. They are very similar to rendering shaders, but there is no inter-shader exchange variables (as there is only single shader in a pipeline) and no vertex data. All data consumed and produced by the shader must be contained in buffers, images and push constants.
See the docs for vpp::ComputePipelineConfig for examples and more details.
The next step is to make a class derived from either vpp::ComputePass (low level method) or vpp::Computation (high level method). See introduction in the docs for vpp::ComputePass for details about computation model, local and global workgroups, compute shaders, local and shared variables, etc.
The vpp::Computation base class is derived itself from vpp::ComputePass. Using it instead vpp::ComputePass gives you a compute pass with additional capabilities. vpp::Computation defines several overloads of operator()
allowing to call the object in syntactically similar way to regular method call. These overloads launch computation and optionally wait for results. You can also use Vulkan synchronization objects (vpp::Fence, vpp::Semaphore) to synchronize these computations.
You can have several computations in single computation engine. They can be arranged in a way that the computation listed latter in the owner class can wait for the results of preceding computation. The vpp::ComputationEngine maintains an implicit chain of Vulkan semaphores to achieve that effect.