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