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