• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5<meta name="generator" content="AsciiDoc 8.6.9">
6<title>Vulkan on Android Implementor&#8217;s Guide</title>
7<style type="text/css">
8/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
9
10/* Default font. */
11body {
12  font-family: Georgia,serif;
13}
14
15/* Title font. */
16h1, h2, h3, h4, h5, h6,
17div.title, caption.title,
18thead, p.table.header,
19#toctitle,
20#author, #revnumber, #revdate, #revremark,
21#footer {
22  font-family: Arial,Helvetica,sans-serif;
23}
24
25body {
26  margin: 1em 5% 1em 5%;
27}
28
29a {
30  color: blue;
31  text-decoration: underline;
32}
33a:visited {
34  color: fuchsia;
35}
36
37em {
38  font-style: italic;
39  color: navy;
40}
41
42strong {
43  font-weight: bold;
44  color: #083194;
45}
46
47h1, h2, h3, h4, h5, h6 {
48  color: #527bbd;
49  margin-top: 1.2em;
50  margin-bottom: 0.5em;
51  line-height: 1.3;
52}
53
54h1, h2, h3 {
55  border-bottom: 2px solid silver;
56}
57h2 {
58  padding-top: 0.5em;
59}
60h3 {
61  float: left;
62}
63h3 + * {
64  clear: left;
65}
66h5 {
67  font-size: 1.0em;
68}
69
70div.sectionbody {
71  margin-left: 0;
72}
73
74hr {
75  border: 1px solid silver;
76}
77
78p {
79  margin-top: 0.5em;
80  margin-bottom: 0.5em;
81}
82
83ul, ol, li > p {
84  margin-top: 0;
85}
86ul > li     { color: #aaa; }
87ul > li > * { color: black; }
88
89.monospaced, code, pre {
90  font-family: "Courier New", Courier, monospace;
91  font-size: inherit;
92  color: navy;
93  padding: 0;
94  margin: 0;
95}
96pre {
97  white-space: pre-wrap;
98}
99
100#author {
101  color: #527bbd;
102  font-weight: bold;
103  font-size: 1.1em;
104}
105#email {
106}
107#revnumber, #revdate, #revremark {
108}
109
110#footer {
111  font-size: small;
112  border-top: 2px solid silver;
113  padding-top: 0.5em;
114  margin-top: 4.0em;
115}
116#footer-text {
117  float: left;
118  padding-bottom: 0.5em;
119}
120#footer-badges {
121  float: right;
122  padding-bottom: 0.5em;
123}
124
125#preamble {
126  margin-top: 1.5em;
127  margin-bottom: 1.5em;
128}
129div.imageblock, div.exampleblock, div.verseblock,
130div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
131div.admonitionblock {
132  margin-top: 1.0em;
133  margin-bottom: 1.5em;
134}
135div.admonitionblock {
136  margin-top: 2.0em;
137  margin-bottom: 2.0em;
138  margin-right: 10%;
139  color: #606060;
140}
141
142div.content { /* Block element content. */
143  padding: 0;
144}
145
146/* Block element titles. */
147div.title, caption.title {
148  color: #527bbd;
149  font-weight: bold;
150  text-align: left;
151  margin-top: 1.0em;
152  margin-bottom: 0.5em;
153}
154div.title + * {
155  margin-top: 0;
156}
157
158td div.title:first-child {
159  margin-top: 0.0em;
160}
161div.content div.title:first-child {
162  margin-top: 0.0em;
163}
164div.content + div.title {
165  margin-top: 0.0em;
166}
167
168div.sidebarblock > div.content {
169  background: #ffffee;
170  border: 1px solid #dddddd;
171  border-left: 4px solid #f0f0f0;
172  padding: 0.5em;
173}
174
175div.listingblock > div.content {
176  border: 1px solid #dddddd;
177  border-left: 5px solid #f0f0f0;
178  background: #f8f8f8;
179  padding: 0.5em;
180}
181
182div.quoteblock, div.verseblock {
183  padding-left: 1.0em;
184  margin-left: 1.0em;
185  margin-right: 10%;
186  border-left: 5px solid #f0f0f0;
187  color: #888;
188}
189
190div.quoteblock > div.attribution {
191  padding-top: 0.5em;
192  text-align: right;
193}
194
195div.verseblock > pre.content {
196  font-family: inherit;
197  font-size: inherit;
198}
199div.verseblock > div.attribution {
200  padding-top: 0.75em;
201  text-align: left;
202}
203/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
204div.verseblock + div.attribution {
205  text-align: left;
206}
207
208div.admonitionblock .icon {
209  vertical-align: top;
210  font-size: 1.1em;
211  font-weight: bold;
212  text-decoration: underline;
213  color: #527bbd;
214  padding-right: 0.5em;
215}
216div.admonitionblock td.content {
217  padding-left: 0.5em;
218  border-left: 3px solid #dddddd;
219}
220
221div.exampleblock > div.content {
222  border-left: 3px solid #dddddd;
223  padding-left: 0.5em;
224}
225
226div.imageblock div.content { padding-left: 0; }
227span.image img { border-style: none; vertical-align: text-bottom; }
228a.image:visited { color: white; }
229
230dl {
231  margin-top: 0.8em;
232  margin-bottom: 0.8em;
233}
234dt {
235  margin-top: 0.5em;
236  margin-bottom: 0;
237  font-style: normal;
238  color: navy;
239}
240dd > *:first-child {
241  margin-top: 0.1em;
242}
243
244ul, ol {
245    list-style-position: outside;
246}
247ol.arabic {
248  list-style-type: decimal;
249}
250ol.loweralpha {
251  list-style-type: lower-alpha;
252}
253ol.upperalpha {
254  list-style-type: upper-alpha;
255}
256ol.lowerroman {
257  list-style-type: lower-roman;
258}
259ol.upperroman {
260  list-style-type: upper-roman;
261}
262
263div.compact ul, div.compact ol,
264div.compact p, div.compact p,
265div.compact div, div.compact div {
266  margin-top: 0.1em;
267  margin-bottom: 0.1em;
268}
269
270tfoot {
271  font-weight: bold;
272}
273td > div.verse {
274  white-space: pre;
275}
276
277div.hdlist {
278  margin-top: 0.8em;
279  margin-bottom: 0.8em;
280}
281div.hdlist tr {
282  padding-bottom: 15px;
283}
284dt.hdlist1.strong, td.hdlist1.strong {
285  font-weight: bold;
286}
287td.hdlist1 {
288  vertical-align: top;
289  font-style: normal;
290  padding-right: 0.8em;
291  color: navy;
292}
293td.hdlist2 {
294  vertical-align: top;
295}
296div.hdlist.compact tr {
297  margin: 0;
298  padding-bottom: 0;
299}
300
301.comment {
302  background: yellow;
303}
304
305.footnote, .footnoteref {
306  font-size: 0.8em;
307}
308
309span.footnote, span.footnoteref {
310  vertical-align: super;
311}
312
313#footnotes {
314  margin: 20px 0 20px 0;
315  padding: 7px 0 0 0;
316}
317
318#footnotes div.footnote {
319  margin: 0 0 5px 0;
320}
321
322#footnotes hr {
323  border: none;
324  border-top: 1px solid silver;
325  height: 1px;
326  text-align: left;
327  margin-left: 0;
328  width: 20%;
329  min-width: 100px;
330}
331
332div.colist td {
333  padding-right: 0.5em;
334  padding-bottom: 0.3em;
335  vertical-align: top;
336}
337div.colist td img {
338  margin-top: 0.3em;
339}
340
341@media print {
342  #footer-badges { display: none; }
343}
344
345#toc {
346  margin-bottom: 2.5em;
347}
348
349#toctitle {
350  color: #527bbd;
351  font-size: 1.1em;
352  font-weight: bold;
353  margin-top: 1.0em;
354  margin-bottom: 0.1em;
355}
356
357div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
358  margin-top: 0;
359  margin-bottom: 0;
360}
361div.toclevel2 {
362  margin-left: 2em;
363  font-size: 0.9em;
364}
365div.toclevel3 {
366  margin-left: 4em;
367  font-size: 0.9em;
368}
369div.toclevel4 {
370  margin-left: 6em;
371  font-size: 0.9em;
372}
373
374span.aqua { color: aqua; }
375span.black { color: black; }
376span.blue { color: blue; }
377span.fuchsia { color: fuchsia; }
378span.gray { color: gray; }
379span.green { color: green; }
380span.lime { color: lime; }
381span.maroon { color: maroon; }
382span.navy { color: navy; }
383span.olive { color: olive; }
384span.purple { color: purple; }
385span.red { color: red; }
386span.silver { color: silver; }
387span.teal { color: teal; }
388span.white { color: white; }
389span.yellow { color: yellow; }
390
391span.aqua-background { background: aqua; }
392span.black-background { background: black; }
393span.blue-background { background: blue; }
394span.fuchsia-background { background: fuchsia; }
395span.gray-background { background: gray; }
396span.green-background { background: green; }
397span.lime-background { background: lime; }
398span.maroon-background { background: maroon; }
399span.navy-background { background: navy; }
400span.olive-background { background: olive; }
401span.purple-background { background: purple; }
402span.red-background { background: red; }
403span.silver-background { background: silver; }
404span.teal-background { background: teal; }
405span.white-background { background: white; }
406span.yellow-background { background: yellow; }
407
408span.big { font-size: 2em; }
409span.small { font-size: 0.6em; }
410
411span.underline { text-decoration: underline; }
412span.overline { text-decoration: overline; }
413span.line-through { text-decoration: line-through; }
414
415div.unbreakable { page-break-inside: avoid; }
416
417
418/*
419 * xhtml11 specific
420 *
421 * */
422
423div.tableblock {
424  margin-top: 1.0em;
425  margin-bottom: 1.5em;
426}
427div.tableblock > table {
428  border: 3px solid #527bbd;
429}
430thead, p.table.header {
431  font-weight: bold;
432  color: #527bbd;
433}
434p.table {
435  margin-top: 0;
436}
437/* Because the table frame attribute is overriden by CSS in most browsers. */
438div.tableblock > table[frame="void"] {
439  border-style: none;
440}
441div.tableblock > table[frame="hsides"] {
442  border-left-style: none;
443  border-right-style: none;
444}
445div.tableblock > table[frame="vsides"] {
446  border-top-style: none;
447  border-bottom-style: none;
448}
449
450
451/*
452 * html5 specific
453 *
454 * */
455
456table.tableblock {
457  margin-top: 1.0em;
458  margin-bottom: 1.5em;
459}
460thead, p.tableblock.header {
461  font-weight: bold;
462  color: #527bbd;
463}
464p.tableblock {
465  margin-top: 0;
466}
467table.tableblock {
468  border-width: 3px;
469  border-spacing: 0px;
470  border-style: solid;
471  border-color: #527bbd;
472  border-collapse: collapse;
473}
474th.tableblock, td.tableblock {
475  border-width: 1px;
476  padding: 4px;
477  border-style: solid;
478  border-color: #527bbd;
479}
480
481table.tableblock.frame-topbot {
482  border-left-style: hidden;
483  border-right-style: hidden;
484}
485table.tableblock.frame-sides {
486  border-top-style: hidden;
487  border-bottom-style: hidden;
488}
489table.tableblock.frame-none {
490  border-style: hidden;
491}
492
493th.tableblock.halign-left, td.tableblock.halign-left {
494  text-align: left;
495}
496th.tableblock.halign-center, td.tableblock.halign-center {
497  text-align: center;
498}
499th.tableblock.halign-right, td.tableblock.halign-right {
500  text-align: right;
501}
502
503th.tableblock.valign-top, td.tableblock.valign-top {
504  vertical-align: top;
505}
506th.tableblock.valign-middle, td.tableblock.valign-middle {
507  vertical-align: middle;
508}
509th.tableblock.valign-bottom, td.tableblock.valign-bottom {
510  vertical-align: bottom;
511}
512
513
514/*
515 * manpage specific
516 *
517 * */
518
519body.manpage h1 {
520  padding-top: 0.5em;
521  padding-bottom: 0.5em;
522  border-top: 2px solid silver;
523  border-bottom: 2px solid silver;
524}
525body.manpage h2 {
526  border-style: none;
527}
528body.manpage div.sectionbody {
529  margin-left: 3em;
530}
531
532@media print {
533  body.manpage div#toc { display: none; }
534}
535
536
537</style>
538<script type="text/javascript">
539/*<![CDATA[*/
540var asciidoc = {  // Namespace.
541
542/////////////////////////////////////////////////////////////////////
543// Table Of Contents generator
544/////////////////////////////////////////////////////////////////////
545
546/* Author: Mihai Bazon, September 2002
547 * http://students.infoiasi.ro/~mishoo
548 *
549 * Table Of Content generator
550 * Version: 0.4
551 *
552 * Feel free to use this script under the terms of the GNU General Public
553 * License, as long as you do not remove or alter this notice.
554 */
555
556 /* modified by Troy D. Hanson, September 2006. License: GPL */
557 /* modified by Stuart Rackham, 2006, 2009. License: GPL */
558
559// toclevels = 1..4.
560toc: function (toclevels) {
561
562  function getText(el) {
563    var text = "";
564    for (var i = el.firstChild; i != null; i = i.nextSibling) {
565      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
566        text += i.data;
567      else if (i.firstChild != null)
568        text += getText(i);
569    }
570    return text;
571  }
572
573  function TocEntry(el, text, toclevel) {
574    this.element = el;
575    this.text = text;
576    this.toclevel = toclevel;
577  }
578
579  function tocEntries(el, toclevels) {
580    var result = new Array;
581    var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
582    // Function that scans the DOM tree for header elements (the DOM2
583    // nodeIterator API would be a better technique but not supported by all
584    // browsers).
585    var iterate = function (el) {
586      for (var i = el.firstChild; i != null; i = i.nextSibling) {
587        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
588          var mo = re.exec(i.tagName);
589          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
590            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
591          }
592          iterate(i);
593        }
594      }
595    }
596    iterate(el);
597    return result;
598  }
599
600  var toc = document.getElementById("toc");
601  if (!toc) {
602    return;
603  }
604
605  // Delete existing TOC entries in case we're reloading the TOC.
606  var tocEntriesToRemove = [];
607  var i;
608  for (i = 0; i < toc.childNodes.length; i++) {
609    var entry = toc.childNodes[i];
610    if (entry.nodeName.toLowerCase() == 'div'
611     && entry.getAttribute("class")
612     && entry.getAttribute("class").match(/^toclevel/))
613      tocEntriesToRemove.push(entry);
614  }
615  for (i = 0; i < tocEntriesToRemove.length; i++) {
616    toc.removeChild(tocEntriesToRemove[i]);
617  }
618
619  // Rebuild TOC entries.
620  var entries = tocEntries(document.getElementById("content"), toclevels);
621  for (var i = 0; i < entries.length; ++i) {
622    var entry = entries[i];
623    if (entry.element.id == "")
624      entry.element.id = "_toc_" + i;
625    var a = document.createElement("a");
626    a.href = "#" + entry.element.id;
627    a.appendChild(document.createTextNode(entry.text));
628    var div = document.createElement("div");
629    div.appendChild(a);
630    div.className = "toclevel" + entry.toclevel;
631    toc.appendChild(div);
632  }
633  if (entries.length == 0)
634    toc.parentNode.removeChild(toc);
635},
636
637
638/////////////////////////////////////////////////////////////////////
639// Footnotes generator
640/////////////////////////////////////////////////////////////////////
641
642/* Based on footnote generation code from:
643 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
644 */
645
646footnotes: function () {
647  // Delete existing footnote entries in case we're reloading the footnodes.
648  var i;
649  var noteholder = document.getElementById("footnotes");
650  if (!noteholder) {
651    return;
652  }
653  var entriesToRemove = [];
654  for (i = 0; i < noteholder.childNodes.length; i++) {
655    var entry = noteholder.childNodes[i];
656    if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
657      entriesToRemove.push(entry);
658  }
659  for (i = 0; i < entriesToRemove.length; i++) {
660    noteholder.removeChild(entriesToRemove[i]);
661  }
662
663  // Rebuild footnote entries.
664  var cont = document.getElementById("content");
665  var spans = cont.getElementsByTagName("span");
666  var refs = {};
667  var n = 0;
668  for (i=0; i<spans.length; i++) {
669    if (spans[i].className == "footnote") {
670      n++;
671      var note = spans[i].getAttribute("data-note");
672      if (!note) {
673        // Use [\s\S] in place of . so multi-line matches work.
674        // Because JavaScript has no s (dotall) regex flag.
675        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
676        spans[i].innerHTML =
677          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
678          "' title='View footnote' class='footnote'>" + n + "</a>]";
679        spans[i].setAttribute("data-note", note);
680      }
681      noteholder.innerHTML +=
682        "<div class='footnote' id='_footnote_" + n + "'>" +
683        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
684        n + "</a>. " + note + "</div>";
685      var id =spans[i].getAttribute("id");
686      if (id != null) refs["#"+id] = n;
687    }
688  }
689  if (n == 0)
690    noteholder.parentNode.removeChild(noteholder);
691  else {
692    // Process footnoterefs.
693    for (i=0; i<spans.length; i++) {
694      if (spans[i].className == "footnoteref") {
695        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
696        href = href.match(/#.*/)[0];  // Because IE return full URL.
697        n = refs[href];
698        spans[i].innerHTML =
699          "[<a href='#_footnote_" + n +
700          "' title='View footnote' class='footnote'>" + n + "</a>]";
701      }
702    }
703  }
704},
705
706install: function(toclevels) {
707  var timerId;
708
709  function reinstall() {
710    asciidoc.footnotes();
711    if (toclevels) {
712      asciidoc.toc(toclevels);
713    }
714  }
715
716  function reinstallAndRemoveTimer() {
717    clearInterval(timerId);
718    reinstall();
719  }
720
721  timerId = setInterval(reinstall, 500);
722  if (document.addEventListener)
723    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
724  else
725    window.onload = reinstallAndRemoveTimer;
726}
727
728}
729asciidoc.install(2);
730/*]]>*/
731</script>
732</head>
733<body class="book">
734<div id="header">
735<h1>Vulkan on Android Implementor&#8217;s Guide</h1>
736<span id="revnumber">version 5</span>
737<div id="toc">
738  <div id="toctitle">Table of Contents</div>
739  <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
740</div>
741</div>
742<div id="content">
743<div id="preamble">
744<div class="sectionbody">
745<div class="paragraph"><p>This document is intended for GPU IHVs writing Vulkan drivers for Android, and OEMs integrating them for specific devices. It describes how a Vulkan driver interacts with the system, how GPU-specific tools should be installed, and Android-specific requirements.</p></div>
746</div>
747</div>
748<div class="sect1">
749<h2 id="_architecture">1. Architecture</h2>
750<div class="sectionbody">
751<div class="paragraph"><p>The primary interface between Vulkan applications and a device&#8217;s Vulkan driver is the loader, which is part of AOSP and installed at <span class="monospaced">/system/lib[64]/libvulkan.so</span>. The loader provides the core Vulkan API entry points, as well as entry points of a few extensions that are required on Android and always present. In particular, the window system integration (WSI) extensions are exported by the loader and primarily implemented in it rather than the driver. The loader also supports enumerating and loading layers which can expose additional extensions and/or intercept core API calls on their way to the driver.</p></div>
752<div class="paragraph"><p>The NDK will include a stub <span class="monospaced">libvulkan.so</span> exporting the same symbols as the loader. Calling the Vulkan functions exported from <span class="monospaced">libvulkan.so</span> will enter trampoline functions in the loader which will dispatch to the appropriate layer or driver based on their first argument. The <span class="monospaced">vkGet*ProcAddr</span> calls will return the function pointers that the trampolines would dispatch to, so calling through these function pointers rather than the exported symbols will be slightly more efficient since it skips the trampoline and dispatch.</p></div>
753<div class="sect2">
754<h3 id="_driver_enumeration_and_loading">1.1. Driver Enumeration and Loading</h3>
755<div class="paragraph"><p>Android expects the GPUs available to the system to be known when the system image is built, so its driver enumeration process isn&#8217;t as elaborate as on other platforms. The loader will use the existing HAL mechanism for discovering and loading the driver. As of this writing, the preferred paths for 32-bit and 64-bit Vulkan drivers are:</p></div>
756<div class="literalblock">
757<div class="content monospaced">
758<pre>/vendor/lib/hw/vulkan.&lt;ro.product.platform&gt;.so
759/vendor/lib64/hw/vulkan.&lt;ro.product.platform&gt;.so</pre>
760</div></div>
761<div class="paragraph"><p>where <span class="monospaced">&lt;ro.product.platform&gt;</span> is replaced by the value of the system property of that name. See <a href="https://android.googlesource.com/platform/hardware/libhardware/+/master/hardware.c">libhardware/hardware.c</a> for details and supported alternative locations.</p></div>
762<div class="paragraph"><p>The Vulkan <span class="monospaced">hw_module_t</span> derivative is currently trivial. If support for multiple drivers is ever added, the HAL module will export a list of strings that can be passed to the module <span class="monospaced">open</span> call. For the time being, only one driver is supported, and the constant string <span class="monospaced">HWVULKAN_DEVICE_0</span> is passed to <span class="monospaced">open</span>.</p></div>
763<div class="paragraph"><p>The Vulkan <span class="monospaced">hw_device_t</span> derivative corresponds to a single driver, though that driver can support multiple Vulkan physical devices. The <span class="monospaced">hw_device_t</span> structure contains a function pointer for the <span class="monospaced">vkGetInstanceProcAddr</span> function. The loader finds all other driver Vulkan functions by calling that <span class="monospaced">vkGetInstanceProcAddr</span> function.</p></div>
764</div>
765<div class="sect2">
766<h3 id="_layer_discovery_and_loading">1.2. Layer Discovery and Loading</h3>
767<div class="paragraph"><p>Android&#8217;s security model and policies differ significantly from other platforms. In particular, Android does not allow loading external code into a non-debuggable process on production (non-rooted) devices, nor does it allow external code to inspect or control the process&#8217;s memory/state/etc. This includes a prohibition on saving core dumps, API traces, etc. to disk for later inspection. So only layers delivered as part of the application will be enabled on production devices, and drivers must also not provide functionality that violates these policies.</p></div>
768<div class="paragraph"><p>There are three major use cases for layers:</p></div>
769<div class="olist arabic"><ol class="arabic">
770<li>
771<p>
772Development-time layers: validation layers, shims for tracing/profiling/debugging tools, etc. These shouldn&#8217;t be installed on the system image of production devices: they would be a waste of space for most users, and they should be updateable without requiring a system update. A developer wishing to use one of these during development has the ability to modify their application package (e.g. adding a file to their native libraries directory). IHV and OEM engineers who are trying to diagnose failures in shipping, unmodifiable apps are assumed to have access to non-production (rooted) builds of the system image.
773</p>
774</li>
775<li>
776<p>
777Utility layers, such as a layer that implements a heap for device memory. These layers will almost always expose extensions. Developers choose which layers, and which versions of those layers, to use in their application; different applications that use the same layer may still use different versions. Developers will choose which of these layers to ship in their application package.
778</p>
779</li>
780<li>
781<p>
782Injected layers, like framerate, social network, or game launcher overlays, which are provided by the user or some other application without the application&#8217;s knowledge or consent. These violate Android&#8217;s security policies and will not be supported.
783</p>
784</li>
785</ol></div>
786<div class="paragraph"><p>In the normal state the loader will only search in the application&#8217;s normal library search path (as defined by the system ClassLoader) for layers. It will attempt to load any shared library named <span class="monospaced">libVkLayer_*.so</span> as a layer library. Android does not use manifests to describe layers: because layers must have been deliberately included in the application by the developer, the motivation for manifests on other platforms don&#8217;t apply.</p></div>
787<div class="paragraph"><p>On debuggable devices (<span class="monospaced">ro.debuggable</span> property exists and is non-zero, generally rooted or engineering builds) the loader will also search the directory <span class="monospaced">/data/local/debug/vulkan</span> and attempt to load layer libraries it finds there. This directory doesn&#8217;t exist by default. On Android N and later, because this location is writable by adb, SELinux policies prevent mapping code located here as executable. So to use layers from here, SELinux enforcement must be disabled: <span class="monospaced">adb shell setenforce 0</span>. This mechanism is not intended for application developers, only for IHV and OEM engineers working on test devices that don&#8217;t have private or sensitive data.</p></div>
788<div class="paragraph"><p>Our goal is to allow layers to be ported with only build-environment changes between Android and other platforms. For this to work, layers must properly implement things like <span class="monospaced">vkGetInstanceLayerProperties</span> and <span class="monospaced">vkGetInstanceExtensionProperties</span>, even though the LunarG loader doesn&#8217;t use them (it gets the information from manifests instead).</p></div>
789</div>
790</div>
791</div>
792<div class="sect1">
793<h2 id="_window_system_integration">2. Window System Integration</h2>
794<div class="sectionbody">
795<div class="paragraph"><p>The <span class="monospaced">vk_wsi_swapchin</span> and <span class="monospaced">vk_wsi_device_swapchain</span> extensions are primarily be implemented by the platform and live in <span class="monospaced">libvulkan.so</span>. The <span class="monospaced">VkSwapchain</span> object and all interaction with <span class="monospaced">ANativeWindow</span> will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver&#8217;s <span class="monospaced">vkGetDeviceProcAddr</span> functions, after passing through any enabled layers.</p></div>
796<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling</p></div>
797<div class="listingblock">
798<div class="content"><!-- Generator: GNU source-highlight 3.1.8
799by Lorenzo Bettini
800http://www.lorenzobettini.it
801http://www.gnu.org/software/src-highlite -->
802<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsageANDROID</span></span><span style="color: #990000">(</span>
803    <span style="color: #008080">VkDevice</span>            device<span style="color: #990000">,</span>
804    <span style="color: #008080">VkFormat</span>            format<span style="color: #990000">,</span>
805    <span style="color: #008080">VkImageUsageFlags</span>   imageUsage<span style="color: #990000">,</span>
806    <span style="color: #009900">int</span><span style="color: #990000">*</span>                grallocUsage
807<span style="color: #990000">);</span></tt></pre></div></div>
808<div class="paragraph"><p>The <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span> parameters are taken from the <span class="monospaced">VkSwapchainCreateInfoKHR</span> structure. The driver should fill <span class="monospaced">*grallocUsage</span> with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.</p></div>
809<div class="paragraph"><p><span class="monospaced">VkNativeBufferANDROID</span> is a <span class="monospaced">vkCreateImage</span> extension structure for creating an image backed by a gralloc buffer. This structure is provided to <span class="monospaced">vkCreateImage</span> in the <span class="monospaced">VkImageCreateInfo</span> structure chain. Calls to <span class="monospaced">vkCreateImage</span> with this structure will happen during the first call to <span class="monospaced">vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)</span>. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a <span class="monospaced">VkImage</span> for each one.</p></div>
810<div class="listingblock">
811<div class="content"><!-- Generator: GNU source-highlight 3.1.8
812by Lorenzo Bettini
813http://www.lorenzobettini.it
814http://www.gnu.org/software/src-highlite -->
815<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #FF0000">{</span>
816    <span style="color: #008080">VkStructureType</span>             sType<span style="color: #990000">;</span> <span style="font-style: italic"><span style="color: #9A1900">// must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID</span></span>
817    <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #009900">void</span><span style="color: #990000">*</span>                 pNext<span style="color: #990000">;</span>
818
819    <span style="font-style: italic"><span style="color: #9A1900">// Buffer handle and stride returned from gralloc alloc()</span></span>
820    <span style="color: #008080">buffer_handle_t</span>             handle<span style="color: #990000">;</span>
821    <span style="color: #009900">int</span>                         stride<span style="color: #990000">;</span>
822
823    <span style="font-style: italic"><span style="color: #9A1900">// Gralloc format and usage requested when the buffer was allocated.</span></span>
824    <span style="color: #009900">int</span>                         format<span style="color: #990000">;</span>
825    <span style="color: #009900">int</span>                         usage<span style="color: #990000">;</span>
826<span style="color: #FF0000">}</span> VkNativeBufferANDROID<span style="color: #990000">;</span></tt></pre></div></div>
827<div class="paragraph"><p>When creating a gralloc-backed image, the <span class="monospaced">VkImageCreateInfo</span> will have:</p></div>
828<div class="listingblock">
829<div class="content monospaced">
830<pre>  .imageType           = VK_IMAGE_TYPE_2D
831  .format              = a VkFormat matching the format requested for the gralloc buffer
832  .extent              = the 2D dimensions requested for the gralloc buffer
833  .mipLevels           = 1
834  .arraySize           = 1
835  .samples             = 1
836  .tiling              = VK_IMAGE_TILING_OPTIMAL
837  .usage               = VkSwapChainCreateInfoWSI::imageUsageFlags
838  .flags               = 0
839  .sharingMode         = VkSwapChainCreateInfoWSI::sharingMode
840  .queueFamilyCount    = VkSwapChainCreateInfoWSI::queueFamilyCount
841  .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices</pre>
842</div></div>
843<div class="paragraph"><p><span class="monospaced">vkAcquireImageANDROID</span> acquires ownership of a swapchain image and imports an
844externally-signalled native fence into both an existing VkSemaphore object
845and an existing VkFence object:</p></div>
846<div class="listingblock">
847<div class="content"><!-- Generator: GNU source-highlight 3.1.8
848by Lorenzo Bettini
849http://www.lorenzobettini.it
850http://www.gnu.org/software/src-highlite -->
851<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkAcquireImageANDROID</span></span><span style="color: #990000">(</span>
852    <span style="color: #008080">VkDevice</span>            device<span style="color: #990000">,</span>
853    <span style="color: #008080">VkImage</span>             image<span style="color: #990000">,</span>
854    <span style="color: #009900">int</span>                 nativeFenceFd<span style="color: #990000">,</span>
855    <span style="color: #008080">VkSemaphore</span>         semaphore<span style="color: #990000">,</span>
856    VkFence             fence
857<span style="color: #990000">);</span></tt></pre></div></div>
858<div class="paragraph"><p>This function is called during <span class="monospaced">vkAcquireNextImageWSI</span> to import a native
859fence into the <span class="monospaced">VkSemaphore</span> and <span class="monospaced">VkFence</span> objects provided by the
860application. Both semaphore and fence objects are optional in this call. The
861driver may also use this opportunity to recognize and handle any external
862changes to the gralloc buffer state; many drivers won&#8217;t need to do anything
863here. This call puts the <span class="monospaced">VkSemaphore</span> and <span class="monospaced">VkFence</span> into the same "pending"
864state as <span class="monospaced">vkQueueSignalSemaphore</span> and <span class="monospaced">vkQueueSubmit</span> respectively, so queues
865can wait on the semaphore and the application can wait on the fence. Both
866objects become signalled when the underlying native fence signals; if the
867native fence has already signalled, then the semaphore will be in the signalled
868state when this function returns. The driver takes ownership of the fence fd
869and is responsible for closing it when no longer needed. It must do so even if
870neither a semaphore or fence object is provided, or even if
871<span class="monospaced">vkAcquireImageANDROID</span> fails and returns an error. If <span class="monospaced">fenceFd</span> is -1, it
872is as if the native fence was already signalled.</p></div>
873<div class="paragraph"><p><span class="monospaced">vkQueueSignalReleaseImageANDROID</span> prepares a swapchain image for external use, and creates a native fence and schedules it to be signalled when prior work on the queue has completed.</p></div>
874<div class="listingblock">
875<div class="content"><!-- Generator: GNU source-highlight 3.1.8
876by Lorenzo Bettini
877http://www.lorenzobettini.it
878http://www.gnu.org/software/src-highlite -->
879<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkQueueSignalReleaseImageANDROID</span></span><span style="color: #990000">(</span>
880    <span style="color: #008080">VkQueue</span>             queue<span style="color: #990000">,</span>
881    <span style="color: #008080">uint32_t</span>            waitSemaphoreCount<span style="color: #990000">,</span>
882    <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> VkSemaphore<span style="color: #990000">*</span>  pWaitSemaphores<span style="color: #990000">,</span>
883    <span style="color: #008080">VkImage</span>             image<span style="color: #990000">,</span>
884    <span style="color: #009900">int</span><span style="color: #990000">*</span>                pNativeFenceFd
885<span style="color: #990000">);</span></tt></pre></div></div>
886<div class="paragraph"><p>This will be called during <span class="monospaced">vkQueuePresentWSI</span> on the provided queue. Effects are similar to <span class="monospaced">vkQueueSignalSemaphore</span>, except with a native fence instead of a semaphore. The native fence must: not signal until the <span class="monospaced">waitSemaphoreCount</span> semaphores in <span class="monospaced">pWaitSemaphores</span> have signaled. Unlike <span class="monospaced">vkQueueSignalSemaphore</span>, however, this call creates and returns the synchronization object that will be signalled rather than having it provided as input. If the queue is already idle when this function is called, it is allowed but not required to set <span class="monospaced">*pNativeFenceFd</span> to -1. The file descriptor returned in <span class="monospaced">*pNativeFenceFd</span> is owned and will be closed by the caller. Many drivers will be able to ignore the <span class="monospaced">image</span> parameter, but some may need to prepare CPU-side data structures associated with a gralloc buffer for use by external image consumers. Preparing buffer contents for use by external consumers should have been done asynchronously as part of transitioning the image to <span class="monospaced">VK_IMAGE_LAYOUT_PRESENT_SRC_KHR</span>.</p></div>
887</div>
888</div>
889<div class="sect1">
890<h2 id="_history">3. History</h2>
891<div class="sectionbody">
892<div class="olist arabic"><ol class="arabic">
893<li>
894<p>
895<strong>2015-07-08</strong> Initial version
896</p>
897</li>
898<li>
899<p>
900<strong>2015-08-16</strong>
901</p>
902<div class="ulist"><ul>
903<li>
904<p>
905Renamed to Implementor&#8217;s Guide
906</p>
907</li>
908<li>
909<p>
910Wording and formatting changes
911</p>
912</li>
913<li>
914<p>
915Updated based on resolution of Khronos bug 14265
916</p>
917</li>
918<li>
919<p>
920Deferred support for multiple drivers
921</p>
922</li>
923</ul></div>
924</li>
925<li>
926<p>
927<strong>2015-11-04</strong>
928</p>
929<div class="ulist"><ul>
930<li>
931<p>
932Added vkGetSwapchainGrallocUsageANDROID
933</p>
934</li>
935<li>
936<p>
937Replaced vkImportNativeFenceANDROID and vkQueueSignalNativeFenceANDROID
938     with vkAcquireImageANDROID and vkQueueSignalReleaseImageANDROID, to allow
939     drivers to known the ownership state of swapchain images.
940</p>
941</li>
942</ul></div>
943</li>
944<li>
945<p>
946<strong>2015-12-03</strong>
947</p>
948<div class="ulist"><ul>
949<li>
950<p>
951Added a VkFence parameter to vkAcquireImageANDROID corresponding to the
952     parameter added to vkAcquireNextImageKHR.
953</p>
954</li>
955</ul></div>
956</li>
957<li>
958<p>
959<strong>2016-01-08</strong>
960</p>
961<div class="ulist"><ul>
962<li>
963<p>
964Added waitSemaphoreCount and pWaitSemaphores parameters to vkQueueSignalReleaseImageANDROID.
965</p>
966</li>
967</ul></div>
968</li>
969<li>
970<p>
971<strong>2016-06-17</strong>
972</p>
973<div class="ulist"><ul>
974<li>
975<p>
976Updates to reflect final behavior, closed some TBDs now that they&#8217;ve BDed.
977</p>
978</li>
979</ul></div>
980</li>
981</ol></div>
982</div>
983</div>
984</div>
985<div id="footnotes"><hr></div>
986<div id="footer">
987<div id="footer-text">
988Version 5<br>
989Last updated 2016-06-17 13:54:25 PDT
990</div>
991</div>
992</body>
993</html>
994