blob: 8c2aabb7174fde7d3003a2cb7694cd5621a6df97 [file] [log] [blame]
Jesse Hallbbd4c102015-08-15 17:56:53 -07001<!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">
Jesse Hall83321be2015-08-16 23:36:28 -07006<title>Vulkan on Android Implementor&#8217;s Guide</title>
Jesse Hallbbd4c102015-08-15 17:56:53 -07007<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">
Jesse Hall83321be2015-08-16 23:36:28 -0700735<h1>Vulkan on Android Implementor&#8217;s Guide</h1>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700736<span id="revnumber">version 1</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">
Jesse Hall83321be2015-08-16 23:36:28 -0700745<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>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700746<div class="paragraph"><p>This is still a fairly rough draft; details will be filled in over time.</p></div>
747</div>
748</div>
749<div class="sect1">
Jesse Hall83321be2015-08-16 23:36:28 -0700750<h2 id="_architecture">1. Architecture</h2>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700751<div class="sectionbody">
Jesse Hall83321be2015-08-16 23:36:28 -0700752<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>
753<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>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700754<div class="sect2">
755<h3 id="_driver_enumeration_and_loading">1.1. Driver Enumeration and Loading</h3>
756<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 other platforms. The loader will use the existing HAL mechanism (see <a href="https://android.googlesource.com/platform/hardware/libhardware/+/lollipop-mr1-release/include/hardware/hardware.h">hardware.h</a>) for discovering and loading the driver. As of this writing, the preferred paths for 32-bit and 64-bit Vulkan drivers are:</p></div>
757<div class="literalblock">
758<div class="content monospaced">
759<pre>/vendor/lib/hw/vulkan.&lt;ro.product.platform&gt;.so
760/vendor/lib64/hw/vulkan.&lt;ro.product.platform&gt;.so</pre>
761</div></div>
762<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/+/lollipop-mr1-release/hardware.c">libhardware/hardware.c</a> for details and supported alternative locations.</p></div>
Jesse Hall83321be2015-08-16 23:36:28 -0700763<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>
764<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 physical devices. The <span class="monospaced">hw_device_t</span> structure will be extended to export <span class="monospaced">vkGetGlobalExtensionProperties</span>, <span class="monospaced">vkCreateInstance</span>, and <span class="monospaced">vkGetInstanceProcAddr</span> functions. The loader will find all other <span class="monospaced">VkInstance</span>, <span class="monospaced">VkPhysicalDevice</span>, and <span class="monospaced">vkGetDeviceProcAddr</span> functions by calling <span class="monospaced">vkGetInstanceProcAddr</span>.</p></div>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700765</div>
766<div class="sect2">
767<h3 id="_layer_discovery_and_loading">1.2. Layer Discovery and Loading</h3>
Jesse Hall83321be2015-08-16 23:36:28 -0700768<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>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700769<div class="paragraph"><p>There are three major use cases for layers:</p></div>
770<div class="olist arabic"><ol class="arabic">
771<li>
772<p>
Jesse Hall83321be2015-08-16 23:36:28 -0700773Development-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.
Jesse Hallbbd4c102015-08-15 17:56:53 -0700774</p>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700775</li>
776<li>
777<p>
Jesse Hall83321be2015-08-16 23:36:28 -0700778Utility 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.
Jesse Hallbbd4c102015-08-15 17:56:53 -0700779</p>
780</li>
781<li>
782<p>
783Injected 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.
784</p>
785</li>
786</ol></div>
Jesse Hall83321be2015-08-16 23:36:28 -0700787<div class="paragraph"><p>In the normal state the loader will only search in the application&#8217;s native library directory for layers; details are TBD but it will probably just try to load any library with a name matching a particular pattern(e.g. <span class="monospaced">libvklayer_foo.so</span>). It will probably not need a separate manifest file; the developer deliberately included these layers, so the reasons to avoid loading libraries before enabling them don&#8217;t apply.</p></div>
788<div class="paragraph"><p>On debuggable devices (<span class="monospaced">ro.debuggable</span> property exists and is non-zero, generally rooted or engineering builds) or debuggable processes (<span class="monospaced">prctl(PR_GET_DUMPABLE)==1</span>, based on the application&#8217;s manifest), the loader may also search an adb-writeable location on /data for layers. It&#8217;s not clear whether this is useful; in all the cases it could be used, the layer could be just as easily be put in the application&#8217;s native library directory.</p></div>
789<div class="paragraph"><p>Finally, the loader may include a built-in validation layer that it will enable based on settings in the Developer Options menu, which would send validation errors or warnings to the system log. Drivers may be able to emit additional hardware-specific errors/warnings through this mechanism. This layer would not be enumerated through the API. This is intended to allow cooperative end-users to collect extra information about failures from unmodified applications on unmodified devices to aid triage/diagnosis of difficult-to-reproduce problems. The functionality would be intentionally limited to minimize security and privacy risk.</p></div>
790<div class="paragraph"><p>Our goal is to allow layers to be ported with only build-environment changes between Android and other platforms. This means the interface between layers and the loader must match the interface used by the LunarG loader. Currently, the LunarG interface has a few deficiencies and is largely unspecified. We intend to work with LunarG to correct as many deficiencies as we can and to specify the interface in detail so that layers can be implemented without referring to the loader source code.</p></div>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700791</div>
792</div>
793</div>
794<div class="sect1">
795<h2 id="_window_system_integration">2. Window System Integration</h2>
796<div class="sectionbody">
Jesse Hall83321be2015-08-16 23:36:28 -0700797<div class="paragraph"><p>The <span class="monospaced">vk_wsi_swapchin</span> and <span class="monospaced">vk_wsi_device_swapchain</span> extensions will 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>
798<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>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700799<div class="listingblock">
800<div class="content"><!-- Generator: GNU source-highlight 3.1.8
801by Lorenzo Bettini
802http://www.lorenzobettini.it
803http://www.gnu.org/software/src-highlite -->
Jesse Hall83321be2015-08-16 23:36:28 -0700804<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>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700805 <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>
806 <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>
807
808 <span style="font-style: italic"><span style="color: #9A1900">// Buffer handle and stride returned from gralloc alloc()</span></span>
809 <span style="color: #008080">buffer_handle_t</span> handle<span style="color: #990000">;</span>
810 <span style="color: #009900">int</span> stride<span style="color: #990000">;</span>
811
812 <span style="font-style: italic"><span style="color: #9A1900">// Gralloc format and usage requested when the buffer was allocated.</span></span>
813 <span style="color: #009900">int</span> format<span style="color: #990000">;</span>
814 <span style="color: #009900">int</span> usage<span style="color: #990000">;</span>
815<span style="color: #FF0000">}</span> VkNativeBufferANDROID<span style="color: #990000">;</span></tt></pre></div></div>
Jesse Hall83321be2015-08-16 23:36:28 -0700816<div class="paragraph"><p>TBD: During swapchain re-creation (using <span class="monospaced">oldSwapChain</span>), we may have to defer allocation of new gralloc buffers until old buffers have been released. If so, the <span class="monospaced">vkCreateImage</span> calls will be deferred until the first <span class="monospaced">vkAcquireNextImageWSI</span> that would return the new image.</p></div>
817<div class="paragraph"><p>When creating a gralloc-backed image, the <span class="monospaced">VkImageCreateInfo</span> will have:</p></div>
818<div class="listingblock">
819<div class="content monospaced">
820<pre> .imageType = VK_IMAGE_TYPE_2D
821 .format = a VkFormat matching the format requested for the gralloc buffer
822 .extent = the 2D dimensions requested for the gralloc buffer
823 .mipLevels = 1
824 .arraySize = 1
825 .samples = 1
826 .tiling = VK_IMAGE_TILING_OPTIMAL
827 .usage = VkSwapChainCreateInfoWSI::imageUsageFlags
828 .flags = 0
829 .sharingMode = VkSwapChainCreateInfoWSI::sharingMode
830 .queueFamilyCount = VkSwapChainCreateInfoWSI::queueFamilyCount
831 .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices</pre>
832</div></div>
833<div class="paragraph"><p><span class="monospaced">vkImportNativeFenceANDROID</span> imports an externally-signalled native fence into an existing <span class="monospaced">VkSemaphore</span> object:</p></div>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700834<div class="listingblock">
835<div class="content"><!-- Generator: GNU source-highlight 3.1.8
836by Lorenzo Bettini
837http://www.lorenzobettini.it
838http://www.gnu.org/software/src-highlite -->
Jesse Hall83321be2015-08-16 23:36:28 -0700839<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkImportNativeFenceANDROID</span></span><span style="color: #990000">(</span>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700840 <span style="color: #008080">VkDevice</span> device<span style="color: #990000">,</span>
841 <span style="color: #008080">VkSemaphore</span> semaphore<span style="color: #990000">,</span>
842 <span style="color: #009900">int</span> nativeFenceFd
843<span style="color: #990000">);</span></tt></pre></div></div>
Jesse Hall83321be2015-08-16 23:36:28 -0700844<div class="paragraph"><p>This function is called during <span class="monospaced">vkAcquireNextImageWSI</span> to import a native fence into the <span class="monospaced">VkSemaphore</span> object provided by the application. This call puts the <span class="monospaced">VkSemaphore</span> into the same "pending" state as <span class="monospaced">vkQueueSignalSemaphore</span>, so queues can wait on the semaphore. The <span class="monospaced">VkSemaphore</span> signals when the underlying native fence signals; if the fence has already signalled, then the semaphore
845will be in the signalled state when this function returns. The driver takes ownership of the fence fd and is responsible for closing it when the <span class="monospaced">VkSemaphore</span> is destroyed, when a different native fence is imported, or any other condition that replaces the <span class="monospaced">VkSemaphore</span>'s underlying synchronization object. If <span class="monospaced">fenceFd</span> is -1, the <span class="monospaced">VkSemaphore</span> will be considered signalled immediately, but it can still be passed to <span class="monospaced">vkQueueWaitSemaphore</span>.</p></div>
846<div class="paragraph"><p><span class="monospaced">vkQueueSignalNativeFenceANDROID</span> creates a native fence and schedules it to be signalled when prior work on the queue has completed.</p></div>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700847<div class="listingblock">
848<div class="content"><!-- Generator: GNU source-highlight 3.1.8
849by Lorenzo Bettini
850http://www.lorenzobettini.it
851http://www.gnu.org/software/src-highlite -->
Jesse Hall83321be2015-08-16 23:36:28 -0700852<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkQueueSignalNativeFenceANDROID</span></span><span style="color: #990000">(</span>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700853 <span style="color: #008080">VkQueue</span> queue<span style="color: #990000">,</span>
854 <span style="color: #009900">int</span><span style="color: #990000">*</span> pNativeFenceFd<span style="color: #990000">);</span></tt></pre></div></div>
Jesse Hall83321be2015-08-16 23:36:28 -0700855<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. 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.</p></div>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700856</div>
857</div>
858<div class="sect1">
859<h2 id="_history">3. History</h2>
860<div class="sectionbody">
861<div class="olist arabic"><ol class="arabic">
862<li>
863<p>
864<strong>2015-07-08</strong> Initial version
865</p>
866</li>
Jesse Hall83321be2015-08-16 23:36:28 -0700867<li>
868<p>
869<strong>2015-08-16</strong>
870</p>
871<div class="ulist"><ul>
872<li>
873<p>
874Renamed to Implementor&#8217;s Guide
875</p>
876</li>
877<li>
878<p>
879Wording and formatting changes
880</p>
881</li>
882<li>
883<p>
884Updated based on resolution of Khronos bug 14265
885</p>
886</li>
887<li>
888<p>
889Deferred support for multiple drivers
890</p>
891</li>
892</ul></div>
893</li>
Jesse Hallbbd4c102015-08-15 17:56:53 -0700894</ol></div>
895</div>
896</div>
897</div>
898<div id="footnotes"><hr></div>
899<div id="footer">
900<div id="footer-text">
901Version 1<br>
Jesse Hall83321be2015-08-16 23:36:28 -0700902Last updated 2015-08-16 23:34:58 PDT
Jesse Hallbbd4c102015-08-15 17:56:53 -0700903</div>
904</div>
905</body>
906</html>