Imagination Technologies Public
Revision PowerVR SDK REL_18.1@5080009a 4 Migrating from OpenGL ES
2. Paradigm shift
2.1. Explicit control
2.1.1. Transparent driver model
When using previous generation graphics APIs, the graphics driver might often seem like a black box
to the developer. Everything is hidden and abstracted away and a developer may feel they do not
have any control over what happens behind the scenes. The developer only instructs the API to do a
specific task, and it is up to the graphics driver to decide how to do it.
With the new Vulkan API, the developer has explicit control over what the hardware does and does
not do. The driver layer is significantly slimmer, everything is exposed and the developer has full
control. The developer tells the driver exactly what they want to happen, and the graphics driver has
to do minimal guesswork.
2.1.2. API objects/states
The old way that graphics APIs followed was that there was a single global render state that the
developer could modify. Based on this state the driver had to figure out what commands to create on
the fly that the GPU can execute. To add to these issues, this approach was very error prone. This is
because the developer had to make sure that at the point of issuing a draw command the render state
was correct and what they want it to be.
The new way of doing this is to prepare all the API objects that describe what actions to take
beforehand. This way the graphic driver does not have to decide anything, just translate the actions
into machine code and execute it on the GPU. This approach is less error prone as the API objects
usually do not change. The only thing a developer has to make sure of is that the right API object is
bound, and that object has the right content.
2.1.3. Synchronisation
Synchronisation in software engineering can be a challenging problem. That is why in the previous
generation of APIs it was hidden from the developer. Only coarse-grained synchronisation was
possible in some places. In some cases it would be expected that the driver would synchronise the
CPU and the GPU, in other words one of them would have to wait for the other. This also meant that
sync points could exist without the developer knowing about them, and performance could be poor for
no apparent reason.
In the new Vulkan API, synchronisation is explicitly specified in a fine-grained manner. This is
supported by fences, semaphores, events and barriers:
Fences are used to communicate the completion of execution of command buffer
submissions to queues
Semaphores can be used to marshal ownership of shared data
Events provide fine-grained synchronisation primitives that can be signalled and waited upon
at command level granularity
Barriers provide execution and memory synchronisation between sets of commands
This does make development more difficult, but it also enables the developer to do things that were
previously impossible due to the black box driver model. It is now possible to do precise and efficient
synchronisation, which could make migrating to Vulkan worthwhile.
2.1.4. Explicit image layout transitions
One of the things that used to happen outside the developer’s control with the old APIs was image
layout transitions. Image layouts specify how the driver should organise pixels in memory. Due to the
way GPUs work, storing pixels in a linear fashion does not give an optimal performance, and instead
pixels are stored in a zig-zag pattern. Drivers always tried to keep images (textures) in the best
possible layout so that sampling or using them as render targets always had the best performance.
Unfortunately sometimes this resulted in unnecessary transitions.