Home | History | Annotate | Download | only in libvulkan
      1 {{define "Copyright"}}
      2 /*
      3 * Copyright 2016 The Android Open Source Project
      4 *
      5 * Licensed under the Apache License, Version 2.0 (the "License");
      6 * you may not use this file except in compliance with the License.
      7 * You may obtain a copy of the License at
      8 *
      9 *      http://www.apache.org/licenses/LICENSE-2.0
     10 *
     11 * Unless required by applicable law or agreed to in writing, software
     12 * distributed under the License is distributed on an "AS IS" BASIS,
     13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 * See the License for the specific language governing permissions and
     15 * limitations under the License.
     16 */
     17 {{end}}
     18 
     19 {{Include "../api/templates/vulkan_common.tmpl"}}
     20 {{Global "clang-format" (Strings "clang-format" "-style=file")}}
     21 {{Macro "DefineGlobals" $}}
     22 {{$ | Macro "api_gen.h"   | Format (Global "clang-format") | Write "api_gen.h"  }}
     23 {{$ | Macro "api_gen.cpp" | Format (Global "clang-format") | Write "api_gen.cpp"}}
     24 {{$ | Macro "driver_gen.h" | Format (Global "clang-format") | Write "driver_gen.h"}}
     25 {{$ | Macro "driver_gen.cpp" | Format (Global "clang-format") | Write "driver_gen.cpp"}}
     26 
     27 {{/*
     28 -------------------------------------------------------------------------------
     29   api_gen.h
     30 -------------------------------------------------------------------------------
     31 */}}
     32 {{define "api_gen.h"}}
     33 {{Macro "Copyright"}}
     34 
     35 // WARNING: This file is generated. See ../README.md for instructions.
     36 
     37 #ifndef LIBVULKAN_API_GEN_H
     38 #define LIBVULKAN_API_GEN_H
     39 
     40 #include <bitset>
     41 #include <vulkan/vulkan.h>
     42 #include "driver_gen.h"
     43 
     44 namespace vulkan {
     45 namespace api {
     46 
     47 struct InstanceDispatchTable {
     48   // clang-format off
     49   {{range $f := AllCommands $}}
     50     {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
     51       {{Macro "C++.DeclareTableEntry" $f}};
     52     {{end}}
     53   {{end}}
     54   // clang-format on
     55 };
     56 
     57 struct DeviceDispatchTable {
     58   // clang-format off
     59   {{range $f := AllCommands $}}
     60     {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
     61       {{Macro "C++.DeclareTableEntry" $f}};
     62     {{end}}
     63   {{end}}
     64   // clang-format on
     65 };
     66 
     67 bool InitDispatchTable(
     68     VkInstance instance,
     69     PFN_vkGetInstanceProcAddr get_proc,
     70     const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
     71 bool InitDispatchTable(
     72     VkDevice dev,
     73     PFN_vkGetDeviceProcAddr get_proc,
     74     const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
     75 
     76 } // namespace api
     77 } // namespace vulkan
     78 
     79 #endif // LIBVULKAN_API_GEN_H
     80 {{end}}
     81 
     82 
     83 {{/*
     84 -------------------------------------------------------------------------------
     85   api_gen.cpp
     86 -------------------------------------------------------------------------------
     87 */}}
     88 {{define "api_gen.cpp"}}
     89 {{Macro "Copyright"}}
     90 
     91 // WARNING: This file is generated. See ../README.md for instructions.
     92 
     93 #include <string.h>
     94 
     95 #include <algorithm>
     96 
     97 #include <log/log.h>
     98 
     99 // to catch mismatches between vulkan.h and this file
    100 #undef VK_NO_PROTOTYPES
    101 #include "api.h"
    102 
    103 namespace vulkan {
    104 namespace api {
    105 
    106 {{Macro "C++.DefineInitProcMacro" "dispatch"}}
    107 
    108 {{Macro "api.C++.DefineInitProcExtMacro"}}
    109 
    110 namespace {
    111 
    112 // clang-format off
    113 
    114 {{range $f := AllCommands $}}
    115   {{Macro "api.C++.DefineExtensionStub" $f}}
    116 {{end}}
    117 // clang-format on
    118 
    119 } // anonymous
    120 
    121 bool InitDispatchTable(
    122     VkInstance instance,
    123     PFN_vkGetInstanceProcAddr get_proc,
    124     const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
    125     auto& data = GetData(instance);
    126     bool success = true;
    127     
    128     // clang-format off
    129     {{range $f := AllCommands $}}
    130       {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
    131         {{Macro "C++.InitProc" $f}}
    132       {{end}}
    133     {{end}}
    134     // clang-format on
    135     
    136     return success;
    137 }
    138 
    139 bool InitDispatchTable(
    140     VkDevice dev,
    141     PFN_vkGetDeviceProcAddr get_proc,
    142     const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
    143     auto& data = GetData(dev);
    144     bool success = true;
    145     
    146     // clang-format off
    147     {{range $f := AllCommands $}}
    148       {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
    149         {{Macro "C++.InitProc" $f}}
    150       {{end}}
    151     {{end}}
    152     // clang-format on
    153     
    154     return success;
    155 }
    156 
    157 // clang-format off
    158 
    159 namespace {
    160 
    161 // forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr
    162 {{range $f := AllCommands $}}
    163   {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
    164     VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}});
    165   {{end}}
    166 {{end}}
    167 
    168 {{range $f := AllCommands $}}
    169   {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
    170     VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}}) {
    171       {{     if eq $f.Name "vkGetInstanceProcAddr"}}
    172         {{Macro "api.C++.InterceptInstanceProcAddr" $}}
    173       {{else if eq $f.Name "vkGetDeviceProcAddr"}}
    174         {{Macro "api.C++.InterceptDeviceProcAddr" $}}
    175       {{end}}
    176 
    177       {{Macro "api.C++.Dispatch" $f}}
    178     }
    179     
    180   {{end}}
    181 {{end}}
    182 
    183 }  // anonymous namespace
    184 
    185 // clang-format on
    186 
    187 } // namespace api
    188 } // namespace vulkan
    189 
    190 // clang-format off
    191 
    192 {{range $f := AllCommands $}}
    193   {{if (Macro "IsFunctionExported" $f)}}
    194     __attribute__((visibility("default")))
    195     VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
    196       {{if not (IsVoid $f.Return.Type)}}return {{end}}
    197       vulkan::api::{{Macro "BaseName" $f}}({{Macro "Arguments" $f}});
    198     }
    199     
    200   {{end}}
    201 {{end}}
    202 
    203 // clang-format on
    204 {{end}}
    205 
    206 
    207 {{/*
    208 -------------------------------------------------------------------------------
    209   driver_gen.h
    210 -------------------------------------------------------------------------------
    211 */}}
    212 {{define "driver_gen.h"}}
    213 {{Macro "Copyright"}}
    214 
    215 // WARNING: This file is generated. See ../README.md for instructions.
    216 
    217 #ifndef LIBVULKAN_DRIVER_GEN_H
    218 #define LIBVULKAN_DRIVER_GEN_H
    219 
    220 #include <bitset>
    221 #include <vulkan/vulkan.h>
    222 #include <vulkan/vk_android_native_buffer.h>
    223 
    224 namespace vulkan {
    225 namespace driver {
    226 
    227 {{Macro "driver.C++.DefineProcHookType"}}
    228 
    229 struct InstanceDriverTable {
    230   // clang-format off
    231   {{range $f := AllCommands $}}
    232     {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
    233       {{Macro "C++.DeclareTableEntry" $f}};
    234     {{end}}
    235   {{end}}
    236   // clang-format on
    237 };
    238 
    239 struct DeviceDriverTable {
    240   // clang-format off
    241   {{range $f := AllCommands $}}
    242     {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
    243       {{Macro "C++.DeclareTableEntry" $f}};
    244     {{end}}
    245   {{end}}
    246   // clang-format on
    247 };
    248 
    249 const ProcHook* GetProcHook(const char* name);
    250 ProcHook::Extension GetProcHookExtension(const char* name);
    251 
    252 bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
    253                      const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
    254 bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
    255                      const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
    256 
    257 } // namespace driver
    258 } // namespace vulkan
    259 
    260 #endif // LIBVULKAN_DRIVER_TABLE_H
    261 {{end}}
    262 
    263 
    264 {{/*
    265 -------------------------------------------------------------------------------
    266   driver_gen.cpp
    267 -------------------------------------------------------------------------------
    268 */}}
    269 {{define "driver_gen.cpp"}}
    270 {{Macro "Copyright"}}
    271 
    272 // WARNING: This file is generated. See ../README.md for instructions.
    273 
    274 #include <string.h>
    275 
    276 #include <algorithm>
    277 
    278 #include <log/log.h>
    279 
    280 #include "driver.h"
    281 
    282 namespace vulkan {
    283 namespace driver {
    284 
    285 namespace {
    286 
    287 // clang-format off
    288 
    289 {{range $f := AllCommands $}}
    290   {{Macro "driver.C++.DefineProcHookStub" $f}}
    291 {{end}}
    292 // clang-format on
    293 
    294 const ProcHook g_proc_hooks[] = {
    295   // clang-format off
    296   {{range $f := SortBy (AllCommands $) "FunctionName"}}
    297     {{if (Macro "driver.IsIntercepted" $f)}}
    298       {{     if (Macro "IsGloballyDispatched" $f)}}
    299         {{Macro "driver.C++.DefineGlobalProcHook" $f}}
    300       {{else if (Macro "IsInstanceDispatched" $f)}}
    301         {{Macro "driver.C++.DefineInstanceProcHook" $f}}
    302       {{else if (Macro "IsDeviceDispatched" $f)}}
    303         {{Macro "driver.C++.DefineDeviceProcHook" $f}}
    304       {{end}}
    305     {{end}}
    306   {{end}}
    307   // clang-format on
    308 };
    309 
    310 } // anonymous
    311 
    312 const ProcHook* GetProcHook(const char* name) {
    313     const auto& begin = g_proc_hooks;
    314     const auto& end = g_proc_hooks +
    315       sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
    316     const auto hook = std::lower_bound(begin, end, name,
    317         [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
    318     return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
    319 }
    320 
    321 ProcHook::Extension GetProcHookExtension(const char* name) {
    322   {{$exts := Strings (Macro "driver.KnownExtensions") | SplitOn "\n"}}
    323   // clang-format off
    324   {{range $e := $exts}}
    325     if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
    326   {{end}}
    327   // clang-format on
    328   return ProcHook::EXTENSION_UNKNOWN;
    329 }
    330 
    331 {{Macro "C++.DefineInitProcMacro" "driver"}}
    332 
    333 {{Macro "driver.C++.DefineInitProcExtMacro"}}
    334 
    335 bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
    336                      const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
    337 {
    338     auto& data = GetData(instance);
    339     bool success = true;
    340     
    341     // clang-format off
    342     {{range $f := AllCommands $}}
    343       {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
    344         {{Macro "C++.InitProc" $f}}
    345       {{end}}
    346     {{end}}
    347     // clang-format on
    348     
    349     return success;
    350 }
    351 
    352 bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
    353                      const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
    354 {
    355     auto& data = GetData(dev);
    356     bool success = true;
    357     
    358     // clang-format off
    359     {{range $f := AllCommands $}}
    360       {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
    361         {{Macro "C++.InitProc" $f}}
    362       {{end}}
    363     {{end}}
    364     // clang-format on
    365     
    366     return success;
    367 }
    368 
    369 } // namespace driver
    370 } // namespace vulkan
    371 
    372 // clang-format on
    373 {{end}}
    374 
    375 
    376 {{/*
    377 ------------------------------------------------------------------------------
    378   Emits a declaration of a dispatch/driver table entry.
    379 ------------------------------------------------------------------------------
    380 */}}
    381 {{define "C++.DeclareTableEntry"}}
    382   {{AssertType $ "Function"}}
    383 
    384   {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
    385 {{end}}
    386 
    387 
    388 {{/*
    389 -------------------------------------------------------------------------------
    390   Emits INIT_PROC macro.
    391 -------------------------------------------------------------------------------
    392 */}}
    393 {{define "C++.DefineInitProcMacro"}}
    394   #define UNLIKELY(expr) __builtin_expect((expr), 0)
    395   
    396   #define INIT_PROC(required, obj, proc) do {                   \
    397       data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
    398               get_proc(obj, "vk" # proc));                      \
    399       if (UNLIKELY(required && !data.{{$}}.proc)) {             \
    400           ALOGE("missing " # obj " proc: vk" # proc);           \
    401           success = false;                                      \
    402       }                                                         \
    403   } while(0)
    404 {{end}}
    405 
    406 
    407 {{/*
    408 -------------------------------------------------------------------------------
    409   Emits code to invoke INIT_PROC or INIT_PROC_EXT.
    410 -------------------------------------------------------------------------------
    411 */}}
    412 {{define "C++.InitProc"}}
    413   {{AssertType $ "Function"}}
    414 
    415   {{$ext := GetAnnotation $ "extension"}}
    416   {{if $ext}}
    417     INIT_PROC_EXT({{Macro "BaseName" $ext}}, 
    418   {{else}}
    419     INIT_PROC(
    420   {{end}}
    421 
    422   {{if GetAnnotation $ "optional"}}false{{else if GetAnnotation $ "vulkan1_1"}}false{{else}}true{{end}}, 
    423 
    424   {{if (Macro "IsInstanceDispatched" $)}}
    425     instance, 
    426   {{else}}
    427     dev, 
    428   {{end}}
    429 
    430   {{Macro "BaseName" $}});
    431 {{end}}
    432 
    433 
    434 {{/*
    435 ------------------------------------------------------------------------------
    436   Emits true if a function is exported and instance-dispatched.
    437 ------------------------------------------------------------------------------
    438 */}}
    439 {{define "api.IsInstanceDispatchTableEntry"}}
    440   {{AssertType $ "Function"}}
    441 
    442   {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
    443     {{/* deprecated and unused internally */}}
    444     {{if not (eq $.Name "vkEnumerateDeviceLayerProperties")}}
    445       true
    446     {{end}}
    447   {{end}}
    448 {{end}}
    449 
    450 
    451 {{/*
    452 ------------------------------------------------------------------------------
    453   Emits true if a function is exported and device-dispatched.
    454 ------------------------------------------------------------------------------
    455 */}}
    456 {{define "api.IsDeviceDispatchTableEntry"}}
    457   {{AssertType $ "Function"}}
    458 
    459   {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
    460     true
    461   {{end}}
    462 {{end}}
    463 
    464 
    465 {{/*
    466 ------------------------------------------------------------------------------
    467   Emits true if a function is intercepted by vulkan::api.
    468 ------------------------------------------------------------------------------
    469 */}}
    470 {{define "api.IsIntercepted"}}
    471   {{AssertType $ "Function"}}
    472 
    473   {{if (Macro "IsFunctionSupported" $)}}
    474     {{/* Global functions cannot be dispatched at all */}}
    475     {{     if (Macro "IsGloballyDispatched" $)}}true
    476 
    477     {{/* VkPhysicalDevice functions that manage device layers */}}
    478     {{else if eq $.Name "vkCreateDevice"}}true
    479     {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
    480     {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
    481 
    482     {{/* Destroy functions of dispatchable objects */}}
    483     {{else if eq $.Name "vkDestroyInstance"}}true
    484     {{else if eq $.Name "vkDestroyDevice"}}true
    485 
    486     {{end}}
    487   {{end}}
    488 {{end}}
    489 
    490 
    491 {{/*
    492 -------------------------------------------------------------------------------
    493   Emits INIT_PROC_EXT macro for vulkan::api.
    494 -------------------------------------------------------------------------------
    495 */}}
    496 {{define "api.C++.DefineInitProcExtMacro"}}
    497   // Exported extension functions may be invoked even when their extensions
    498   // are disabled.  Dispatch to stubs when that happens.
    499   #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
    500       if (extensions[driver::ProcHook::ext])                    \
    501         INIT_PROC(required, obj, proc);                         \
    502       else                                                      \
    503         data.dispatch.proc = disabled ## proc;                  \
    504   } while(0)
    505 {{end}}
    506 
    507 
    508 {{/*
    509 -------------------------------------------------------------------------------
    510   Emits a stub for an exported extension function.
    511 -------------------------------------------------------------------------------
    512 */}}
    513 {{define "api.C++.DefineExtensionStub"}}
    514   {{AssertType $ "Function"}}
    515 
    516   {{$ext := GetAnnotation $ "extension"}}
    517   {{if and $ext (Macro "IsFunctionExported" $)}}
    518     {{$ext_name := index $ext.Arguments 0}}
    519 
    520     {{$base := (Macro "BaseName" $)}}
    521 
    522     {{$p0 := (index $.CallParameters 0)}}
    523     {{$ptail := (Tail 1 $.CallParameters)}}
    524 
    525     {{$first_type := (Macro "Parameter" $p0)}}
    526     {{$tail_types := (ForEach $ptail "ParameterType" | JoinWith ", ")}}
    527 
    528     VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$first_type}}, {{$tail_types}}) {
    529       driver::Logger({{$p0.Name}}).Err({{$p0.Name}}, 
    530         "{{$ext_name}} not enabled. Exported {{$.Name}} not executed.");
    531       {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
    532     }
    533     
    534   {{end}}
    535 {{end}}
    536 
    537 
    538 {{/*
    539 ------------------------------------------------------------------------------
    540   Emits code for vkGetInstanceProcAddr for function interception.
    541 ------------------------------------------------------------------------------
    542 */}}
    543 {{define "api.C++.InterceptInstanceProcAddr"}}
    544   {{AssertType $ "API"}}
    545 
    546   // global functions
    547   if (instance == VK_NULL_HANDLE) {
    548     {{range $f := AllCommands $}}
    549       {{if (Macro "IsGloballyDispatched" $f)}}
    550         if (strcmp(pName, "{{$f.Name}}") == 0) return 
    551           reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}});
    552       {{end}}
    553     {{end}}
    554     
    555     ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", pName);
    556     return nullptr;
    557   }
    558   
    559   static const struct Hook {
    560     const char* name;
    561     PFN_vkVoidFunction proc;
    562   } hooks[] = {
    563     {{range $f := SortBy (AllCommands $) "FunctionName"}}
    564       {{if (Macro "IsFunctionExported" $f)}}
    565         {{/* hide global functions */}}
    566         {{if (Macro "IsGloballyDispatched" $f)}}
    567           { "{{$f.Name}}", nullptr },
    568 
    569         {{/* redirect intercepted functions */}}
    570         {{else if (Macro "api.IsIntercepted" $f)}}
    571           { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(
    572             {{Macro "BaseName" $f}}) },
    573 
    574         {{/* redirect vkGetInstanceProcAddr to itself */}}
    575         {{else if eq $f.Name "vkGetInstanceProcAddr"}}
    576           { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}}) },
    577 
    578         {{/* redirect device functions to themselves as a workaround for
    579              layers that do not intercept in their vkGetInstanceProcAddr */}}
    580         {{else if (Macro "IsDeviceDispatched" $f)}}
    581           { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}}) },
    582 
    583         {{end}}
    584       {{end}}
    585     {{end}}
    586   };
    587   // clang-format on
    588   constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
    589   auto hook = std::lower_bound(
    590     hooks, hooks + count, pName,
    591     [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
    592   if (hook <  hooks + count && strcmp(hook->name, pName) == 0) {
    593     if (!hook->proc) {
    594       vulkan::driver::Logger(instance).Err(
    595         instance, "invalid vkGetInstanceProcAddr(%p, \"%s\") call",
    596         instance, pName);
    597     }
    598     return hook->proc;
    599   }
    600   // clang-format off
    601   
    602 {{end}}
    603 
    604 
    605 {{/*
    606 ------------------------------------------------------------------------------
    607   Emits code for vkGetDeviceProcAddr for function interception.
    608 ------------------------------------------------------------------------------
    609 */}}
    610 {{define "api.C++.InterceptDeviceProcAddr"}}
    611   {{AssertType $ "API"}}
    612 
    613   if (device == VK_NULL_HANDLE) {
    614     ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
    615     return nullptr;
    616   }
    617   
    618   static const char* const known_non_device_names[] = {
    619     {{range $f := SortBy (AllCommands $) "FunctionName"}}
    620       {{if (Macro "IsFunctionSupported" $f)}}
    621         {{if not (Macro "IsDeviceDispatched" $f)}}
    622           "{{$f.Name}}",
    623         {{end}}
    624       {{end}}
    625     {{end}}
    626   };
    627   // clang-format on
    628   constexpr size_t count = sizeof(known_non_device_names) /
    629     sizeof(known_non_device_names[0]);
    630   if (!pName ||
    631       std::binary_search(
    632         known_non_device_names, known_non_device_names + count, pName,
    633         [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
    634     vulkan::driver::Logger(device).Err(
    635       device, "invalid vkGetDeviceProcAddr(%p, \"%s\") call", device,
    636       (pName) ? pName : "(null)");
    637     return nullptr;
    638   }
    639   // clang-format off
    640   
    641   {{range $f := AllCommands $}}
    642     {{if (Macro "IsDeviceDispatched" $f)}}
    643       {{     if (Macro "api.IsIntercepted" $f)}}
    644         if (strcmp(pName, "{{$f.Name}}") == 0) return 
    645           reinterpret_cast<PFN_vkVoidFunction>(
    646             {{Macro "BaseName" $f}});
    647       {{else if eq $f.Name "vkGetDeviceProcAddr"}}
    648         if (strcmp(pName, "{{$f.Name}}") == 0) return 
    649           reinterpret_cast<PFN_vkVoidFunction>(
    650             {{Macro "BaseName" $f}});
    651       {{end}}
    652     {{end}}
    653   {{end}}
    654   
    655 {{end}}
    656 
    657 
    658 {{/*
    659 ------------------------------------------------------------------------------
    660   Emits code to dispatch a function.
    661 ------------------------------------------------------------------------------
    662 */}}
    663 {{define "api.C++.Dispatch"}}
    664   {{AssertType $ "Function"}}
    665   {{if (Macro "api.IsIntercepted" $)}}
    666     {{Error "$.Name should not be generated"}}
    667   {{end}}
    668 
    669   {{if not (IsVoid $.Return.Type)}}return {{end}}
    670 
    671   {{$p0 := index $.CallParameters 0}}
    672   GetData({{$p0.Name}}).dispatch.
    673   {{Macro "BaseName" $}}({{Macro "Arguments" $}});
    674 {{end}}
    675 
    676 
    677 {{/*
    678 ------------------------------------------------------------------------------
    679   Emits a list of extensions intercepted by vulkan::driver.
    680 ------------------------------------------------------------------------------
    681 */}}
    682 {{define "driver.InterceptedExtensions"}}
    683 VK_ANDROID_native_buffer
    684 VK_EXT_debug_report
    685 VK_EXT_hdr_metadata
    686 VK_EXT_swapchain_colorspace
    687 VK_GOOGLE_display_timing
    688 VK_KHR_android_surface
    689 VK_KHR_incremental_present
    690 VK_KHR_shared_presentable_image
    691 VK_KHR_surface
    692 VK_KHR_swapchain
    693 VK_KHR_get_surface_capabilities2
    694 {{end}}
    695 
    696 
    697 {{/*
    698 ------------------------------------------------------------------------------
    699   Emits a list of extensions known to vulkan::driver.
    700 ------------------------------------------------------------------------------
    701 */}}
    702 {{define "driver.KnownExtensions"}}
    703 {{Macro "driver.InterceptedExtensions"}}
    704 VK_KHR_get_physical_device_properties2
    705 VK_ANDROID_external_memory_android_hardware_buffer
    706 VK_KHR_bind_memory2
    707 {{end}}
    708 
    709 
    710 {{/*
    711 ------------------------------------------------------------------------------
    712   Emits true if an extension is intercepted by vulkan::driver.
    713 ------------------------------------------------------------------------------
    714 */}}
    715 {{define "driver.IsExtensionIntercepted"}}
    716   {{$ext_name := index $.Arguments 0}}
    717   {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
    718 
    719   {{range $f := $filters}}
    720     {{if eq $ext_name $f}}true{{end}}
    721   {{end}}
    722 {{end}}
    723 
    724 
    725 {{/*
    726 ------------------------------------------------------------------------------
    727   Emits true if a function is intercepted by vulkan::driver.
    728 ------------------------------------------------------------------------------
    729 */}}
    730 {{define "driver.IsIntercepted"}}
    731   {{AssertType $ "Function"}}
    732 
    733   {{if (Macro "IsFunctionSupported" $)}}
    734     {{/* Create functions of dispatchable objects */}}
    735     {{     if eq $.Name "vkCreateInstance"}}true
    736     {{else if eq $.Name "vkCreateDevice"}}true
    737     {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
    738     {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
    739     {{else if eq $.Name "vkGetDeviceQueue"}}true
    740     {{else if eq $.Name "vkGetDeviceQueue2"}}true
    741     {{else if eq $.Name "vkAllocateCommandBuffers"}}true
    742 
    743     {{/* Destroy functions of dispatchable objects */}}
    744     {{else if eq $.Name "vkDestroyInstance"}}true
    745     {{else if eq $.Name "vkDestroyDevice"}}true
    746 
    747     {{/* Enumeration of extensions */}}
    748     {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
    749     {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
    750 
    751     {{else if eq $.Name "vkGetInstanceProcAddr"}}true
    752     {{else if eq $.Name "vkGetDeviceProcAddr"}}true
    753 
    754     {{/* VK_KHR_swapchain v69 requirement */}}
    755     {{else if eq $.Name "vkBindImageMemory2"}}true
    756     {{else if eq $.Name "vkBindImageMemory2KHR"}}true
    757     {{end}}
    758 
    759     {{$ext := GetAnnotation $ "extension"}}
    760     {{if $ext}}
    761       {{Macro "driver.IsExtensionIntercepted" $ext}}
    762     {{end}}
    763 
    764   {{end}}
    765 {{end}}
    766 
    767 
    768 {{/*
    769 ------------------------------------------------------------------------------
    770   Emits true if a function needs a ProcHook stub.
    771 ------------------------------------------------------------------------------
    772 */}}
    773 {{define "driver.NeedProcHookStub"}}
    774   {{AssertType $ "Function"}}
    775 
    776   {{if and (Macro "driver.IsIntercepted" $) (Macro "IsDeviceDispatched" $)}}
    777     {{$ext := GetAnnotation $ "extension"}}
    778     {{if $ext}}
    779       {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
    780     {{end}}
    781   {{end}}
    782 {{end}}
    783 
    784 
    785 {{/*
    786 -------------------------------------------------------------------------------
    787   Emits definition of struct ProcHook.
    788 -------------------------------------------------------------------------------
    789 */}}
    790 {{define "driver.C++.DefineProcHookType"}}
    791   struct ProcHook {
    792       enum Type {
    793         GLOBAL,
    794         INSTANCE,
    795         DEVICE,
    796       };
    797 
    798       enum Extension {
    799         {{$exts := Strings (Macro "driver.KnownExtensions") | SplitOn "\n"}}
    800         {{range $e := $exts}}
    801           {{TrimPrefix "VK_" $e}},
    802         {{end}}
    803         
    804         EXTENSION_CORE, // valid bit
    805         EXTENSION_COUNT,
    806         EXTENSION_UNKNOWN,
    807       };
    808       
    809       const char* name;
    810       Type type;
    811       Extension extension;
    812       
    813       PFN_vkVoidFunction proc;
    814       PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
    815   };
    816 {{end}}
    817 
    818 
    819 {{/*
    820 -------------------------------------------------------------------------------
    821   Emits INIT_PROC_EXT macro for vulkan::driver.
    822 -------------------------------------------------------------------------------
    823 */}}
    824 {{define "driver.C++.DefineInitProcExtMacro"}}
    825   #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
    826       if (extensions[ProcHook::ext])                            \
    827         INIT_PROC(required, obj, proc);                         \
    828   } while(0)
    829 {{end}}
    830 
    831 
    832 {{/*
    833 -------------------------------------------------------------------------------
    834   Emits a stub for ProcHook::checked_proc.
    835 -------------------------------------------------------------------------------
    836 */}}
    837 {{define "driver.C++.DefineProcHookStub"}}
    838   {{AssertType $ "Function"}}
    839 
    840   {{if (Macro "driver.NeedProcHookStub" $)}}
    841     {{$ext := GetAnnotation $ "extension"}}
    842     {{$ext_name := index $ext.Arguments 0}}
    843 
    844     {{$base := (Macro "BaseName" $)}}
    845 
    846     VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
    847       {{$p0 := index $.CallParameters 0}}
    848       {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
    849 
    850       if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
    851         {{if not (IsVoid $.Return.Type)}}return {{end}}
    852         {{$base}}({{Macro "Arguments" $}});
    853       } else {
    854         Logger({{$p0.Name}}).Err({{$p0.Name}}, "{{$ext_name}} not enabled. {{$.Name}} not executed.");
    855         {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
    856       }
    857     }
    858     
    859   {{end}}
    860 {{end}}
    861 
    862 
    863 {{/*
    864 -------------------------------------------------------------------------------
    865   Emits definition of a global ProcHook.
    866 -------------------------------------------------------------------------------
    867 */}}
    868 {{define "driver.C++.DefineGlobalProcHook"}}
    869   {{AssertType $ "Function"}}
    870 
    871   {{$base := (Macro "BaseName" $)}}
    872 
    873   {{$ext := GetAnnotation $ "extension"}}
    874   {{if $ext}}
    875     {{Error "invalid global extension"}}
    876   {{end}}
    877 
    878   {
    879     "{{$.Name}}",
    880     ProcHook::GLOBAL,
    881     ProcHook::EXTENSION_CORE,
    882     reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
    883     nullptr,
    884   },
    885 {{end}}
    886 
    887 
    888 {{/*
    889 -------------------------------------------------------------------------------
    890   Emits definition of an instance ProcHook.
    891 -------------------------------------------------------------------------------
    892 */}}
    893 {{define "driver.C++.DefineInstanceProcHook"}}
    894   {{AssertType $ "Function"}}
    895 
    896   {{$base := (Macro "BaseName" $)}}
    897 
    898   {
    899     "{{$.Name}}",
    900     ProcHook::INSTANCE,
    901 
    902     {{$ext := GetAnnotation $ "extension"}}
    903     {{if $ext}}
    904       ProcHook::{{Macro "BaseName" $ext}},
    905 
    906       {{if (Macro "IsExtensionInternal" $ext)}}
    907         nullptr,
    908         nullptr,
    909       {{else}}
    910         reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
    911         nullptr,
    912       {{end}}
    913     {{else}}
    914       ProcHook::EXTENSION_CORE,
    915       reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
    916       nullptr,
    917     {{end}}
    918   },
    919 {{end}}
    920 
    921 
    922 {{/*
    923 -------------------------------------------------------------------------------
    924   Emits definition of a device ProcHook.
    925 -------------------------------------------------------------------------------
    926 */}}
    927 {{define "driver.C++.DefineDeviceProcHook"}}
    928   {{AssertType $ "Function"}}
    929 
    930   {{$base := (Macro "BaseName" $)}}
    931 
    932   {
    933     "{{$.Name}}",
    934     ProcHook::DEVICE,
    935 
    936     {{$ext := GetAnnotation $ "extension"}}
    937     {{if $ext}}
    938       ProcHook::{{Macro "BaseName" $ext}},
    939 
    940       {{if (Macro "IsExtensionInternal" $ext)}}
    941         nullptr,
    942         nullptr,
    943       {{else}}
    944         reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
    945         reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
    946       {{end}}
    947     {{else}}
    948       ProcHook::EXTENSION_CORE,
    949       reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
    950       nullptr,
    951     {{end}}
    952   },
    953 {{end}}
    954 
    955 
    956 {{/*
    957 -------------------------------------------------------------------------------
    958   Emits true if a function is needed by vulkan::driver.
    959 -------------------------------------------------------------------------------
    960 */}}
    961 {{define "driver.IsDriverTableEntry"}}
    962   {{AssertType $ "Function"}}
    963 
    964   {{if (Macro "IsFunctionSupported" $)}}
    965     {{/* Create functions of dispatchable objects */}}
    966     {{     if eq $.Name "vkCreateDevice"}}true
    967     {{else if eq $.Name "vkGetDeviceQueue"}}true
    968     {{else if eq $.Name "vkGetDeviceQueue2"}}true
    969     {{else if eq $.Name "vkAllocateCommandBuffers"}}true
    970 
    971     {{/* Destroy functions of dispatchable objects */}}
    972     {{else if eq $.Name "vkDestroyInstance"}}true
    973     {{else if eq $.Name "vkDestroyDevice"}}true
    974 
    975     {{/* Enumeration of extensions */}}
    976     {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
    977 
    978     {{/* We cache physical devices in loader.cpp */}}
    979     {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
    980     {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
    981 
    982     {{else if eq $.Name "vkGetInstanceProcAddr"}}true
    983     {{else if eq $.Name "vkGetDeviceProcAddr"}}true
    984 
    985     {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
    986     {{else if eq $.Name "vkCreateImage"}}true
    987     {{else if eq $.Name "vkDestroyImage"}}true
    988 
    989     {{else if eq $.Name "vkGetPhysicalDeviceProperties"}}true
    990     {{else if eq $.Name "vkGetPhysicalDeviceProperties2"}}true
    991     {{else if eq $.Name "vkGetPhysicalDeviceProperties2KHR"}}true
    992 
    993     {{/* VK_KHR_swapchain v69 requirement */}}
    994     {{else if eq $.Name "vkBindImageMemory2"}}true
    995     {{else if eq $.Name "vkBindImageMemory2KHR"}}true
    996     {{end}}
    997 
    998     {{$ext := GetAnnotation $ "extension"}}
    999     {{if $ext}}
   1000       {{$ext_name := index $ext.Arguments 0}}
   1001       {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
   1002       {{else if eq $ext_name "VK_EXT_debug_report"}}true
   1003       {{end}}
   1004     {{end}}
   1005   {{end}}
   1006 {{end}}
   1007 
   1008 
   1009 {{/*
   1010 ------------------------------------------------------------------------------
   1011   Emits true if an instance-dispatched function is needed by vulkan::driver.
   1012 ------------------------------------------------------------------------------
   1013 */}}
   1014 {{define "driver.IsInstanceDriverTableEntry"}}
   1015   {{AssertType $ "Function"}}
   1016 
   1017   {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
   1018     true
   1019   {{end}}
   1020 {{end}}
   1021 
   1022 
   1023 {{/*
   1024 ------------------------------------------------------------------------------
   1025   Emits true if a device-dispatched function is needed by vulkan::driver.
   1026 ------------------------------------------------------------------------------
   1027 */}}
   1028 {{define "driver.IsDeviceDriverTableEntry"}}
   1029   {{AssertType $ "Function"}}
   1030 
   1031   {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
   1032     true
   1033   {{end}}
   1034 {{end}}
   1035 
   1036 
   1037 {{/*
   1038 -------------------------------------------------------------------------------
   1039   Emits a function/extension name without the "vk"/"VK_" prefix.
   1040 -------------------------------------------------------------------------------
   1041 */}}
   1042 {{define "BaseName"}}
   1043   {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
   1044   {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
   1045   {{else}}{{Error "invalid use of BaseName"}}
   1046   {{end}}
   1047 {{end}}
   1048 
   1049 
   1050 {{/*
   1051 -------------------------------------------------------------------------------
   1052   Emits a comma-separated list of C parameter names for the given command.
   1053 -------------------------------------------------------------------------------
   1054 */}}
   1055 {{define "Arguments"}}
   1056   {{AssertType $ "Function"}}
   1057 
   1058   {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
   1059 {{end}}
   1060 
   1061 
   1062 {{/*
   1063 ------------------------------------------------------------------------------
   1064 ------------------------------------------------------------------------------
   1065 */}}
   1066 {{define "IsGloballyDispatched"}}
   1067   {{AssertType $ "Function"}}
   1068   {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
   1069     true
   1070   {{end}}
   1071 {{end}}
   1072 
   1073 
   1074 {{/*
   1075 ------------------------------------------------------------------------------
   1076   Emit "true" for supported functions that undergo table dispatch. Only global
   1077   functions and functions handled in the loader top without calling into
   1078   lower layers are not dispatched.
   1079 ------------------------------------------------------------------------------
   1080 */}}
   1081 {{define "IsInstanceDispatched"}}
   1082   {{AssertType $ "Function"}}
   1083   {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
   1084     true
   1085   {{end}}
   1086 {{end}}
   1087 
   1088 
   1089 {{/*
   1090 ------------------------------------------------------------------------------
   1091   Emit "true" for supported functions that can have device-specific dispatch.
   1092 ------------------------------------------------------------------------------
   1093 */}}
   1094 {{define "IsDeviceDispatched"}}
   1095   {{AssertType $ "Function"}}
   1096   {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
   1097     true
   1098   {{end}}
   1099 {{end}}
   1100 
   1101 
   1102 {{/*
   1103 ------------------------------------------------------------------------------
   1104   Emit "true" if a function is core or from a supportable extension.
   1105 ------------------------------------------------------------------------------
   1106 */}}
   1107 {{define "IsFunctionSupported"}}
   1108   {{AssertType $ "Function"}}
   1109   {{if not (GetAnnotation $ "pfn")}}
   1110     {{$ext := GetAnnotation $ "extension"}}
   1111     {{if not $ext}}true
   1112     {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
   1113     {{end}}
   1114   {{end}}
   1115 {{end}}
   1116 
   1117 
   1118 {{/*
   1119 ------------------------------------------------------------------------------
   1120   Decides whether a function should be exported from the Android Vulkan
   1121   library. Functions in the core API and in loader extensions are exported.
   1122 ------------------------------------------------------------------------------
   1123 */}}
   1124 {{define "IsFunctionExported"}}
   1125   {{AssertType $ "Function"}}
   1126 
   1127   {{if (Macro "IsFunctionSupported" $)}}
   1128     {{$ext := GetAnnotation $ "extension"}}
   1129     {{if $ext}}
   1130       {{Macro "IsExtensionExported" $ext}}
   1131     {{else}}
   1132       true
   1133     {{end}}
   1134   {{end}}
   1135 {{end}}
   1136 
   1137 
   1138 {{/*
   1139 ------------------------------------------------------------------------------
   1140   Emit "true" if an extension is unsupportable on Android.
   1141 ------------------------------------------------------------------------------
   1142 */}}
   1143 {{define "IsExtensionBlacklisted"}}
   1144   {{$ext := index $.Arguments 0}}
   1145   {{     if eq $ext "VK_KHR_display"}}true
   1146   {{else if eq $ext "VK_KHR_display_swapchain"}}true
   1147   {{else if eq $ext "VK_KHR_mir_surface"}}true
   1148   {{else if eq $ext "VK_KHR_xcb_surface"}}true
   1149   {{else if eq $ext "VK_KHR_xlib_surface"}}true
   1150   {{else if eq $ext "VK_KHR_wayland_surface"}}true
   1151   {{else if eq $ext "VK_KHR_win32_surface"}}true
   1152   {{else if eq $ext "VK_KHR_external_memory_win32"}}true
   1153   {{else if eq $ext "VK_KHR_win32_keyed_mutex"}}true
   1154   {{else if eq $ext "VK_KHR_external_semaphore_win32"}}true
   1155   {{else if eq $ext "VK_KHR_external_fence_win32"}}true
   1156   {{else if eq $ext "VK_EXT_acquire_xlib_display"}}true
   1157   {{else if eq $ext "VK_EXT_direct_mode_display"}}true
   1158   {{else if eq $ext "VK_EXT_display_surface_counter"}}true
   1159   {{else if eq $ext "VK_EXT_display_control"}}true
   1160   {{else if eq $ext "VK_FUCHSIA_imagepipe_surface"}}true
   1161   {{else if eq $ext "VK_MVK_ios_surface"}}true
   1162   {{else if eq $ext "VK_MVK_macos_surface"}}true
   1163   {{else if eq $ext "VK_NN_vi_surface"}}true
   1164   {{else if eq $ext "VK_NV_external_memory_win32"}}true
   1165   {{else if eq $ext "VK_NV_win32_keyed_mutex"}}true
   1166   {{end}}
   1167 {{end}}
   1168 
   1169 
   1170 {{/*
   1171 ------------------------------------------------------------------------------
   1172   Reports whether an extension has functions exported by the loader.
   1173   E.g. applications can directly link to an extension function.
   1174 ------------------------------------------------------------------------------
   1175 */}}
   1176 {{define "IsExtensionExported"}}
   1177   {{$ext := index $.Arguments 0}}
   1178   {{     if eq $ext "VK_KHR_surface"}}true
   1179   {{else if eq $ext "VK_KHR_swapchain"}}true
   1180   {{else if eq $ext "VK_KHR_android_surface"}}true
   1181   {{else if eq $ext "VK_ANDROID_external_memory_android_hardware_buffer"}}true
   1182   {{end}}
   1183 {{end}}
   1184 
   1185 
   1186 {{/*
   1187 ------------------------------------------------------------------------------
   1188   Reports whether an extension is internal to the loader and drivers,
   1189   so the loader should not enumerate it.
   1190 ------------------------------------------------------------------------------
   1191 */}}
   1192 {{define "IsExtensionInternal"}}
   1193   {{$ext := index $.Arguments 0}}
   1194   {{     if eq $ext "VK_ANDROID_native_buffer"}}true
   1195   {{end}}
   1196 {{end}}
   1197