With advantages like reduced driver overhead and more control over GPUs, Vulkan has become the 3D graphics and compute API of choice for a growing number of developers. The Khronos group’s successor to OpenGL, Vulkan improves upon the previous open standard by offering access to new extensions, developer tools and useful features such as asynchronous compute and the reuse of command buffers. So why aren’t more developers building with Vulkan? The required low-knowledge of GPU hardware and behavior in Vulkan is much greater than in OpenGL which may require a steeper learning curve for many developers who may have only scratched the surface of OpenGL 4.5. Vulkan also requires applications to be responsible for many things that OpenGL did not – such as memory management and synchronization.
Continuing our partnership with the Khronos Group and our commitment to providing developers with the hardware agnostic tools they need to build modern professional applications, AMD is announcing the release of V-EZ, a middleware layer that significantly reduces the house-keeping overhead of Vulkan making it easier to use and more accessible to a broader base of developers. V-EZ will still retain the most powerful capabilities of Vulkan but with a simplified API that can be mixed with standard Vulkan where needed. Read on to learn more about some of V-EZ’s key technical features.
V-EZ maintains the existing semantics and API of Vulkan. This allows V-EZ to be used as a transition layer while ISVs familiarize themselves with the new concepts and programming paradigms required by Vulkan. There is no need to learn a new API or framework. One benefit of this is that existing Khronos documentation is still largely applicable in most areas.
The following images summarize the high-level changes and simplifications V-EZ brings to the Vulkan API. Vulkan, and all its objects and relationships are shown in the first image. In the second, is V-EZ.
Figure 1 – Vulkan API
Figure 2 – V-EZ middleware layer
Vulkan Compatibility Designed In
V-EZ was designed to be compatible with Vulkan, in particular it allows for developers to add more complex low-level Vulkan code to their V-EZ project when needed. This presented a couple of minor technical issues, given that V-EZ contains similar function and object declarations found in Vulkan: V-EZ and Vulkan header files cannot be included within the same source file, and linking against both V-EZ and Vulkan will result in linker errors. To circumvent the latter, V-EZ includes a dynamic runtime linking utility header so that entry points may be retrieved at runtime and not conflict with those found within the Vulkan library.
To support applications requiring third party libraries which use Vulkan, many object handles returned by V-EZ are the native ones. These include the following:
Given the additional level of responsibility V-EZ alleviates from applications, other object handles cannot be directly used with Vulkan. These include the obvious ones missing from the list above, namely VkCommandBuffer, VkPipeline and VkFramebuffer.
Memory management has been greatly simplified in V-EZ. Applications deal only with buffer and image object handles while given the flexibility to still specify residency and sub-allocation flags. These flags are reduced to the following set of self-explanatory enumeration values.
Low level details of heap types and their properties is no longer required by applications. Managing VkMemory object handles alongside the buffers and images they back is no longer required.
Automated Descriptor Sets
Descriptor sets and pools are no longer explicitly exposed in V-EZ. Applications are no longer responsible for managing descriptor pools, pool sizes, descriptor set layouts or compatibility with bound pipelines. Rather, an OpenGL style resource binding model is employed allowing applications to employ a more ad-hoc approach. Existing Vulkan best practices with set and binding indices are still applicable however and should be observed. Below are the set of resource binding functions provided by V-EZ. These functions do not require a valid pipeline to be bound or require that they be called again when a pipeline binding changes. They remain valid throughout the scope of a command buffer.
void vkCmdBindBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, uint32_t set, uint32_t binding, uint32_t arrayElement);
void vkCmdBindBufferRange(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range, uint32_t set, uint32_t binding, uint32_t arrayElement);
void vkCmdBindBufferView(VkCommandBuffer commandBuffer, VkBufferView bufferView, uint32_t set, uint32_t binding, uint32_t arrayElement);
void vkCmdBindImageView(VkCommandBuffer commandBuffer, VkImageView imageView, VkSampler sampler, uint32_t set, uint32_t binding, uint32_t arrayElement);
void vkCmdBindSampler(VkCommandBuffer commandBuffer, VkSampler sampler, uint32_t set, uint32_t binding, uint32_t arrayElement);
Automated Pipeline Barriers
Alongside memory management, pipeline barriers are one of the most complex topics to master in the VulkanAPI. As a middleware solution, V-EZ can make intelligent decisions about when and where pipeline barriers are required. With V-EZ, applications are no longer required to handle synchronization of resources at any level or to handle image layout transitions. Pipeline barriers are inserted on demand when read/write hazards are detected. With V-EZ, an application may write to a buffer in a compute shader, then immediately use that buffer as input to a graphics pipeline. No explicit synchronization is required.
Handling pipeline permutations in Vulkan can be quite cumbersome for applications. V-EZ alleviates this burden by decoupling graphics state and vertex input format from pipeline creation. Applications need only specify the set of shader modules for a given pipeline. All graphics state is now set ad-hoc during command buffer recording. This state remains valid throughout the scope of a command buffer and between pipeline bindings. Existing best practices are still encouraged to minimize the cost of binding new pipelines.
V-EZ does not require an application to create render passes up front. Rather, render passes, their subpasses and synchronization details are implicitly set or deduced at runtime. Synchronization between subpasses is handled similarly to pipeline barriers. No responsibility is placed on the application as the heavy lifting is done by V-EZ. Use of input attachments need only be specified within the GLSL or SPIR-V shader source. No details or API calls are required on the host.
V-EZ makes GLSL a first-class citizen again. Applications are given the flexibility to specify either GLSL or SPIR-V as input to a shader module. Once a pipeline is created, applications also have access to full reflection information of each stage, which includes all bindings (textures, samplers, uniform buffers, storage buffers, inputs, outputs, etc)
Minimal Performance Overhead
Some performance overhead can be expected with V-EZ given the additional level of responsibility it removes from the application. However, this overhead is negligible and measured in the range of microseconds for tens of thousands of API calls during command buffer recording.
V-EZ is available for download from the GPUOpen GitHub. V-EZ is being released as closed source. However AMD will work with professional ISVs who would benefit from acquiring the source code. As always, we’d love to hear about how you’re using V-EZ and what other features you’d like to learn. To learn more visit GPUopen.com and subscribe to AMD Developer News to stay up to date.