Home | History | Annotate | Download | only in graphics
      1 <html devsite>
      2   <head>
      3     <title>Implementing Vulkan</title>
      4     <meta name="project_path" value="/_project.yaml" />
      5     <meta name="book_path" value="/_book.yaml" />
      6   </head>
      7   <body>
      8   <!--
      9       Copyright 2017 The Android Open Source Project
     10 
     11       Licensed under the Apache License, Version 2.0 (the "License");
     12       you may not use this file except in compliance with the License.
     13       You may obtain a copy of the License at
     14 
     15           http://www.apache.org/licenses/LICENSE-2.0
     16 
     17       Unless required by applicable law or agreed to in writing, software
     18       distributed under the License is distributed on an "AS IS" BASIS,
     19       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     20       See the License for the specific language governing permissions and
     21       limitations under the License.
     22   -->
     23 
     24 
     25 
     26 
     27 <p>Vulkan is a low-overhead, cross-platform API for high-performance 3D
     28 graphics. Like OpenGL ES, Vulkan provides tools for creating high-quality,
     29 real-time graphics in applications. Vulkan advantages include reductions in CPU
     30 overhead and support for the <a href="https://www.khronos.org/spir">SPIR-V
     31 Binary Intermediate</a> language.</p>
     32 
     33 <p class="note"><strong>Note:</strong> This section describes Vulkan
     34 implementation; for details on Vulkan architecture, advantages, API, and other
     35 resources, see <a href="/devices/graphics/arch-vulkan.html">Vulkan
     36 Architecture</a>.</p>
     37 
     38 <p>To implement Vulkan, a device:</p>
     39 <ul>
     40 <li>Must include the Vulkan Loader (provided by Android) in the build.</li>
     41 <li>Must include a Vulkan driver (provided by SoCs such as GPU IHVs) that
     42 implements the
     43 <a href="https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/xhtml/vkspec.html">Vulkan
     44 API</a>. To support Vulkan functionality, the Android device needs capable GPU
     45 hardware and the associated driver. Consult your SoC vendor to request driver
     46 support.</li>
     47 </ul>
     48 <p>If a Vulkan driver is available on the device, the device needs to declare
     49 <code>FEATURE_VULKAN_HARDWARE_LEVEL</code> and
     50 <code>FEATURE_VULKAN_HARDWARE_VERSION</code> system features, with versions that
     51 accurately reflect the capabilities of the device.</p>
     52 
     53 <h2 id=vulkan_loader>Vulkan Loader</h2>
     54 <p>The primary interface between Vulkan applications and a device's Vulkan
     55 driver is the Vulkan loader, which is part of Android Open Source Project (AOSP)
     56 (<code>platform/frameworks/native/vulkan</code>) and installed at
     57 <code>/system/lib[64]/libvulkan.so</code>. The loader provides the core Vulkan
     58 API entry points, as well as entry points of a few extensions that are required
     59 on Android and always present. In particular, Window System Integration (WSI)
     60 extensions are exported by the loader and primarily implemented in it rather
     61 than the driver. The loader also supports enumerating and loading layers that
     62 can expose additional extensions and/or intercept core API calls on their way to
     63 the driver.</p>
     64 
     65 <p>The NDK includes a stub <code>libvulkan.so</code> library that exports the
     66 same symbols as the loader and which is used for linking. When running on a
     67 device, applications call the Vulkan functions exported from
     68 <code>libvulkan.so</code> (the real library, not the stub) to enter trampoline
     69 functions in the loader (which then dispatch to the appropriate layer or driver
     70 based on their first argument). The <code>vkGetDeviceProcAddr</code> calls
     71 return the function pointers to which the trampolines would dispatch (i.e. it
     72 calls directly into the core API code), so calling through these function
     73 pointers (rather than the exported symbols) is slightly more efficient as it
     74 skips the trampoline and dispatch. However, <code>vkGetInstanceProcAddr</code>
     75 must still call into trampoline code.</p>
     76 
     77 <h2 id=driver_emun>Driver enumeration and loading</h2>
     78 <p>Android expects the GPUs available to the system to be known when the system
     79 image is built. The loader uses the existing HAL mechanism (see <code><a href="https://android.googlesource.com/platform/hardware/libhardware/+/master/include/hardware/hardware.h">hardware.h</code></a>)
     80 for discovering and loading the driver. Preferred paths for 32-bit and 64-bit
     81 Vulkan drivers are:</p>
     82 
     83 <pre class="devsite-click-to-copy">
     84 /vendor/lib/hw/vulkan.&lt;ro.product.platform&gt;.so
     85 /vendor/lib64/hw/vulkan.&lt;ro.product.platform&gt;.so
     86 </pre>
     87 
     88 <p>Where &lt;<code>ro.product.platform</code>&gt; is replaced by the value of
     89 the system property of that name. For details and supported alternative
     90 locations, refer to <code><a href="https://android.googlesource.com/platform/hardware/libhardware/+/master/hardware.c">libhardware/hardware.c</code></a>.</p>
     91 
     92 <p>In Android 7.0, the Vulkan <code>hw_module_t</code> derivative is trivial;
     93 only one driver is supported and the constant string
     94 <code>HWVULKAN_DEVICE_0</code> is passed to open. If support for multiple
     95 drivers is added in future versions of Android, the HAL module will export a
     96 list of strings that can be passed to the <code>module open</code> call.</p>
     97 
     98 <p>The Vulkan <code>hw_device_t</code> derivative corresponds to a single
     99 driver, though that driver can support multiple physical devices. The
    100 <code>hw_device_t</code> structure can be extended to export
    101 <code>vkGetGlobalExtensionProperties</code>, <code>vkCreateInstance</code>, and
    102 <code>vkGetInstanceProcAddr</code> functions. The loader can find all other
    103 <code>VkInstance</code>, <code>VkPhysicalDevice</code>, and
    104 <code>vkGetDeviceProcAddr</code> functions by calling
    105 <code>vkGetInstanceProcAddr</code>.</p>
    106 
    107 <h2 id=layer_discover>Layer discovery and loading</h2>
    108 <p>The Vulkan loader supports enumerating and loading layers that can expose
    109 additional extensions and/or intercept core API calls on their way to the
    110 driver. Android 7.0 does not include layers on the system image; however,
    111 applications may include layers in their APK.</p>
    112 <p>When using layers, keep in mind that Android's security model and policies
    113 differ significantly from other platforms. In particular, Android does not allow
    114 loading external code into a non-debuggable process on production (non-rooted)
    115 devices, nor does it allow external code to inspect or control the process's
    116 memory, state, etc. This includes a prohibition on saving core dumps, API
    117 traces, etc. to disk for later inspection. Only layers delivered as part of the
    118 application are enabled on production devices, and drivers must not provide
    119 functionality that violates these policies.</p>
    120 
    121 <p>Use cases for layers include:</p>
    122 <ul>
    123 <li><strong>Development-time layers</strong>. These layers (validation layers,
    124 shims for tracing/profiling/debugging tools, etc.) should not be installed on
    125 the system image of production devices as they waste space for users and should
    126 be updateable without requiring a system update. Developers who want to use one
    127 of these layers during development can modify the application package (e.g.
    128 adding a file to their native libraries directory). IHV and OEM engineers who
    129 want to diagnose failures in shipping, unmodifiable apps are assumed to have
    130 access to non-production (rooted) builds of the system image.</li>
    131 <li><strong>Utility layers</strong>. These layers almost always expose
    132 extensions, such as a layer that implements a memory manager for device memory.
    133 Developers choose layers (and versions of those layers) to use in their
    134 application; different applications using the same layer may still use
    135 different versions. Developers choose which of these layers to ship in their
    136 application package.</li>
    137 <li><strong>Injected (implicit) layers</strong>. Includes layers such as
    138 framerate, social network, or game launcher overlays provided by the user or
    139 some other application without the application's knowledge or consent. These
    140 violate Android's security policies and are not supported.</li>
    141 </ul>
    142 
    143 <p>In the normal state, the loader searches for layers only in the application's
    144 native library directory and attempts to load any library with a name matching a
    145 particular pattern (e.g. <code>libVKLayer_foo.so</code>). It does not need a
    146 separate manifest file as the developer deliberately included these layers and
    147 reasons to avoid loading libraries before enabling them don't apply.</p>
    148 
    149 <p>Android allows layers to be ported with build-environment changes between
    150 Android and other platforms. For details on the interface between layers and the
    151 loader, refer to
    152 <a href="https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md">Vulkan
    153 Loader Specification and Architecture Overview</a>. Versions of the LunarG
    154 validation layers that have been verified to build and work on Android are
    155 hosted in the android_layers branch of the
    156 <a href="https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/tree/android_layers">KhronosGroup/Vulkan-LoaderAndValidationLayers</a>
    157 project on GitHub.</p>
    158 
    159 <h2 id=wsi>Window System Integration (WSI)</h2>
    160 <p>The Window System Integration (WSI) extensions <code>VK_KHR_surface</code>,
    161 <code>VK_KHR_android_surface</code>, and <code>VK_KHR_swapchain</code> are
    162 implemented by the platform and live in <code>libvulkan.so</code>. The
    163 <code>VkSurfaceKHR</code> and <code>VkSwapchainKHR</code> objects and all
    164 interaction with <code>ANativeWindow</code> is handled by the platform and is
    165 not exposed to drivers. The WSI implementation relies on the
    166 <code>VK_ANDROID_native_buffer</code> extension (described below) which must be
    167 supported by the driver; this extension is only used by the WSI implementation
    168 and will not be exposed to applications.</p>
    169 
    170 <h3 id=gralloc_usage_flags>Gralloc usage flags</h3>
    171 <p>Implementations may need swapchain buffers to be allocated with
    172 implementation-defined private gralloc usage flags. When creating a swapchain,
    173 the platform asks the driver to translate the requested format and image usage
    174 flags into gralloc usage flags by calling:</p>
    175 
    176 <pre class="devsite-click-to-copy">
    177 VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
    178     VkDevice            device,
    179     VkFormat            format,
    180     VkImageUsageFlags   imageUsage,
    181     int*                grallocUsage
    182 );
    183 </pre>
    184 
    185 <p>The <code>format</code> and <code>imageUsage</code> parameters are taken from
    186 the <code>VkSwapchainCreateInfoKHR</code> structure. The driver should fill
    187 <code>*grallocUsage</code> with the gralloc usage flags required for the format
    188 and usage (which are combined with the usage flags requested by the swapchain
    189 consumer when allocating buffers).</p>
    190 
    191 <h3 id=gralloc_usage_flags>Gralloc-backed images</h3>
    192 
    193 <p><code>VkNativeBufferANDROID</code> is a <code>vkCreateImage</code> extension
    194 structure for creating an image backed by a gralloc buffer. This structure is
    195 provided to <code>vkCreateImage</code> in the <code>VkImageCreateInfo</code>
    196 structure chain. Calls to <code>vkCreateImage</code> with this structure happen
    197 during the first call to <code>vkGetSwapChainInfoWSI(..
    198 VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)</code>. The WSI implementation allocates
    199 the number of native buffers requested for the swapchain, then creates a
    200 <code>VkImage</code> for each one:</p>
    201 
    202 <pre class="devsite-click-to-copy">
    203 typedef struct {
    204     VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
    205     const void*                 pNext;
    206 
    207     // Buffer handle and stride returned from gralloc alloc()
    208     buffer_handle_t             handle;
    209     int                         stride;
    210 
    211     // Gralloc format and usage requested when the buffer was allocated.
    212     int                         format;
    213     int                         usage;
    214 } VkNativeBufferANDROID;
    215 </pre>
    216 
    217 <p>When creating a gralloc-backed image, the <code>VkImageCreateInfo</code> has
    218 the following data:</p>
    219 
    220 <pre class="devsite-click-to-copy">
    221  .imageType           = VK_IMAGE_TYPE_2D
    222   .format              = a VkFormat matching the format requested for the gralloc buffer
    223   .extent              = the 2D dimensions requested for the gralloc buffer
    224   .mipLevels           = 1
    225   .arraySize           = 1
    226   .samples             = 1
    227   .tiling              = VK_IMAGE_TILING_OPTIMAL
    228   .usage               = VkSwapChainCreateInfoWSI::imageUsageFlags
    229   .flags               = 0
    230   .sharingMode         = VkSwapChainCreateInfoWSI::sharingMode
    231   .queueFamilyCount    = VkSwapChainCreateInfoWSI::queueFamilyCount
    232   .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices
    233 </pre>
    234 
    235 <h3 id=acquire_image>Aquiring images</h3>
    236 <p><code>vkAcquireImageANDROID</code> acquires ownership of a swapchain image
    237 and imports an externally-signalled native fence into both an existing
    238 <code>VkSemaphore</code> object and an existing <code>VkFence</code> object:</p>
    239 
    240 <pre class="devsite-click-to-copy">
    241 VkResult VKAPI vkAcquireImageANDROID(
    242     VkDevice            device,
    243     VkImage             image,
    244     int                 nativeFenceFd,
    245     VkSemaphore         semaphore,
    246     VkFence             fence
    247 );
    248 </pre>
    249 
    250 <p>This function is called during <code>vkAcquireNextImageWSI</code> to import a
    251 native fence into the <code>VkSemaphore</code> and <code>VkFence</code> objects
    252 provided by the application (however, both semaphore and fence objects are
    253 optional in this call). The driver may also use this opportunity to recognize
    254 and handle any external changes to the gralloc buffer state; many drivers won't
    255 need to do anything here. This call puts the <code>VkSemaphore</code> and
    256 <code>VkFence</code> into the same pending state as
    257 <code>vkQueueSignalSemaphore</code> and <code>vkQueueSubmit</code> respectively,
    258 so queues can wait on the semaphore and the application can wait on the fence.</p>
    259 
    260 <p>Both objects become signalled when the underlying native fence signals; if
    261 the native fence has already signalled, then the semaphore is in the signalled
    262 state when this function returns. The driver takes ownership of the fence fd and
    263 is responsible for closing it when no longer needed. It must do so even if
    264 neither a semaphore or fence object is provided, or even if
    265 <code>vkAcquireImageANDROID</code> fails and returns an error. If fenceFd is -1,
    266 it is as if the native fence was already signalled.</p>
    267 
    268 <h3 id=acquire_image>Releasing images</h3>
    269 <p><code>vkQueueSignalReleaseImageANDROID</code> prepares a swapchain image for
    270 external use, and creates a native fence and schedules it to be signalled when
    271 prior work on the queue has completed:</p>
    272 
    273 <pre class="devsite-click-to-copy">
    274 VkResult VKAPI vkQueueSignalReleaseImageANDROID(
    275     VkQueue             queue,
    276     VkImage             image,
    277     int*                pNativeFenceFd
    278 );
    279 </pre>
    280 
    281 <p>This API is called during <code>vkQueuePresentWSI</code> on the provided
    282 queue. Effects are similar to <code>vkQueueSignalSemaphore</code>, except with a
    283 native fence instead of a semaphore. Unlike <code>vkQueueSignalSemaphore</code>,
    284 however, this call creates and returns the synchronization object that will be
    285 signalled rather than having it provided as input. If the queue is already idle
    286 when this function is called, it is allowed (but not required) to set
    287 <code>*pNativeFenceFd</code> to -1. The file descriptor returned in
    288 *<code>pNativeFenceFd</code> is owned and will be closed by the caller.</p>
    289 
    290 <h3 id=update_drivers>Updating drivers</h3>
    291 
    292 <p>Many drivers can ignore the image parameter, but some may need to prepare
    293 CPU-side data structures associated with a gralloc buffer for use by external
    294 image consumers. Preparing buffer contents for use by external consumers should
    295 have been done asynchronously as part of transitioning the image to
    296 <code>VK_IMAGE_LAYOUT_PRESENT_SRC_KHR</code>.</p>
    297 
    298 <h2 id=validation>Validation</h2>
    299 <p>OEMs can test their Vulkan implementation using CTS, which includes
    300 <a href="/devices/graphics/cts-integration.html">drawElements
    301 Quality Program (dEQP)</a> tests that exercise the Vulkan Runtime.</p>
    302 
    303   </body>
    304 </html>
    305