Introduction to PVRVk#
Overview#
PVRVK is a library providing an advanced interface that is close enough to the original Vulkan interface to be perfectly useable with the Vulkan spec, while offering a sweet spot combination of simplicity, ease of use and minimal overhead. Its most important features are C++ language offering defaults and constructors for all objects, deterministic lifecycle management through reference counting and in general a clean, modern interface.
You can find the PVRVk source in the SDK package’s framework/PVRVk
folder.
Using PVRVk#
PVRVk can be used independently of the rest of the framework, by following the Vulkan spec with the following differences:
All enums in Vulkan have been replaced with C++ type safe scoped enums (enum class).
All enum members lose the enum name as part of the values, and gain
e_
as a prefix.All functions become methods (member functions) of the class of their first argument.
Sensible, obvious rules, such as using RAII for objects (objects can be released by just null-ing their last handle, or letting it go out of scope).
Code Examples#
Pipeline creation:
pvrvk::GraphicsPipelineCreateInfo pipeCreate;
//Create the descriptor set layouts
pvrvk::DescriptorSetLayoutCreateInfo imageDescParam;
imageDescParam.setBinding(0, VkDescriptorType::e_COMBINED_IMAGE_SAMPLER, 1, VkShaderStageFlags::e_FRAGMENT_BIT);
pvrvk::DescriptorSetLayout descLayoutImage = device->createDescriptorSetLayout(imageDescParam);
pvrvk::DescriptorSetLayoutCreateInfo dynamicUboDescParam;
dynamicUboDescParam.setBinding(0, VkDescriptorType::e_UNIFORM_BUFFER_DYNAMIC, 1, VkShaderStageFlags::e_VERTEX_BIT);
pvrvk::DescriptorSetLayout descLayoutUboDynamic = device->createDescriptorSetLayout(dynamicUboDescParam);
pvrvk::DescriptorSetLayoutCreateInfo uboDescParam;
uboDescParam.setBinding(0, VkDescriptorType::e_UNIFORM_BUFFER_DYNAMIC, 1, VkShaderStageFlags::e_VERTEX_BIT);
pvrvk::DescriptorSetLayout descLayoutUboStatic = device->createDescriptorSetLayout(uboDescParam);
//Create a pipeline layout from all the descriptor set layouts
pvrvk::PipelineLayout pipeLayout = device->createPipelineLayout(
pvrvk::PipelineLayoutCreateInfo()
.setDescSetLayout(0, descLayoutImage)
.setDescSetLayout(1, descLayoutUboDynamic)
.setDescSetLayout(2, descLayoutUboStatic));
//Load the shaders from their bytes. The createShaderModule function accepts a vector of unsigned integers containing the binary spir-v.
pipeCreate.vertexShader = device->createShaderModule(getAssetStream("Object.vsh.spv")->readToEnd<uint32_t>());
pipeCreate.fragmentShader = device->createShaderModule(getAssetStream("Solid.fsh.spv")->readToEnd<uint32_t>());
//Create a color blending state without blending
pvrvk::PipelineColorBlendAttachmentState cbStateNoBlend(false);
pipeCreate.vertexInput.addInputAttribute(VertexAttribute(/ *attribute config here* /)).addInputBinding(VertexInputBindingDescription(/ * input bindings here * /);
pipeCreate.rasterizer.setFrontFaceWinding(VkFrontFace::e_COUNTER_CLOCKWISE);
pipeCreate.rasterizer.setCullMode(VkCullModeFlags::e_BACK_BIT);
pipeCreate.depthStencil.enableDepthTest(true);
pipeCreate.depthStencil.setDepthCompareFunc(VkCompareOp::e_LESS);
pipeCreate.depthStencil.enableDepthWrite(true);
pipeCreate.renderPass = onScreenFramebuffer[0]->getRenderPass();
pipeCreate.pipelineLayout = pipeLayout;
pipeCreate.viewport.setViewportAndScissor(0,
pvrvk::Viewport(0, 0, swapchain->getDimension().width, swapchain->getDimension().height),
pvrvk::Rect2Di(0, 0, swapchain->getDimension().width, swapchain->getDimension().height));
// create the pipeline
= objectVsh;
pipeCreate.fragmentShader = solidFsh;
pipeCreate.colorBlend.setAttachmentState(0, cbStateNoBlend);
pvrvk::GraphicsPipeline solidObjectPipeline = device->createGraphicsPipeline(pipeCreate);
if (solidObjectPipeline.isNull())
{
setExitMessage("Failed to create Opaque rendering pipeline");
return pvr::Result::UnknownError;
}