1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006
|
<!-- markdownlint-disable MD041 -->
[![Khronos Vulkan][1]][2]
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
# Driver interface to the Vulkan Loader <!-- omit from toc -->
[![Creative Commons][3]][4]
<!-- Copyright © 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
## Table of Contents <!-- omit from toc -->
- [Overview](#overview)
- [Driver Discovery](#driver-discovery)
- [Overriding the Default Driver Discovery](#overriding-the-default-driver-discovery)
- [Additional Driver Discovery](#additional-driver-discovery)
- [Driver Filtering](#driver-filtering)
- [Driver Select Filtering](#driver-select-filtering)
- [Driver Disable Filtering](#driver-disable-filtering)
- [Exception for Elevated Privileges](#exception-for-elevated-privileges)
- [Examples](#examples)
- [On Windows](#on-windows)
- [On Linux](#on-linux)
- [On macOS](#on-macos)
- [Driver Manifest File Usage](#driver-manifest-file-usage)
- [Driver Discovery on Windows](#driver-discovery-on-windows)
- [Driver Discovery on Linux](#driver-discovery-on-linux)
- [Example Linux Driver Search Path](#example-linux-driver-search-path)
- [Driver Discovery on Fuchsia](#driver-discovery-on-fuchsia)
- [Driver Discovery on macOS](#driver-discovery-on-macos)
- [Example macOS Driver Search Path](#example-macos-driver-search-path)
- [Additional Settings For Driver Debugging](#additional-settings-for-driver-debugging)
- [Driver Discovery using the`VK_LUNARG_direct_driver_loading` extension](#driver-discovery-using-thevk_lunarg_direct_driver_loading-extension)
- [How to use `VK_LUNARG_direct_driver_loading`](#how-to-use-vk_lunarg_direct_driver_loading)
- [Interactions with other driver discovery mechanisms](#interactions-with-other-driver-discovery-mechanisms)
- [Limitations of `VK_LUNARG_direct_driver_loading`](#limitations-of-vk_lunarg_direct_driver_loading)
- [Using Pre-Production ICDs or Software Drivers](#using-pre-production-icds-or-software-drivers)
- [Driver Discovery on Android](#driver-discovery-on-android)
- [Driver Manifest File Format](#driver-manifest-file-format)
- [Driver Manifest File Versions](#driver-manifest-file-versions)
- [Driver Manifest File Version 1.0.0](#driver-manifest-file-version-100)
- [Driver Manifest File Version 1.0.1](#driver-manifest-file-version-101)
- [Driver Vulkan Entry Point Discovery](#driver-vulkan-entry-point-discovery)
- [Driver API Version](#driver-api-version)
- [Mixed Driver Instance Extension Support](#mixed-driver-instance-extension-support)
- [Filtering Out Instance Extension Names](#filtering-out-instance-extension-names)
- [Loader Instance Extension Emulation Support](#loader-instance-extension-emulation-support)
- [Driver Unknown Physical Device Extensions](#driver-unknown-physical-device-extensions)
- [Reason for adding `vk_icdGetPhysicalDeviceProcAddr`](#reason-for-adding-vk_icdgetphysicaldeviceprocaddr)
- [Physical Device Sorting](#physical-device-sorting)
- [Driver Dispatchable Object Creation](#driver-dispatchable-object-creation)
- [Handling KHR Surface Objects in WSI Extensions](#handling-khr-surface-objects-in-wsi-extensions)
- [Loader and Driver Interface Negotiation](#loader-and-driver-interface-negotiation)
- [Windows, Linux and macOS Driver Negotiation](#windows-linux-and-macos-driver-negotiation)
- [Version Negotiation Between the Loader and Drivers](#version-negotiation-between-the-loader-and-drivers)
- [Interfacing With Legacy Drivers or Loaders](#interfacing-with-legacy-drivers-or-loaders)
- [Loader and Driver Interface Version 7 Requirements](#loader-and-driver-interface-version-7-requirements)
- [Loader and Driver Interface Version 6 Requirements](#loader-and-driver-interface-version-6-requirements)
- [Loader and Driver Interface Version 5 Requirements](#loader-and-driver-interface-version-5-requirements)
- [Loader and Driver Interface Version 4 Requirements](#loader-and-driver-interface-version-4-requirements)
- [Loader and Driver Interface Version 3 Requirements](#loader-and-driver-interface-version-3-requirements)
- [Loader and Driver Interface Version 2 Requirements](#loader-and-driver-interface-version-2-requirements)
- [Loader and Driver Interface Version 1 Requirements](#loader-and-driver-interface-version-1-requirements)
- [Loader and Driver Interface Version 0 Requirements](#loader-and-driver-interface-version-0-requirements)
- [Additional Interface Notes:](#additional-interface-notes)
- [Android Driver Negotiation](#android-driver-negotiation)
- [Loader implementation of VK\_KHR\_portability\_enumeration](#loader-implementation-of-vk_khr_portability_enumeration)
- [Loader and Driver Policy](#loader-and-driver-policy)
- [Number Format](#number-format)
- [Android Differences](#android-differences)
- [Requirements of Well-Behaved Drivers](#requirements-of-well-behaved-drivers)
- [Removed Driver Policies](#removed-driver-policies)
- [Requirements of a Well-Behaved Loader](#requirements-of-a-well-behaved-loader)
## Overview
This is the Driver-centric view of working with the Vulkan loader.
For the complete overview of all sections of the loader, please refer to the
[LoaderInterfaceArchitecture.md](LoaderInterfaceArchitecture.md) file.
**NOTE:** While many of the interfaces still use the "icd" sub-string to
identify various behavior associated with drivers, this is purely
historical and should not indicate that the implementing code do so through
the traditional ICD interface.
Granted, the majority of drivers to this date are ICD drivers
targeting specific GPU hardware.
## Driver Discovery
Vulkan allows multiple drivers each with one or more devices
(represented by a Vulkan `VkPhysicalDevice` object) to be used collectively.
The loader is responsible for discovering available Vulkan drivers on
the system.
Given a list of available drivers, the loader can enumerate all the
physical devices available for an application and return this information to the
application.
The process in which the loader discovers the available drivers on a
system is platform-dependent.
Windows, Linux, Android, and macOS Driver Discovery details are listed
below.
### Overriding the Default Driver Discovery
There may be times that a developer wishes to force the loader to use a specific
Driver.
This could be for many reasons including using a beta driver, or forcing the
loader to skip a problematic driver.
In order to support this, the loader can be forced to look at specific
drivers with either the `VK_DRIVER_FILES` or the older `VK_ICD_FILENAMES`
environment variable.
Both these environment variables behave the same, but `VK_ICD_FILENAMES`
should be considered deprecated.
If both `VK_DRIVER_FILES` and `VK_ICD_FILENAMES` environment variables are
present, then the newer `VK_DRIVER_FILES` will be used, and the values in
`VK_ICD_FILENAMES` will be ignored.
The `VK_DRIVER_FILES` environment variable is a list of paths to Driver Manifest
files, containing the full path to the driver JSON Manifest file, and/or paths
to folders containing Driver Manifest files.
This list is colon-separated on Linux and macOS, and semicolon-separated on
Windows.
Typically, `VK_DRIVER_FILES` will only contain a full pathname to one info
file for a single driver.
A separator (colon or semicolon) is only used if more than one driver is needed.
### Additional Driver Discovery
There may be times that a developer wishes to force the loader to use a specific
Driver in addition to the standard drivers (without replacing the standard
search paths.
The `VK_ADD_DRIVER_FILES` environment variable can be used to add a list of
Driver Manifest files, containing the full path to the driver JSON Manifest
file, and/or paths to folders containing Driver Manifest files.
This list is colon-separated on Linux and macOS, and semicolon-separated on
Windows.
It will be added prior to the standard driver search files.
If `VK_DRIVER_FILES` or `VK_ICD_FILENAMES` is present, then
`VK_ADD_DRIVER_FILES` will not be used by the loader and any values will be
ignored.
### Driver Filtering
**NOTE:** This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.
The loader supports filter environment variables which can forcibly select and
disable known drivers.
Known driver manifests are those files that are already found by the loader
taking into account default search paths and other environment variables (like
`VK_ICD_FILENAMES` or `VK_ADD_DRIVER_FILES`).
The filter variables will be compared against the driver's manifest filename.
The filters must also follow the behaviors define in the
[Filter Environment Variable Behaviors](LoaderInterfaceArchitecture.md#filter-environment-variable-behaviors)
section of the [LoaderLayerInterface](LoaderLayerInterface.md) document.
#### Driver Select Filtering
The driver select environment variable `VK_LOADER_DRIVERS_SELECT` is a
comma-delimited list of globs to search for in known drivers.
If a driver is not selected when using the `VK_LOADER_DRIVERS_SELECT` filter,
and loader logging is set to emit either warnings or driver messages, then a
message will show for each driver that has been ignored.
This message will look like the following:
```
[Vulkan Loader] WARNING | DRIVER: Driver "intel_icd.x86_64.json" ignored because not selected by env var 'VK_LOADER_DRIVERS_SELECT'
```
If no drivers are found with a manifest filename that matches any of the
provided globs, then no driver is enabled and may result in failures for
any Vulkan application that is run.
#### Driver Disable Filtering
The driver disable environment variable `VK_LOADER_DRIVERS_DISABLE` is a
comma-delimited list of globs to search for in known drivers.
When a driver is disabled using the `VK_LOADER_DRIVERS_DISABLE` filter, and
loader logging is set to emit either warnings or driver messages, then a message
will show for each driver that has been forcibly disabled.
This message will look like the following:
```
[Vulkan Loader] WARNING | DRIVER: Driver "radeon_icd.x86_64.json" ignored because it was disabled by env var 'VK_LOADER_DRIVERS_DISABLE'
```
If no drivers are found with a manifest filename that matches any of the
provided globs, then no driver is disabled.
### Exception for Elevated Privileges
For security reasons, `VK_ICD_FILENAMES`, `VK_DRIVER_FILES`, and
`VK_ADD_DRIVER_FILES` are all ignored if running the Vulkan application
with elevated privileges.
This is because they may insert new libraries into the executable process that
are not normally found by the loader.
Because of this, these environment variables can only be used for applications
that do not use elevated privileges.
For more information see
[Elevated Privilege Caveats](LoaderInterfaceArchitecture.md#elevated-privilege-caveats)
in the top-level
[LoaderInterfaceArchitecture.md](LoaderInterfaceArchitecture.md) document.
#### Examples
In order to use the setting, simply set it to a properly delimited list of
Driver Manifest files.
In this case, please provide the global path to these files to reduce issues.
For example:
##### On Windows
```
set VK_DRIVER_FILES=\windows\system32\nv-vk64.json
```
This is an example which is using the `VK_DRIVER_FILES` override on Windows to
point to the Nvidia Vulkan Driver's Manifest file.
```
set VK_ADD_DRIVER_FILES=\windows\system32\nv-vk64.json
```
This is an example which is using the `VK_ADD_DRIVER_FILES` on Windows to
point to the Nvidia Vulkan Driver's Manifest file which will be loaded first
before all other drivers.
##### On Linux
```
export VK_DRIVER_FILES=/home/user/dev/mesa/share/vulkan/icd.d/intel_icd.x86_64.json
```
This is an example which is using the `VK_DRIVER_FILES` override on Linux to
point to the Intel Mesa Driver's Manifest file.
```
export VK_ADD_DRIVER_FILES=/home/user/dev/mesa/share/vulkan/icd.d/intel_icd.x86_64.json
```
This is an example which is using the `VK_ADD_DRIVER_FILES` on Linux to
point to the Intel Mesa Driver's Manifest file which will be loaded first
before all other drivers.
##### On macOS
```
export VK_DRIVER_FILES=/home/user/MoltenVK/Package/Latest/MoltenVK/macOS/MoltenVK_icd.json
```
This is an example which is using the `VK_DRIVER_FILES` override on macOS to
point to an installation and build of the MoltenVK GitHub repository that
contains the MoltenVK driver.
See the
[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md#table-of-debug-environment-variables)
in the [LoaderInterfaceArchitecture.md document](LoaderInterfaceArchitecture.md)
for more details
### Driver Manifest File Usage
As with layers, on Windows, Linux and macOS systems, JSON-formatted manifest
files are used to store driver information.
In order to find system-installed drivers, the Vulkan loader will read the JSON
files to identify the names and attributes of each driver.
Notice that Driver Manifest files are much simpler than the corresponding
layer Manifest files.
See the
[Current Driver Manifest File Format](#driver-manifest-file-format)
section for more details.
### Driver Discovery on Windows
In order to find available drivers (including installed ICDs), the
loader scans through registry keys specific to Display Adapters and all Software
Components associated with these adapters for the locations of JSON manifest
files.
These keys are located in device keys created during driver installation and
contain configuration information for base settings, including OpenGL and
Direct3D locations.
The Device Adapter and Software Component key paths will be obtained by first
enumerating DXGI adapters.
Should that fail it will use the PnP Configuration Manager API.
The `000X` key will be a numbered key, where each device is assigned a different
number.
```
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\{Adapter GUID}\000X\VulkanDriverName
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\{SoftwareComponent GUID}\000X\VulkanDriverName
```
In addition, on 64-bit systems there may be another set of registry values,
listed below.
These values record the locations of 32-bit layers on 64-bit operating systems,
in the same way as the Windows-on-Windows functionality.
```
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\{Adapter GUID}\000X\VulkanDriverNameWow
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\{SoftwareComponent GUID}\000X\VulkanDriverNameWow
```
If any of the above values exist and is of type `REG_SZ`, the loader will open
the JSON manifest file specified by the key value.
Each value must be a full absolute path to a JSON manifest file.
The values may also be of type `REG_MULTI_SZ`, in which case the value will be
interpreted as a list of paths to JSON manifest files.
Additionally, the Vulkan loader will scan the values in the following Windows
registry key:
```
HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers
```
For 32-bit applications on 64-bit Windows, the loader scan's the 32-bit
registry location:
```
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\Vulkan\Drivers
```
Every driver in these locations should be given as a DWORD, with value 0, where
the name of the value is the full path to a JSON manifest file.
The Vulkan loader will attempt to open each manifest file to obtain the
information about a driver's shared library (".dll") file.
For example, let us assume the registry contains the following data:
```
[HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\Drivers\]
"C:\vendor a\vk_vendor_a.json"=dword:00000000
"C:\windows\system32\vendor_b_vk.json"=dword:00000001
"C:\windows\system32\vendor_c_icd.json"=dword:00000000
```
In this case, the loader will step through each entry, and check the value.
If the value is 0, then the loader will attempt to load the file.
In this case, the loader will open the first and last listings, but not the
middle.
This is because the value of 1 for vendor_b_vk.json disables the driver.
Additionally, the Vulkan loader will scan the system for well-known Windows
AppX/MSIX packages.
If a package is found, the loader will scan the root directory of this installed
package for JSON manifest files. At this time, the only package that is known is
Microsoft's
[OpenCL™, OpenGL®, and Vulkan® Compatibility Pack](https://apps.microsoft.com/store/detail/9NQPSL29BFFF?hl=en-us&gl=US).
The Vulkan loader will open each enabled manifest file found to obtain the name
or pathname of a driver's shared library (".DLL") file.
Drivers should use the registry locations from the PnP Configuration
Manager wherever practical.
Typically, this is most important for drivers, and the location clearly
ties the driver to a given device.
The `SOFTWARE\Khronos\Vulkan\Drivers` location is the older method for locating
drivers, but is the primary location for software based drivers.
See the
[Driver Manifest File Format](#driver-manifest-file-format)
section for more details.
### Driver Discovery on Linux
On Linux, the Vulkan loader will scan for Driver Manifest files using
environment variables or corresponding fallback values if the corresponding
environment variable is not defined:
<table style="width:100%">
<tr>
<th>Search Order</th>
<th>Directory/Environment Variable</th>
<th>Fallback</th>
<th>Additional Notes</th>
</tr>
<tr>
<td>1</td>
<td>$XDG_CONFIG_HOME</td>
<td>$HOME/.config</td>
<td><b>This path is ignored when running with elevated privileges such as
setuid, setgid, or filesystem capabilities</b>.<br/>
This is done because under these scenarios it is not safe to trust
that the environment variables are non-malicious.<br/>
See <a href="LoaderInterfaceArchitecture.md#elevated-privilege-caveats">
Elevated Privilege Caveats</a> for more information.
</td>
</tr>
<tr>
<td>1</td>
<td>$XDG_CONFIG_DIRS</td>
<td>/etc/xdg</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>SYSCONFDIR</td>
<td>/etc</td>
<td>Compile-time option set to possible location of drivers
installed from non-Linux-distribution-provided packages.
</td>
</tr>
<tr>
<td>3</td>
<td>EXTRASYSCONFDIR</td>
<td>/etc</td>
<td>Compile-time option set to possible location of drivers
installed from non-Linux-distribution-provided packages.
Typically only set if SYSCONFDIR is set to something other than /etc
</td>
</tr>
<tr>
<td>4</td>
<td>$XDG_DATA_HOME</td>
<td>$HOME/.local/share</td>
<td><b>This path is ignored when running with elevated privileges such as
setuid, setgid, or filesystem capabilities</b>.<br/>
This is done because under these scenarios it is not safe to trust
that the environment variables are non-malicious.<br/>
See <a href="LoaderInterfaceArchitecture.md#elevated-privilege-caveats">
Elevated Privilege Caveats</a> for more information.
</td>
</tr>
<tr>
<td>5</td>
<td>$XDG_DATA_DIRS</td>
<td>/usr/local/share/:/usr/share/</td>
<td></td>
</tr>
</table>
The directory lists are concatenated together using the standard platform path
separator (:).
The loader then selects each path, and applies the "/vulkan/icd.d" suffix onto
each and looks in that specific folder for manifest files.
The Vulkan loader will open each manifest file found to obtain the name or
pathname of a driver's shared library (".so") file.
**NOTE** While the order of folders searched for manifest files is well
defined, the order contents are read by the loader in each directory is
[random due to the behavior of readdir](https://www.ibm.com/support/pages/order-directory-contents-returned-calls-readdir).
See the
[Driver Manifest File Format](#driver-manifest-file-format)
section for more details.
It is also important to note that while `VK_DRIVER_FILES` will point the loader
to finding the manifest files, it does not guarantee the library files mentioned
by the manifest will immediately be found.
Often, the Driver Manifest file will point to the library file using a
relative or absolute path.
When a relative or absolute path is used, the loader can typically find the
library file without querying the operating system.
However, if a library is listed only by name, the loader may not find it,
unless the driver is installed placing the library in an operating system
searchable default location.
If problems occur finding a library file associated with a driver, try updating
the `LD_LIBRARY_PATH` environment variable to point at the location of the
corresponding `.so` file.
#### Example Linux Driver Search Path
For a fictional user "me" the Driver Manifest search path might look
like the following:
```
/home/me/.config/vulkan/icd.d
/etc/xdg/vulkan/icd.d
/usr/local/etc/vulkan/icd.d
/etc/vulkan/icd.d
/home/me/.local/share/vulkan/icd.d
/usr/local/share/vulkan/icd.d
/usr/share/vulkan/icd.d
```
### Driver Discovery on Fuchsia
On Fuchsia, the Vulkan loader will scan for manifest files using environment
variables or corresponding fallback values if the corresponding environment
variable is not defined in the same way as
[Linux](#linux-driver-discovery).
The **only** difference is that Fuchsia does not allow fallback values for
*$XDG_DATA_DIRS* or *$XDG_HOME_DIRS*.
### Driver Discovery on macOS
On macOS, the Vulkan loader will scan for Driver Manifest files using
the application resource folder as well as environment variables or
corresponding fallback values if the corresponding environment variable is not
defined.
The order is similar to the search path on Linux with the exception that
the application's bundle resources are searched first:
`(bundle)/Contents/Resources/`.
System installed drivers will be ignored if drivers are found inside of the app
bundle.
This is because there is not a standard mechanism in which to distinguish drivers
that happen to be duplicates.
For example, MoltenVK is commonly placed inside application bundles.
If there exists a system installed MoltenVK, the loader will load both the app
bundled and the system installed MoltenVK, leading to potential issues or crashes.
Drivers found through environment variables, such as `VK_DRIVER_FILES`, will be
used regardless of whether there are bundled drivers present or not.
#### Example macOS Driver Search Path
For a fictional user "Me" the Driver Manifest search path might look
like the following:
```
<bundle>/Contents/Resources/vulkan/icd.d
/Users/Me/.config/vulkan/icd.d
/etc/xdg/vulkan/icd.d
/usr/local/etc/vulkan/icd.d
/etc/vulkan/icd.d
/Users/Me/.local/share/vulkan/icd.d
/usr/local/share/vulkan/icd.d
/usr/share/vulkan/icd.d
```
#### Additional Settings For Driver Debugging
Sometimes, the driver may encounter issues when loading.
A useful option may be to enable the `LD_BIND_NOW` environment variable
to debug the issue.
This forces every dynamic library's symbols to be fully resolved on load.
If there is a problem with a driver missing symbols on the current system, this
will expose it and cause the Vulkan loader to fail on loading the driver.
It is recommended that `LD_BIND_NOW` along with `VK_LOADER_DEBUG=error,warn`
to expose any issues.
### Driver Discovery using the`VK_LUNARG_direct_driver_loading` extension
The `VK_LUNARG_direct_driver_loading` extension allows for applications to
provide a driver or drivers to the Loader during vkCreateInstance.
This allows drivers to be included with an application without requiring
installation and is capable of being used in any execution environment, such as
a process running with elevated privileges.
When calling `vkEnumeratePhysicalDevices` with the
`VK_LUNARG_direct_driver_loading` extension enabled, the `VkPhysicalDevice`s
from system installed drivers and environment variable specified drivers will
appear before any `VkPhysicalDevice`s that originate from drivers from the
`VkDirectDriverLoadingListLUNARG::pDrivers` list.
#### How to use `VK_LUNARG_direct_driver_loading`
To use this extension, it must first be enabled on the VkInstance.
This requires enabling the `VK_LUNARG_direct_driver_loading` extension through
the `enabledExtensionCount` and `ppEnabledExtensionNames`members of
`VkInstanceCreateInfo`.
```c
const char* extensions[] = {VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME, <other extensions>};
VkInstanceCreateInfo instance_create_info = {};
instance_create_info.enabledExtensionCount = <size of extension list>;
instance_create_info.ppEnabledExtensionNames = extensions;
```
The `VkDirectDriverLoadingInfoLUNARG` structure contains a
`VkDirectDriverLoadingFlagsLUNARG` member (reserved for future use) and a
`PFN_vkGetInstanceProcAddrLUNARG` member which provides the loader with the
function pointer for the driver's `vkGetInstanceProcAddr`.
The `VkDirectDriverLoadingListLUNARG` structure contains a count and pointer
members which provide the size of and pointer to an application provided array of
`VkDirectDriverLoadingInfoLUNARG` structures.
Creating those structures looks like the following
```c
VkDirectDriverLoadingInfoLUNARG direct_loading_info = {};
direct_loading_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG
direct_loading_info.pfnGetInstanceProcAddr = <put the PFN_vkGetInstanceProcAddr of the driver here>
VkDirectDriverLoadingListLUNARG direct_driver_list = {};
direct_driver_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
direct_driver_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG; // or VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG
direct_driver_list.driverCount = 1;
direct_driver_list.pDrivers = &direct_loading_info; // can include multiple drivers here if so desired
```
The `VkDirectDriverLoadingListLUNARG` structure contains the enum
`VkDirectDriverLoadingModeLUNARG`.
There are two modes:
* `VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG` - specifies that the only drivers
to be loaded will come from the `VkDirectDriverLoadingListLUNARG` structure.
* `VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG` - specifies that drivers
from the `VkDirectDriverLoadingModeLUNARG` structure will be used in addition to
any system installed drivers and environment variable specified drivers.
Then, the `VkDirectDriverLoadingListLUNARG` structure *must* be appended to the
`pNext` chain of `VkInstanceCreateInfo`.
```c
instance_create_info.pNext = (const void*)&direct_driver_list;
```
Finally, create the instance like normal.
#### Interactions with other driver discovery mechanisms
If the `VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG` mode is specified in the
`VkDirectDriverLoadingListLUNARG` structure, then no system installed drivers
are loaded.
This applies equally to all platforms.
Additionally, the following environment variables have no effect:
* `VK_DRIVER_FILES`
* `VK_ICD_FILENAMES`
* `VK_ADD_DRIVER_FILES`
* `VK_LOADER_DRIVERS_SELECT`
* `VK_LOADER_DRIVERS_DISABLE`
Exclusive mode will also disable MacOS bundle manifest discovery of drivers.
#### Limitations of `VK_LUNARG_direct_driver_loading`
Because `VkDirectDriverLoadingListLUNARG` is provided to the loader at instance
creation, there is no mechanism for the loader to query the list of instance
extensions that originate from `VkDirectDriverLoadingListLUNARG` drivers during
`vkEnumerateInstanceExtensionProperties`.
Applications can instead manually load the `vkEnumerateInstanceExtensionProperties`
function pointer directly from the drivers the application provides to the loader
using the `pfnGetInstanceProcAddrLUNARG` for each driver.
Then the application can call each driver's
`vkEnumerateInstanceExtensionProperties` and append non-duplicate entriees to the
list from the loader's `vkEnumerateInstanceExtensionProperties` to get the full
list of supported instance extensions.
Alternatively, because the Application is providing drivers, it is reasonable for
the application to already know which instance extensions are available with the
provided drivers, preventing the need to manually query them.
However, there are limitations.
If there are any active implicit layers which intercept
`vkEnumerateInstanceExtensionProperties` to remove unsupported extensions, then
those layers will not be able to remove unsupported extensions from drivers that
are provided by the application.
This is due to `vkEnumerateInstanceExtensionProperties` not having a mechanism
to extend it.
### Using Pre-Production ICDs or Software Drivers
Both software and pre-production ICDs can use an alternative mechanism to
detect their drivers.
Independent Hardware Vendor (IHV) may not want to fully install a pre-production
ICD and so it can't be found in the standard location.
For example, a pre-production ICD may simply be a shared library in the
developer's build tree.
In this case, there should be a way to allow developers to point to such an
ICD without modifying the system-installed ICD(s) on their system.
This need is met with the use of the `VK_DRIVER_FILES` environment variable,
which will override the mechanism used for finding system-installed
drivers.
In other words, only the drivers listed in `VK_DRIVER_FILES` will be
used.
See
[Overriding the Default Driver Discovery](#overriding-the-default-driver-discovery)
for more information on this.
### Driver Discovery on Android
The Android loader lives in the system library folder.
The location cannot be changed.
The loader will load the driver via `hw_get_module` with the ID of "vulkan".
**Due to security policies in Android, none of this can be modified under**
**normal use.**
## Driver Manifest File Format
The following section discusses the details of the Driver Manifest JSON file
format.
The JSON file itself does not have any requirements for naming.
The only requirement is that the extension suffix of the file is ".json".
Here is an example driver JSON Manifest file:
```json
{
"file_format_version": "1.0.1",
"ICD": {
"library_path": "path to driver library",
"api_version": "1.2.205",
"library_arch" : "64",
"is_portability_driver": false
}
}
```
<table style="width:100%">
<tr>
<th>Field Name</th>
<th>Field Value</th>
</tr>
<tr>
<td>"file_format_version"</td>
<td>The JSON format major.minor.patch version number of this file.<br/>
Supported versions are: 1.0.0 and 1.0.1.</td>
</tr>
<tr>
<td>"ICD"</td>
<td>The identifier used to group all driver information together.
<br/>
<b>NOTE:</b> Even though this is labelled <i>ICD</i> it is historical
and just as accurate to use for other drivers.</td>
</tr>
<tr>
<td>"library_path"</td>
<td>The "library_path" specifies either a filename, a relative pathname, or
a full pathname to a driver shared library file. <br />
If "library_path" specifies a relative pathname, it is relative to the
path of the JSON manifest file. <br />
If "library_path" specifies a filename, the library must live in the
system's shared object search path. <br />
There are no rules about the name of the driver's shared library file
other than it should end with the appropriate suffix (".DLL" on
Windows, ".so" on Linux and ".dylib" on macOS).</td>
</tr>
<tr>
<td>"library_arch"</td>
<td>Optional field which specifies the architecture of the binary associated
with "library_path". <br />
Allows the loader to quickly determine if the architecture of the driver
matches that of the running application. <br />
The only valid values are "32" and "64".</td>
</tr>
<tr>
<td>"api_version" </td>
<td>The major.minor.patch version number of the maximum Vulkan API supported
by the driver.
However, just because the driver supports the specific Vulkan API
version, it does not guarantee that the hardware on a user's system can
support that version.
Information on what the underlying physical device can support must be
queried by the user using the <i>vkGetPhysicalDeviceProperties</i> API
call.<br/>
For example: 1.0.33.</td>
</tr>
<tr>
<td>"is_portability_driver" </td>
<td>Defines whether the driver contains any VkPhysicalDevices which
implement the VK_KHR_portability_subset extension.<br/>
</td>
</tr>
</table>
**NOTE:** If the same driver shared library supports multiple, incompatible
versions of text manifest file format versions, it must have separate JSON files
for each (all of which may point to the same shared library).
### Driver Manifest File Versions
The current highest supported Layer Manifest file format supported is 1.0.1.
Information about each version is detailed in the following sub-sections:
#### Driver Manifest File Version 1.0.0
The initial version of the Driver Manifest file specified the basic
format and fields of a layer JSON file.
The fields supported in version 1.0.0 of the file format include:
* "file\_format\_version"
* "ICD"
* "library\_path"
* "api\_version"
#### Driver Manifest File Version 1.0.1
Added the `is_portability_driver` boolean field for drivers to self report that
they contain VkPhysicalDevices which support the VK_KHR_portability_subset
extension. This is an optional field. Omitting the field has the same effect as
setting the field to `false`.
Added the "library\_arch" field to the driver manifest to allow the loader to
quickly determine if the driver matches the architecture of the current running
application. This field is optional.
## Driver Vulkan Entry Point Discovery
The Vulkan symbols exported by a driver must not clash with the loader's
exported Vulkan symbols.
Because of this, all drivers must export the following function that is
used for discovery of driver Vulkan entry-points.
This entry-point is not a part of the Vulkan API itself, only a private
interface between the loader and drivers for version 1 and higher
interfaces.
```cpp
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(
VkInstance instance,
const char* pName);
```
This function has very similar semantics to `vkGetInstanceProcAddr`.
`vk_icdGetInstanceProcAddr` returns valid function pointers for all the
global-level and instance-level Vulkan functions, and also for
`vkGetDeviceProcAddr`.
Global-level functions are those which contain no dispatchable object as the
first parameter, such as `vkCreateInstance` and
`vkEnumerateInstanceExtensionProperties`.
The driver must support querying global-level entry points by calling
`vk_icdGetInstanceProcAddr` with a NULL `VkInstance` parameter.
Instance-level functions are those that have either `VkInstance`, or
`VkPhysicalDevice` as the first parameter dispatchable object.
Both core entry points and any instance extension entry points the
driver supports should be available via `vk_icdGetInstanceProcAddr`.
Future Vulkan instance extensions may define and use new instance-level
dispatchable objects other than `VkInstance` and `VkPhysicalDevice`, in which
case extension entry points using these newly defined dispatchable objects must
be queryable via `vk_icdGetInstanceProcAddr`.
All other Vulkan entry points must either:
* NOT be exported directly from the driver library
* or NOT use the official Vulkan function names if they are exported
This requirement is for driver libraries that include other functionality (such
as OpenGL) and thus could be loaded by the application prior to when the Vulkan
loader library is loaded by the application.
Beware of interposing by dynamic OS library loaders if the official Vulkan
names are used.
On Linux, if official names are used, the driver library must be linked with
`-Bsymbolic`.
## Driver API Version
When an application calls `vkCreateInstance`, it can optionally include a
`VkApplicationInfo` struct, which includes an `apiVersion` field.
A Vulkan 1.0 driver was required to return `VK_ERROR_INCOMPATIBLE_DRIVER` if it
did not support the API version that the user passed.
Beginning with Vulkan 1.1, drivers are not allowed to return this error
for any value of `apiVersion`.
This creates a problem when working with multiple drivers, where one is
a 1.0 driver and another is newer.
A loader that is newer than 1.0 will always give the version it supports when
the application calls `vkEnumerateInstanceVersion`, regardless of the API
version supported by the drivers on the system.
This means that when the application calls `vkCreateInstance`, the loader will
be forced to pass a copy of the `VkApplicationInfo` struct where `apiVersion` is
1.0 to any 1.0 drivers in order to prevent an error.
To determine if this must be done, the loader will perform the following steps:
1. Check the driver's JSON manifest file for the "api_version" field.
2. If the JSON version is greater than or equal to 1.1, Load the driver's
dynamic library
3. Call the driver's `vkGetInstanceProcAddr` command to get a pointer to
`vkEnumerateInstanceVersion`
4. If the pointer to `vkEnumerateInstanceVersion` is not `NULL`, it will be
called to get the driver's supported API version
The driver will be treated as a 1.0 driver if any of the following conditions
are met:
- The JSON manifest's "api_version" field is less that version 1.1
- The function pointer to `vkEnumerateInstanceVersion` is `NULL`
- The version returned by `vkEnumerateInstanceVersion` is less than 1.1
- `vkEnumerateInstanceVersion` returns anything other than `VK_SUCCESS`
If the driver only supports Vulkan 1.0, the loader will ensure that any
`VkApplicationInfo` struct that is passed to the driver will have an
`apiVersion` field set to Vulkan 1.0.
Otherwise, the loader will pass the struct to the driver without any
changes.
## Mixed Driver Instance Extension Support
On a system with more than one driver, a special case can arise.
Some drivers may expose an instance extension that the loader is already
aware of.
Other drivers on that same system may not support the same instance
extension.
In that scenario, the loader has some additional responsibilities:
### Filtering Out Instance Extension Names
During a call to `vkCreateInstance`, the list of requested instance extensions
is passed down to each driver.
Since the driver may not support one or more of these instance extensions, the
loader will filter out any instance extensions that are not supported by the
driver.
This is done per driver since different drivers may support different instance
extensions.
### Loader Instance Extension Emulation Support
In the same scenario, the loader must emulate the instance extension
entry-points, to the best of its ability, for each driver that does not support
an instance extension directly.
This must work correctly when combined with calling into the other
drivers which do support the extension natively.
In this fashion, the application will be unaware of what drivers are
missing support for this extension.
## Driver Unknown Physical Device Extensions
Drivers that implement entrypoints which take a `VkPhysicalDevice` as the first
parameter *should* support `vk_icdGetPhysicalDeviceProcAddr`.
This function is added to the Loader and Driver Driver Interface Version 4,
allowing the loader to distinguish between entrypoints which take `VkDevice`
and `VkPhysicalDevice` as the first parameter.
This allows the loader to properly support entrypoints that are unknown to it
gracefully.
This entry point is not a part of the Vulkan API itself, only a private
interface between the loader and drivers.
Note: Loader and Driver Interface Version 7 makes exporting
`vk_icdGetPhysicalDeviceProcAddr` optional.
Instead, drivers *must* expose it through `vk_icdGetInstanceProcAddr`.
```cpp
PFN_vkVoidFunction
vk_icdGetPhysicalDeviceProcAddr(
VkInstance instance,
const char* pName);
```
This function behaves similar to `vkGetInstanceProcAddr` and
`vkGetDeviceProcAddr` except it should only return values for physical device
extension entry points.
In this way, it compares "pName" to every physical device function supported in
the driver.
Implementations of the function should have the following behavior:
* If `pName` is the name of a Vulkan API entrypoint that takes a
`VkPhysicalDevice` as its primary dispatch handle, and the driver supports the
entrypoint, then the driver **must** return the valid function pointer to the
driver's implementation of that entrypoint.
* If `pName` is the name of a Vulkan API entrypoint that takes something other
than a `VkPhysicalDevice` as its primary dispatch handle, then the driver
**must** return `NULL`.
* If the driver is unaware of any entrypoint with the name `pName`, it **must**
return `NULL`.
If a driver intends to support functions that take VkPhysicalDevice as the
dispatchable parameter, then the driver should support
`vk_icdGetPhysicalDeviceProcAddr`. This is because if these functions aren't
known to the loader, such as those from unreleased extensions or because
the loader is an older build thus doesn't know about them _yet_, the loader
won't be able to distinguish whether this is a device or physical device
function.
If a driver does implement this support, it must export the function from the
driver library using the name `vk_icdGetPhysicalDeviceProcAddr` so that the
symbol can be located through the platform's dynamic linking utilities, or if
the driver supports Loader and Driver Interface Version 7, exposed through
`vk_icdGetInstanceProcAddr` instead.
The behavior of the loader's `vkGetInstanceProcAddr` with support for the
`vk_icdGetPhysicalDeviceProcAddr` function is as follows:
1. Check if core function:
- If it is, return the function pointer
2. Check if known instance or device extension function:
- If it is, return the function pointer
3. Call the layer/driver `GetPhysicalDeviceProcAddr`
- If it returns `non-NULL`, return a trampoline to a generic physical device
function, and set up a generic terminator which will pass it to the proper
driver.
4. Call down using `GetInstanceProcAddr`
- If it returns non-NULL, treat it as an unknown logical device command.
This means setting up a generic trampoline function that takes in a `VkDevice`
as the first parameter and adjusting the dispatch table to call the
driver/layer's function after getting the dispatch table from the
`VkDevice`.
Then, return the pointer to the corresponding trampoline function.
5. Return `NULL`
The result is that if the command gets promoted to Vulkan core later, it will no
longer be set up using `vk_icdGetPhysicalDeviceProcAddr`.
Additionally, if the loader adds direct support for the extension, it will no
longer get to step 3, because step 2 will return a valid function pointer.
However, the driver should continue to support the command query via
`vk_icdGetPhysicalDeviceProcAddr`, until at least a Vulkan version bump, because
an older loader may still be attempting to use the commands.
### Reason for adding `vk_icdGetPhysicalDeviceProcAddr`
Originally, when the loader's `vkGetInstanceProcAddr` was called, it would
result in the following behavior:
1. The loader would check if it was a core function:
- If so, it would return the function pointer
2. The loader would check if it was a known extension function:
- If so, it would return the function pointer
3. If the loader knew nothing about it, it would call down using
`GetInstanceProcAddr`
- If it returned `non-NULL`, treat it as an unknown logical device command.
- This meant setting up a generic trampoline function that takes in a
VkDevice as the first parameter and adjusting the dispatch table to call the
driver/layer's function after getting the dispatch table from the
`VkDevice`.
4. If all the above failed, the loader would return `NULL` to the application.
This caused problems when a driver attempted to expose new physical device
extensions the loader knew nothing about, but an application was aware of.
Because the loader knew nothing about it, the loader would get to step 3 in the
above process and would treat the function as an unknown logical device command.
The problem is, this would create a generic `VkDevice` trampoline function
which, on the first call, would attempt to dereference the VkPhysicalDevice as a
`VkDevice`.
This would lead to a crash or corruption.
## Physical Device Sorting
When an application selects a GPU to use, it must enumerate physical devices or
physical device groups.
These API functions do not specify which order the physical devices or physical
device groups will be presented in.
On Windows, the loader will attempt to sort these objects so that the system
preference will be listed first.
This mechanism does not force an application to use any particular GPU —
it merely changes the order in which they are presented.
This mechanism requires that a driver provide The Loader and Driver Interface
Version 6.
This version defines a new exported function, `vk_icdEnumerateAdapterPhysicalDevices`,
detailed below, that Drivers may provide on Windows.
This entry point is not a part of the Vulkan API itself, only a private
interface between the loader and drivers.
Note: Loader and Driver Interface Version 7 makes exporting
`vk_icdEnumerateAdapterPhysicalDevices` optional.
Instead, drivers *must* expose it through `vk_icdGetInstanceProcAddr`.
```c
VKAPI_ATTR VkResult VKAPI_CALL
vk_icdEnumerateAdapterPhysicalDevices(
VkInstance instance,
LUID adapterLUID,
uint32_t* pPhysicalDeviceCount,
VkPhysicalDevice* pPhysicalDevices);
```
This function takes an adapter LUID as input, and enumerates all Vulkan physical
devices that are associated with that LUID.
This works in the same way as other Vulkan enumerations — if
`pPhysicalDevices` is `NULL`, then the count will be provided.
Otherwise, the physical devices associated with the queried adapter will be
provided.
The function must provide multiple physical devices when the LUID refers to a
linked adapter.
This allows the loader to translate the adapter into Vulkan physical device
groups.
While the loader attempts to match the system's preference for GPU ordering,
there are some limitations.
Because this feature requires a new driver interface, only physical devices from
drivers that support this function will be sorted.
All unsorted physical devices will be listed at the end of the list, in an
indeterminate order.
Furthermore, only physical devices that correspond to an adapter may be sorted.
This means that a software driver would likely not be sorted.
Finally, this API only applies to Windows systems and will only work on versions
of Windows 10 that support GPU selection through the OS.
Other platforms may be included in the future, but they will require separate
platform-specific interfaces.
A requirement of `vk_icdEnumerateAdapterPhysicalDevices` is that it *must*
return the same `VkPhysicalDevice` handle values for the same physical
devices that are returned by `vkEnumeratePhysicalDevices`.
This is because the loader calls both functions on the driver then
de-duplicates the physical devices using the `VkPhysicalDevice` handles.
Since not all physical devices in a driver will have a LUID, such as for
software implementations, this step is necessary to allow drivers to
enumerate all available physical devices.
## Driver Dispatchable Object Creation
As previously covered, the loader requires dispatch tables to be accessible
within Vulkan dispatchable objects, such as: `VkInstance`, `VkPhysicalDevice`,
`VkDevice`, `VkQueue`, and `VkCommandBuffer`.
The specific requirements on all dispatchable objects created by drivers
are as follows:
- All dispatchable objects created by a driver can be cast to void \*\*
- The loader will replace the first entry with a pointer to the dispatch table
which is owned by the loader.
This implies three things for drivers:
1. The driver must return a pointer for the opaque dispatchable object handle
2. This pointer points to a regular C structure with the first entry being a
pointer.
* **NOTE:** For any C\++ drivers that implement VK objects directly
as C\++ classes:
* The C\++ compiler may put a vtable at offset zero if the class is
non-POD due to the use of a virtual function.
* In this case use a regular C structure (see below).
3. The loader checks for a magic value (ICD\_LOADER\_MAGIC) in all the created
dispatchable objects, as follows (see `include/vulkan/vk_icd.h`):
```cpp
#include "vk_icd.h"
union _VK_LOADER_DATA {
uintptr loadermagic;
void * loaderData;
} VK_LOADER_DATA;
vkObj
alloc_icd_obj()
{
vkObj *newObj = alloc_obj();
...
// Initialize pointer to loader's dispatch table with ICD_LOADER_MAGIC
set_loader_magic_value(newObj);
...
return newObj;
}
```
## Handling KHR Surface Objects in WSI Extensions
Normally, drivers handle object creation and destruction for various Vulkan
objects.
The WSI surface extensions for Linux, Windows, macOS, and QNX
("VK\_KHR\_win32\_surface", "VK\_KHR\_xcb\_surface", "VK\_KHR\_xlib\_surface",
"VK\_KHR\_wayland\_surface", "VK\_MVK\_macos\_surface",
"VK\_QNX\_screen\_surface" and "VK\_KHR\_surface") are handled differently.
For these extensions, the `VkSurfaceKHR` object creation and destruction may be
handled by either the loader or a driver.
If the loader handles the management of the `VkSurfaceKHR` objects:
1. The loader will handle the calls to `vkCreateXXXSurfaceKHR` and
`vkDestroySurfaceKHR`
functions without involving the drivers.
* Where XXX stands for the Windowing System name:
* Wayland
* XCB
* Xlib
* Windows
* Android
* MacOS (`vkCreateMacOSSurfaceMVK`)
* QNX (`vkCreateScreenSurfaceQNX`)
2. The loader creates a `VkIcdSurfaceXXX` object for the corresponding
`vkCreateXXXSurfaceKHR` call.
* The `VkIcdSurfaceXXX` structures are defined in `include/vulkan/vk_icd.h`.
3. Drivers can cast any `VkSurfaceKHR` object to a pointer to the
appropriate `VkIcdSurfaceXXX` structure.
4. The first field of all the `VkIcdSurfaceXXX` structures is a
`VkIcdSurfaceBase` enumerant that indicates whether the
surface object is Win32, XCB, Xlib, Wayland, or Screen.
The driver may choose to handle `VkSurfaceKHR` object creation instead.
If a driver desires to handle creating and destroying it must do the following:
1. Support Loader and Driver Interface Version 3 or newer.
2. Expose and handle all functions that take in a `VkSurfaceKHR` object,
including:
* `vkCreateXXXSurfaceKHR`
* `vkGetPhysicalDeviceSurfaceSupportKHR`
* `vkGetPhysicalDeviceSurfaceCapabilitiesKHR`
* `vkGetPhysicalDeviceSurfaceFormatsKHR`
* `vkGetPhysicalDeviceSurfacePresentModesKHR`
* `vkCreateSwapchainKHR`
* `vkDestroySurfaceKHR`
Because the `VkSurfaceKHR` object is an instance-level object, one object can be
associated with multiple drivers.
Therefore, when the loader receives the `vkCreateXXXSurfaceKHR` call, it still
creates an internal `VkSurfaceIcdXXX` object.
This object acts as a container for each driver's version of the
`VkSurfaceKHR` object.
If a driver does not support the creation of its own `VkSurfaceKHR` object, the
loader's container stores a NULL for that driver.
On the other hand, if the driver does support `VkSurfaceKHR` creation, the
loader will make the appropriate `vkCreateXXXSurfaceKHR` call to the
driver, and store the returned pointer in its container object.
The loader then returns the `VkSurfaceIcdXXX` as a `VkSurfaceKHR` object back up
the call chain.
Finally, when the loader receives the `vkDestroySurfaceKHR` call, it
subsequently calls `vkDestroySurfaceKHR` for each driver whose internal
`VkSurfaceKHR` object is not NULL.
Then the loader destroys the container object before returning.
## Loader and Driver Interface Negotiation
Generally, for functions issued by an application, the loader can be viewed as a
pass through.
That is, the loader generally doesn't modify the functions or their parameters,
but simply calls the driver's entry point for that function.
There are specific additional interface requirements a driver needs to comply
with that are not part of any requirements from the Vulkan specification.
These additional requirements are versioned to allow flexibility in the future.
### Windows, Linux and macOS Driver Negotiation
#### Version Negotiation Between the Loader and Drivers
All drivers supporting Loader and Driver Interface Version 2 or higher must
export the following function that is used for determination of the interface
version that will be used.
This entry point is not a part of the Vulkan API itself, only a private
interface between the loader and drivers.
Note: Loader and Driver Interface Version 7 makes exporting
`vk_icdNegotiateLoaderICDInterfaceVersion` optional.
Instead, drivers *must* expose it through `vk_icdGetInstanceProcAddr`.
```cpp
VKAPI_ATTR VkResult VKAPI_CALL
vk_icdNegotiateLoaderICDInterfaceVersion(
uint32_t* pSupportedVersion);
```
This function allows the loader and driver to agree on an interface version to
use.
The "pSupportedVersion" parameter is both an input and output parameter.
"pSupportedVersion" is filled in by the loader with the desired latest interface
version supported by the loader (typically the latest).
The driver receives this and returns back the version it desires in the same
field.
Because it is setting up the interface version between the loader and
driver, this should be the first call made by a loader to the driver (even prior
to any calls to `vk_icdGetInstanceProcAddr`).
If the driver receiving the call no longer supports the interface version
provided by the loader (due to deprecation), then it should report a
`VK_ERROR_INCOMPATIBLE_DRIVER` error.
Otherwise it sets the value pointed by "pSupportedVersion" to the latest
interface version supported by both the driver and the loader and returns
`VK_SUCCESS`.
The driver should report `VK_SUCCESS` in case the loader-provided interface
version is newer than that supported by the driver, as it's the loader's
responsibility to determine whether it can support the older interface version
supported by the driver.
The driver should also report `VK_SUCCESS` in the case its interface version is
greater than the loader's, but return the loader's version.
Thus, upon return of `VK_SUCCESS` the "pSupportedVersion" will contain the
desired interface version to be used by the driver.
If the loader receives an interface version from the driver that the loader no
longer supports (due to deprecation), or it receives a
`VK_ERROR_INCOMPATIBLE_DRIVER` error instead of `VK_SUCCESS`, then the loader
will treat the driver as incompatible and will not load it for use.
In this case, the application will not see the driver's `vkPhysicalDevice`
during enumeration.
#### Interfacing With Legacy Drivers or Loaders
If a loader sees that a driver does not export or expose the
`vk_icdNegotiateLoaderICDInterfaceVersion` function, then the loader assumes the
corresponding driver only supports either interface version 0 or 1.
From the other side of the interface, if a driver sees a call to
`vk_icdGetInstanceProcAddr` before a call to
`vk_icdNegotiateLoaderICDInterfaceVersion`, then the loader is either a legacy
loader with only support for interface version 0 or 1, or the loader is using
interface version 7 or newer.
If the first call to `vk_icdGetInstanceProcAddr` is to query for
`vk_icdNegotiateLoaderICDInterfaceVersion`, then that means the loader is using
interface version 7.
This only occurs when the driver does not export
`vk_icdNegotiateLoaderICDInterfaceVersion`.
Drivers which export `vk_icdNegotiateLoaderICDInterfaceVersion` will have it
called first.
If the first call to `vk_icdGetInstanceProcAddr` is **not** querying for
`vk_icdNegotiateLoaderICDInterfaceVersion`, then loader is a legacy loader only
which supports version 0 or 1.
In this case, if the loader calls `vk_icdGetInstanceProcAddr` first, it supports
at least interface version 1.
Otherwise, the loader only supports version 0.
#### Loader and Driver Interface Version 7 Requirements
Version 7 relaxes the requirement that Loader and Driver Interface functions
must be exported.
Instead, it only requires that those functions be queryable through
`vk_icdGetInstanceProcAddr`.
The functions are:
`vk_icdNegotiateLoaderICDInterfaceVersion`
`vk_icdGetPhysicalDeviceProcAddr`
`vk_icdEnumerateAdapterPhysicalDevices` (Windows only)
These functions are considered global for the purposes of retrieval, so the
`VkInstance` parameter of `vk_icdGetInstanceProcAddr` will be **NULL**.
While exporting these functions is no longer a requirement, drivers may still
export them for compatibility with older loaders.
The changes in this version allow drivers provided through the
`VK_LUNARG_direct_driver_loading` extension to support the entire Loader and
Driver Interface.
#### Loader and Driver Interface Version 6 Requirements
Version 6 provides a mechanism to allow the loader to sort physical devices.
The loader will only attempt to sort physical devices on a driver if version 6
of the interface is supported.
This version provides the `vk_icdEnumerateAdapterPhysicalDevices` function
defined earlier in this document.
#### Loader and Driver Interface Version 5 Requirements
This interface version has no changes to the actual interface.
If the loader requests interface version 5 or greater, it is simply
an indication to drivers that the loader is now evaluating whether the API
Version info passed into vkCreateInstance is a valid version for the loader.
If it is not, the loader will catch this during vkCreateInstance and fail with a
`VK_ERROR_INCOMPATIBLE_DRIVER` error.
On the other hand, if version 5 or newer is not requested by the loader, then it
indicates to the driver that the loader is ignorant of the API version being
requested.
Because of this, it falls on the driver to validate that the API Version is not
greater than major = 1 and minor = 0.
If it is, then the driver should automatically fail with a
`VK_ERROR_INCOMPATIBLE_DRIVER` error since the loader is a 1.0 loader, and is
unaware of the version.
Here is a table of the expected behaviors:
<table style="width:100%">
<tr>
<th>Loader Supports I/f Version</th>
<th>Driver Supports I/f Version</th>
<th>Result</th>
</tr>
<tr>
<td>4 or Earlier</td>
<td>Any Version</td>
<td>Driver <b>must fail</b> with <b>VK_ERROR_INCOMPATIBLE_DRIVER</b>
for all vkCreateInstance calls with apiVersion set to > Vulkan 1.0
because the loader is still at interface version <= 4.<br/>
Otherwise, the driver should behave as normal.
</td>
</tr>
<tr>
<td>5 or Newer</td>
<td>4 or Earlier</td>
<td>Loader <b>must fail</b> with <b>VK_ERROR_INCOMPATIBLE_DRIVER</b> if it
can't handle the apiVersion.
Driver may pass for all apiVersions, but since its interface is
<= 4, it is best if it assumes it needs to do the work of rejecting
anything > Vulkan 1.0 and fail with <b>VK_ERROR_INCOMPATIBLE_DRIVER</b>.
<br/>
Otherwise, the driver should behave as normal.
</td>
</tr>
<tr>
<td>5 or Newer</td>
<td>5 or Newer</td>
<td>Loader <b>must fail</b> with <b>VK_ERROR_INCOMPATIBLE_DRIVER</b> if it
can't handle the apiVersion, and drivers should fail with
<b>VK_ERROR_INCOMPATIBLE_DRIVER</b> <i>only if</i> they can not support
the specified apiVersion. <br/>
Otherwise, the driver should behave as normal.
</td>
</tr>
</table>
#### Loader and Driver Interface Version 4 Requirements
The major change to version 4 of this interface version is the support of
[Unknown Physical Device Extensions](#driver-unknown-physical-device-extensions)
using the `vk_icdGetPhysicalDeviceProcAddr` function.
This function is purely optional.
However, if a driver supports a physical device extension, it must provide a
`vk_icdGetPhysicalDeviceProcAddr` function.
Otherwise, the loader will continue to treat any unknown functions as VkDevice
functions and cause invalid behavior.
#### Loader and Driver Interface Version 3 Requirements
The primary change that occurred in this interface version is to allow a driver
to handle creation and destruction of their own KHR_surfaces.
Up until this point, the loader created a surface object that was used by all
drivers.
However, some drivers *may* want to provide their own surface handles.
If a driver chooses to enable this support, it must support Loader and Driver
Interface Version 3, as well as any Vulkan function that uses a `VkSurfaceKHR`
handle, such as:
- `vkCreateXXXSurfaceKHR` (where XXX is the platform-specific identifier [i.e.
`vkCreateWin32SurfaceKHR` for Windows])
- `vkDestroySurfaceKHR`
- `vkCreateSwapchainKHR`
- `vkGetPhysicalDeviceSurfaceSupportKHR`
- `vkGetPhysicalDeviceSurfaceCapabilitiesKHR`
- `vkGetPhysicalDeviceSurfaceFormatsKHR`
- `vkGetPhysicalDeviceSurfacePresentModesKHR`
A driver which does not participate in this functionality can opt out by
simply not exposing the above `vkCreateXXXSurfaceKHR` and
`vkDestroySurfaceKHR` functions.
#### Loader and Driver Interface Version 2 Requirements
Interface Version 2 requires that drivers export
`vk_icdNegotiateLoaderICDInterfaceVersion`.
For more information, see [Version Negotiation Between Loader and Drivers](#version-negotiation-between-loader-and-drivers).
Additional, version 2 requires that Vulkan dispatchable objects created by
drivers must be created in accordance to the
[Driver Dispatchable Object Creation](#driver-dispatchable-object-creation)
section.
#### Loader and Driver Interface Version 1 Requirements
Version 1 of the interface added the driver-specific entry-point
`vk_icdGetInstanceProcAddr`.
Since this is before the creation of the
`vk_icdNegotiateLoaderICDInterfaceVersion` entry-point, the loader has no
negotiation process for determine what interface version the driver
supports.
Because of this, the loader detects support for version 1 of the interface
by the absence of the negotiate function, but the presence of the
`vk_icdGetInstanceProcAddr`.
No other entry-points need to be exported by the driver as the loader will query
the appropriate function pointers using that.
#### Loader and Driver Interface Version 0 Requirements
Version 0 does not support either `vk_icdGetInstanceProcAddr` or
`vk_icdNegotiateLoaderICDInterfaceVersion`.
Because of this, the loader will assume the driver supports only version 0 of
the interface unless one of those functions exists.
Additionally, for Version 0, the driver must expose at least the following core
Vulkan entry-points so the loader may build up the interface to the driver:
- The function `vkGetInstanceProcAddr` **must be exported** in the driver
library and returns valid function pointers for all the Vulkan API entry points.
- `vkCreateInstance` **must be exported** by the driver library.
- `vkEnumerateInstanceExtensionProperties` **must be exported** by the driver
library.
#### Additional Interface Notes:
- The loader will filter out extensions requested in `vkCreateInstance` and
`vkCreateDevice` before calling into the driver; filtering will be of extensions
advertised by entities (e.g. layers) different from the driver in question.
- The loader will not call the driver for `vkEnumerate*LayerProperties`
as layer properties are obtained from the layer libraries and layer JSON files.
- If a driver library author wants to implement a layer, it can do so by having
the appropriate layer JSON manifest file refer to the driver library file.
- The loader will not call the driver for `vkEnumerate*ExtensionProperties` if
"pLayerName" is not equal to `NULL`.
- Drivers creating new dispatchable objects via device extensions need
to initialize the created dispatchable object.
The loader has generic *trampoline* code for unknown device extensions.
This generic *trampoline* code doesn't initialize the dispatch table within the
newly created object.
See the
[Driver Dispatchable Object Creation](#driver-dispatchable-object-creation)
section for more information on how to initialize created dispatchable objects
for extensions non known by the loader.
### Android Driver Negotiation
The Android loader uses the same protocol for initializing the dispatch table as
described above.
The only difference is that the Android loader queries layer and extension
information directly from the respective libraries and does not use the JSON
manifest files used by the Windows, Linux and macOS loaders.
## Loader implementation of VK_KHR_portability_enumeration
The loader implements the `VK_KHR_portability_enumeration` instance extension,
which filters out any drivers that report support for the portability subset
device extension. Unless the application explicitly requests enumeration of
portability devices by setting the
`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` bit in the
VkInstanceCreateInfo::flags, the loader does not load any drivers that declare
themselves to be portability drivers.
Drivers declare whether they are portability drivers or not in the Driver
Manifest Json file, with the `is_portability_driver` boolean field.
[More information here](#driver-manifest-file-version-101)
The initial support for this extension only reported errors when an application
did not enable the portability enumeration feature. It did not filter out
portability drivers. This was done to give a grace period for applications to
update their instance creation logic without outright breaking the application.
## Loader and Driver Policy
This section is intended to define proper behavior expected between the loader
and drivers.
Much of this section is additive to the Vulkan spec, and necessary for
maintaining consistency across platforms.
In fact, much of the language can be found throughout this document, but is
summarized here for convenience.
Additionally, there should be a way to identify bad or non-conformant behavior
in a driver and remedy it as soon as possible.
Therefore, a policy numbering system is provided to clearly identify each
policy statement in a unique way.
Finally, based on the goal of making the loader efficient and performant,
some of these policy statements defining proper driver behavior may not
be testable (and therefore aren't enforceable by the loader).
However, that should not detract from the requirement in order to provide the
best experience to end-users and developers.
### Number Format
Loader and Driver policy items start with the prefix `LDP_` (short for
Loader and Driver Policy) which is followed by an identifier based on what
component the policy is targeted against.
In this case there are only two possible components:
- Drivers: which will have the string `DRIVER_` as part of the policy number.
- The Loader: which will have the string `LOADER_` as part of the policy
number.
### Android Differences
As stated before, the Android Loader is actually separate from the Khronos
Loader.
Because of this and other platform requirements, not all of these policy
statements apply to Android.
Each table also has a column titled "Applicable to Android?"
which indicates which policy statements apply to drivers that are focused
only on Android support.
Further information on the Android loader can be found in the
<a href="https://source.android.com/devices/graphics/implement-vulkan">
Android Vulkan documentation</a>.
### Requirements of Well-Behaved Drivers
<table style="width:100%">
<tr>
<th>Requirement Number</th>
<th>Requirement Description</th>
<th>Result of Non-Compliance</th>
<th>Applicable to Android?</th>
<th>Enforceable by Loader?</th>
<th>Reference Section</th>
</tr>
<tr>
<td><small><b>LDP_DRIVER_1</b></small></td>
<td>A driver <b>must not</b> cause other drivers to fail, crash, or
otherwise misbehave.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>Yes</td>
<td>No</td>
<td><small>N/A</small></td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_2</b></small></td>
<td>A driver <b>must not</b> crash if it detects that there are no supported
Vulkan Physical Devices (<i>VkPhysicalDevice</i>) on the system when a
call to that driver is made using any Vulkan instance of physical device
API.<br/>
This is because some devices can be hot-plugged.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>Yes</td>
<td>No<br/>
The loader has no direct knowledge of what devices (virtual or physical)
may be supported by a given driver.</td>
<td><small>N/A</small>
</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_3</b></small></td>
<td>A driver <b>must</b> be able to negotiate a supported version of the
Loader and Driver Interface with the loader in accordance with the stated
negotiation process.
</td>
<td>The driver will not be loaded.</td>
<td>No</td>
<td>Yes</td>
<td><small>
<a href="#loader-and-driver-interface-negotiation">
Interface Negotiation</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_4</b></small></td>
<td>A driver <b>must</b> have a valid JSON manifest file for the loader to
process that ends with the ".json" suffix.
</td>
<td>The driver will not be loaded.</td>
<td>No</td>
<td>Yes</td>
<td><small>
<a href="#driver-manifest-file-format">Manifest File Format</a>
</small>
</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_5</b></small></td>
<td>A driver <b>must</b> pass conformance with the results submitted,
verified, and approved by Khronos before reporting a conformance version
through any mechanism provided by Vulkan (examples include inside the
<i>VkPhysicalDeviceVulkan12Properties</i> and the
<i>VkPhysicalDeviceDriverProperties</i> structs).<br/>
Otherwise, when such a structure containing a conformance version is
encountered, the driver <b>must</b> return a conformance version
of 0.0.0.0 to indicate it hasn't been so verified and approved.
</td>
<td>Yes</td>
<td>No</td>
<td>The loader and/or the application may make assumptions about the
capabilities of the driver resulting in undefined behavior
possibly including crashes or corruption.
</td>
<td><small>
<a href="https://github.com/KhronosGroup/VK-GL-CTS/blob/main/external/openglcts/README.md">
Vulkan CTS Documentation</a>
</small>
</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_6</b></small></td>
<td>Removed - See
<a href="#removed-driver-policies">Removed Driver Policies</a>
</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_7</b></small></td>
<td>If a driver desires to support Vulkan API 1.1 or newer, it <b>must</b>
expose support for Loader and Driver Interface Version 5 or newer.
</td>
<td>The driver will be used when it shouldn't be and will cause
undefined behavior possibly including crashes or corruption.
</td>
<td>No</td>
<td>Yes</td>
<td><small>
<a href="#loader-version-5-interface-requirements">
Version 5 Interface Requirements</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_8</b></small></td>
<td>If a driver wishes to handle its own <i>VkSurfaceKHR</i> object
creation, it <b>must</b> implement the Loader and Driver Interface Version 3 or
newer and support querying all the relevant surface functions via
<i>vk_icdGetInstanceProcAddr</i>.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
<td>Yes</td>
<td><small>
<a href="#handling-khr-surface-objects-in-wsi-extensions">
Handling KHR Surface Objects</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_9</b></small></td>
<td>If version negotiation results in a driver using the Loader
and Driver Interface Version 4 or earlier, the driver <b>must</b> verify
that the Vulkan API version passed into <i>vkCreateInstance</i> (through
<i>VkInstanceCreateInfo</i>’s <i>VkApplicationInfo</i>'s
<i>apiVersion</i>) is supported.
If the requested Vulkan API version can not be supported by the driver,
it <b>must</b> return <b>VK_ERROR_INCOMPATIBLE_DRIVER</b>. <br/>
This is not required if the interface version is 5 or newer because the
loader is responsible for this check.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
<td>No</td>
<td><small>
<a href="#loader-version-5-interface-requirements">
Version 5 Interface Requirements</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_10</b></small></td>
<td>If version negotiation results in a driver using the Loader and Driver Interface
Version 5 or newer, the driver <b>must</b> not return
<b>VK_ERROR_INCOMPATIBLE_DRIVER</b> if the Vulkan API version
passed into <i>vkCreateInstance</i> (through
<i>VkInstanceCreateInfo</i>’s <i>VkApplicationInfo</i>'s
<i>apiVersion</i>) is not supported by the driver. This check is performed
by the loader on the drivers behalf.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
<td>No</td>
<td><small>
<a href="#loader-version-5-interface-requirements">
Version 5 Interface Requirements</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_11</b></small></td>
<td>A driver <b>must</b> remove all Manifest files and references to those
files (i.e. Registry entries on Windows) when uninstalling.
<br/>
Similarly, on updating the driver files, the old files <b>must</b> be
all updated or removed.
</td>
<td>If an old file is left pointing to an incorrect library, it will
result in undefined behavior which may include crashes or corruption.
</td>
<td>No</td>
<td>No<br/>
The loader has no idea what driver files are new, old, or incorrect.
Any type of driver file verification would quickly become very complex
since it would require the loader to maintain an internal database
tracking badly behaving drivers based on the driver vendor, driver
version, targeted platform(s), and possibly other criteria.
</td>
<td><small>N/A</small></td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_12</b></small></td>
<td>To work properly with the public Khronos Loader, a driver
<b>must not</b> expose platform interface extensions without first
publishing them with Khronos.<br/>
Platforms under development may use modified versions of the Khronos
Loader until the design because stable and/or public.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>Yes (specifically for Android extensions)</td>
<td>No</td>
<td><small>N/A</small></td>
</tr>
</table>
#### Removed Driver Policies
These policies were in the loader source at some point but later removed.
They are documented here for reference.
<table>
<tr>
<th>Requirement Number</th>
<th>Requirement Description</th>
<th>Removal Reason</th>
</tr>
<tr>
<td><small><b>LDP_DRIVER_6</b></small></td>
<td>A driver supporting Loader and Driver Interface Version 1 or newer <b>must
not</b> directly export standard Vulkan entry-points.
<br/>
Instead, it <b>must</b> export only the loader interface functions
required by the interface versions it does support (for example
<i>vk_icdGetInstanceProcAddr</i>). <br/>
This is because the dynamic linking on some platforms has been
problematic in the past and incorrectly links to exported functions from
the wrong dynamic library at times. <br/>
<b>NOTE:</b> This is actually true for all exports.
When in doubt, don't export any items from a driver that could cause
conflicts in other libraries.<br/>
</td>
<td>
This policy has been removed due to there being valid circumstances for
drivers to export core entrypoints.
Additionally, it was not found that dynamic linking would cause many
issues in practice.
</td>
</tr>
</table>
### Requirements of a Well-Behaved Loader
<table style="width:100%">
<tr>
<th>Requirement Number</th>
<th>Requirement Description</th>
<th>Result of Non-Compliance</th>
<th>Applicable to Android?</th>
<th>Reference Section</th>
</tr>
<tr>
<td><small><b>LDP_LOADER_1</b></small></td>
<td>A loader <b>must</b> return <b>VK_ERROR_INCOMPATIBLE_DRIVER</b> if it
fails to find and load a valid Vulkan driver on the system.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>Yes</td>
<td><small>N/A</small></td>
</tr>
<tr>
<td><small><b>LDP_LOADER_2</b></small></td>
<td>A loader <b>must</b> attempt to load any driver's Manifest file it
discovers and determines is formatted in accordance with this document.
<br/>
The <b>only</b> exception is on platforms which determines driver
location and functionality through some other mechanism.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>Yes</td>
<td><small>
<a href="#driver-discovery">Driver Discovery</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_3</b></small></td>
<td>A loader <b>must</b> support a mechanism to load driver in one or more
non-standard locations.<br/>
This is to allow support for fully software drivers as well as
evaluating in-development ICDs. <br/>
The <b>only</b> exception to this rule is if the OS does not wish to
support this due to security policies.
</td>
<td>It will be more difficult to use a Vulkan loader by certain
tools and driver developers.</td>
<td>No</td>
<td><small>
<a href="#using-pre-production-icds-or-software-drivers">
Pre-Production ICDs or SW</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_4</b></small></td>
<td>A loader <b>must not</b> load a Vulkan driver which defines an API
version that is incompatible with itself.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>Yes</td>
<td><small>
<a href="#driver-discovery">Driver Discovery</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_5</b></small></td>
<td>A loader <b>must</b> ignore any driver for which a compatible
Loader and Driver Interface Version can not be negotiated.
</td>
<td>The loader would load a driver improperly resulting in undefined
behavior possibly including crashes or corruption.
</td>
<td>No</td>
<td><small>
<a href="#loader-and-driver-interface-negotiation">
Interface Negotiation</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_6</b></small></td>
<td>If a driver negotiation results in the loader using Loader and Driver
Interface Version 5 or newer, a loader <b>must</b> verify that the Vulkan
API version passed into <i>vkCreateInstance</i> (through
<i>VkInstanceCreateInfo</i>’s <i>VkApplicationInfo</i>'s
<i>apiVersion</i>) is supported by at least one driver.
If the requested Vulkan API version can not be supported by any
driver, the loader <b>must</b> return
<b>VK_ERROR_INCOMPATIBLE_DRIVER</b>.<br/>
This is not required if the Loader and Driver Interface Version is 4 or
earlier because the responsibility for this check falls on the drivers.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
<td><small>
<a href="#loader-version-5-interface-requirements">
Version 5 Interface Requirements</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_7</b></small></td>
<td>If there exist more than one driver on a system, and some of those
drivers support <i>only</i> Vulkan API version 1.0 while other drivers
support a newer Vulkan API version, then a loader <b>must</b> adjust
the <i>apiVersion</i> field of the <i>VkInstanceCreateInfo</i>’s
<i>VkApplicationInfo</i> to version 1.0 for all the drivers that are
only aware of Vulkan API version 1.0.<br/>
Otherwise, the drivers that support Vulkan API version 1.0 will
return <b>VK_ERROR_INCOMPATIBLE_DRIVER</b> during
<i>vkCreateInstance</i> since 1.0 drivers were not aware of future
versions.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
<td><small>
<a href="#driver-api-version">Driver API Version</a>
</small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_8</b></small></td>
<td>If more than one driver is present, and at least one driver <i>does not
support</i> instance-level functionality that other drivers support;
then a loader <b>must</b> support the instance-level functionality in
some fashion for the non-supporting drivers.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
<td><small>
<a href="#loader-instance-extension-emulation-support">
Loader Instance Extension Emulation Support</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_9</b></small></td>
<td>A loader <b>must</b> filter out instance extensions from the
<i>VkInstanceCreateInfo</i> structure's <i>ppEnabledExtensionNames</i>
field that the driver does not support during a call to the driver's
<i>vkCreateInstance</i>.<br/>
This is because the application has no way of knowing which
drivers support which extensions.<br/>
This ties in directly with <i>LDP_LOADER_8</i> above.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
<td><small>
<a href="#filtering-out-instance-extension-names">
Filtering Out Instance Extension Names</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_10</b></small></td>
<td>A loader <b>must</b> support creating <i>VkSurfaceKHR</i> handles
that <b>may</b> be shared by all underlying drivers.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>Yes</td>
<td><small>
<a href="#handling-khr-surface-objects-in-wsi-extensions">
Handling KHR Surface Objects</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_11</b></small></td>
<td>If a driver exposes the appropriate <i>VkSurfaceKHR</i>
creation/handling entry-points, a loader <b>must</b> support creating
the driver-specific surface object handle and provide it, and not the
shared <i>VkSurfaceKHR</i> handle, back to that driver when requested.
<br/>
Otherwise, a loader <b>must</b> provide the loader created
<i>VkSurfaceKHR</i> handle.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
<td><small>
<a href="#handling-khr-surface-objects-in-wsi-extensions">
Handling KHR Surface Objects</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_12</b></small></td>
<td>A loader <b>must not</b> call any <i>vkEnumerate*ExtensionProperties</i>
entry-points in a driver if <i>pLayerName</i> is not <b>NULL</b>.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>Yes</td>
<td><small>
<a href="#additional-interface-notes">
Additional Interface Notes</a></small>
</td>
</tr>
<tr>
<td><small><b>LDP_LOADER_13</b></small></td>
<td>A loader <b>must</b> not load from user-defined paths (including the
use of any of <i>VK_ICD_FILENAMES</i>, <i>VK_DRIVER_FILES</i>, or
<i>VK_ADD_DRIVER_FILES</i> environment variables) when running elevated
(Administrator/Super-user) applications.<br/>
<b>This is for security reasons.</b>
</td>
<td>The behavior is undefined and may result in computer security lapses,
crashes or corruption.
</td>
<td>No</td>
<td><small>
<a href="#exception-for-administrator-and-super-user-mode">
Exception for Administrator and Super-User mode
</a></small>
</td>
</tr>
</table>
<br/>
[Return to the top-level LoaderInterfaceArchitecture.md file.](LoaderInterfaceArchitecture.md)
|