code-generator.tmpl revision eb7db124e46da9a9210cf868353f5ea79502ffec
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"}}
3435// WARNING: This file is generated. See ../README.md for instructions.
3637#ifndef LIBVULKAN_API_GEN_H
38#define LIBVULKAN_API_GEN_H
3940#include <vulkan/vulkan.h>
4142namespace vulkan {«
43namespace api {«
4445struct InstanceDispatchTable {
46  // clang-format off
47  {{range $f := AllCommands $}}
48    {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
49      {{Macro "C++.DeclareDispatchTableEntry" $f}};
50    {{end}}
51  {{end}}
52  // clang-format on
53};
5455struct DeviceDispatchTable {
56  // clang-format off
57  {{range $f := AllCommands $}}
58    {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
59      {{Macro "C++.DeclareDispatchTableEntry" $f}};
60    {{end}}
61  {{end}}
62  // clang-format on
63};
6465bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc);
66bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc);
6768»} // namespace api
69»} // namespace vulkan
7071#endif // LIBVULKAN_API_GEN_H
72¶{{end}}
73
74
75{{/*
76-------------------------------------------------------------------------------
77  api_gen.cpp
78-------------------------------------------------------------------------------
79*/}}
80{{define "api_gen.cpp"}}
81{{Macro "Copyright"}}
8283// WARNING: This file is generated. See ../README.md for instructions.
8485#include <string.h>
86#include <algorithm>
87#include <log/log.h>
8889#include "api.h"
9091namespace vulkan {«
92namespace api {«
9394{{Macro "C++.DefineInitProcMacros" "dispatch"}}
9596bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc) {
97    auto& data = GetData(instance);
98    bool success = true;
99100    // clang-format off
101    {{range $f := AllCommands $}}
102      {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
103        {{Macro "C++.InitProc" $f}}
104      {{end}}
105    {{end}}
106    // clang-format on
107108    return success;
109}
110111bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc) {
112    auto& data = GetData(dev);
113    bool success = true;
114115    // clang-format off
116    {{range $f := AllCommands $}}
117      {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
118        {{Macro "C++.InitProc" $f}}
119      {{end}}
120    {{end}}
121    // clang-format on
122123    return success;
124}
125126»} // namespace api
127»} // namespace vulkan
128129// clang-format off
130131{{range $f := AllCommands $}}
132  {{if (Macro "IsFunctionExported" $f)}}
133    __attribute__((visibility("default")))
134    VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
135      {{     if eq $f.Name "vkGetInstanceProcAddr"}}
136        {{Macro "api.C++.InterceptInstanceProcAddr" $}}
137      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
138        {{Macro "api.C++.InterceptDeviceProcAddr" $}}
139      {{end}}
140
141      {{Macro "api.C++.Dispatch" $f}}
142    }
143144  {{end}}
145{{end}}
146147// clang-format on
148¶{{end}}
149
150
151{{/*
152-------------------------------------------------------------------------------
153  driver_gen.h
154-------------------------------------------------------------------------------
155*/}}
156{{define "driver_gen.h"}}
157{{Macro "Copyright"}}
158159// WARNING: This file is generated. See ../README.md for instructions.
160161#ifndef LIBVULKAN_DRIVER_GEN_H
162#define LIBVULKAN_DRIVER_GEN_H
163164#include <vulkan/vulkan.h>
165#include <vulkan/vk_android_native_buffer.h>
166167namespace vulkan {«
168namespace driver {«
169170{{Macro "driver.C++.DefineProcHookType"}}
171172const ProcHook* GetProcHook(const char* name);
173ProcHook::Extension GetProcHookExtension(const char* name);
174175»} // namespace driver
176»} // namespace vulkan
177178#endif // LIBVULKAN_DRIVER_TABLE_H
179¶{{end}}
180
181
182{{/*
183-------------------------------------------------------------------------------
184  driver_gen.cpp
185-------------------------------------------------------------------------------
186*/}}
187{{define "driver_gen.cpp"}}
188{{Macro "Copyright"}}
189190// WARNING: This file is generated. See ../README.md for instructions.
191192#include <string.h>
193#include <algorithm>
194#include <log/log.h>
195196#include "driver.h"
197#include "loader.h"
198199namespace vulkan {«
200namespace driver {«
201202namespace {«
203204// clang-format off
205206{{range $f := AllCommands $}}
207  {{Macro "driver.C++.DefineProcHookStubs" $f}}
208{{end}}
209// clang-format on
210211const ProcHook g_proc_hooks[] = {
212  // clang-format off
213  {{range $f := SortBy (AllCommands $) "FunctionName"}}
214    {{if (Macro "driver.IsIntercepted" $f)}}
215      {{     if (Macro "IsGloballyDispatched" $f)}}
216        {{Macro "driver.C++.DefineGlobalProcHook" $f}}
217      {{else if (Macro "IsInstanceDispatched" $f)}}
218        {{Macro "driver.C++.DefineInstanceProcHook" $f}}
219      {{else if (Macro "IsDeviceDispatched" $f)}}
220        {{Macro "driver.C++.DefineDeviceProcHook" $f}}
221      {{end}}
222    {{end}}
223  {{end}}
224  // clang-format on
225};
226227»} // anonymous
228229const ProcHook* GetProcHook(const char* name) {
230    const auto& begin = g_proc_hooks;
231    const auto& end = g_proc_hooks +
232      sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
233    const auto hook = std::lower_bound(begin, end, name,
234        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
235    return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
236}
237238ProcHook::Extension GetProcHookExtension(const char* name) {
239  {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
240  // clang-format off
241  {{range $e := $exts}}
242    if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
243  {{end}}
244  // clang-format on
245  return ProcHook::EXTENSION_UNKNOWN;
246}
247248»} // namespace driver
249»} // namespace vulkan
250251// clang-format on
252¶{{end}}
253
254
255{{/*
256------------------------------------------------------------------------------
257  Emits a declaration of a dispatch table entry.
258------------------------------------------------------------------------------
259*/}}
260{{define "C++.DeclareDispatchTableEntry"}}
261  {{AssertType $ "Function"}}
262
263  {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
264{{end}}
265
266
267{{/*
268-------------------------------------------------------------------------------
269  Emits macros to help initialize dispatch tables.
270-------------------------------------------------------------------------------
271*/}}
272{{define "C++.DefineInitProcMacros"}}
273  #define UNLIKELY(expr) __builtin_expect((expr), 0)
274275  #define INIT_PROC(obj, proc) do {                             \
276      data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
277              get_proc(obj, "vk" # proc));                      \
278      if (UNLIKELY(!data.{{$}}.proc)) {                         \
279          ALOGE("missing " # obj " proc: vk" # proc);           \
280          success = false;                                      \
281      }                                                         \
282  } while(0)
283284  // TODO do we want to point to a stub or nullptr when ext is not enabled?
285  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
286      INIT_PROC(obj, proc);                                     \
287  } while(0)
288{{end}}
289
290
291{{/*
292-------------------------------------------------------------------------------
293  Emits code to invoke INIT_PROC or INIT_PROC_EXT.
294-------------------------------------------------------------------------------
295*/}}
296{{define "C++.InitProc"}}
297  {{AssertType $ "Function"}}
298
299  {{$ext := GetAnnotation $ "extension"}}
300  {{if $ext}}
301    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
302  {{else}}
303    INIT_PROC(§
304  {{end}}
305
306  {{if (Macro "IsInstanceDispatched" $)}}
307    instance, §
308  {{else}}
309    dev, §
310  {{end}}
311
312  {{Macro "BaseName" $}});
313{{end}}
314
315
316{{/*
317------------------------------------------------------------------------------
318  Emits true if a function is exported and instance-dispatched.
319------------------------------------------------------------------------------
320*/}}
321{{define "api.IsInstanceDispatchTableEntry"}}
322  {{AssertType $ "Function"}}
323
324  {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
325    true
326  {{end}}
327{{end}}
328
329
330{{/*
331------------------------------------------------------------------------------
332  Emits true if a function is exported and device-dispatched.
333------------------------------------------------------------------------------
334*/}}
335{{define "api.IsDeviceDispatchTableEntry"}}
336  {{AssertType $ "Function"}}
337
338  {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
339    true
340  {{end}}
341{{end}}
342
343
344{{/*
345------------------------------------------------------------------------------
346  Emits true if a function is intercepted by vulkan::api.
347------------------------------------------------------------------------------
348*/}}
349{{define "api.IsIntercepted"}}
350  {{AssertType $ "Function"}}
351
352  {{if (Macro "IsFunctionSupported" $)}}
353    {{/* Global functions cannot be dispatched at all */}}
354    {{     if (Macro "IsGloballyDispatched" $)}}true
355
356    {{/* VkPhysicalDevice functions that manage device layers */}}
357    {{else if eq $.Name "vkCreateDevice"}}true
358    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
359    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
360
361    {{/* Destroy functions of dispatchable objects */}}
362    {{else if eq $.Name "vkDestroyInstance"}}true
363    {{else if eq $.Name "vkDestroyDevice"}}true
364
365    {{end}}
366  {{end}}
367{{end}}
368
369
370{{/*
371------------------------------------------------------------------------------
372  Emits code for vkGetInstanceProcAddr for function interception.
373------------------------------------------------------------------------------
374*/}}
375{{define "api.C++.InterceptInstanceProcAddr"}}
376  {{AssertType $ "API"}}
377
378  // global functions
379  if (!instance) {
380    {{range $f := AllCommands $}}
381      {{if (Macro "IsGloballyDispatched" $f)}}
382        if (strcmp(pName, "{{$f.Name}}") == 0) return §
383          reinterpret_cast<PFN_vkVoidFunction>(§
384            vulkan::api::{{Macro "BaseName" $f}});
385      {{end}}
386    {{end}}
387388    ALOGE("vkGetInstanceProcAddr called with %s without instance",  pName);
389    return nullptr;
390  }
391392  static const struct Hook {
393    const char* name;
394    PFN_vkVoidFunction proc;
395  } hooks[] = {
396    {{range $f := SortBy (AllCommands $) "FunctionName"}}
397      {{if (Macro "IsFunctionExported" $f)}}
398        {{/* hide global functions */}}
399        {{if (Macro "IsGloballyDispatched" $f)}}
400          { "{{$f.Name}}", nullptr },
401
402        {{/* redirect intercepted functions */}}
403        {{else if (Macro "api.IsIntercepted" $f)}}
404          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
405            vulkan::api::{{Macro "BaseName" $f}}) },
406
407        {{/* redirect vkGetInstanceProcAddr to itself */}}
408        {{else if eq $f.Name "vkGetInstanceProcAddr"}}
409          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
410
411        {{/* redirect device functions to themselves as a workaround for
412             layers that do not intercept in their vkGetInstanceProcAddr */}}
413        {{else if (Macro "IsDeviceDispatched" $f)}}
414          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
415
416        {{end}}
417      {{end}}
418    {{end}}
419  };
420  // clang-format on
421  constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
422  auto hook = std::lower_bound(
423    hooks, hooks + count, pName,
424    [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
425  if (hook <  hooks + count && strcmp(hook->name, pName) == 0) {
426    if (!hook->proc)
427      ALOGE("vkGetInstanceProcAddr called with %s with instance",  pName);
428    return hook->proc;
429  }
430  // clang-format off
431432{{end}}
433
434
435{{/*
436------------------------------------------------------------------------------
437  Emits code for vkGetDeviceProcAddr for function interception.
438------------------------------------------------------------------------------
439*/}}
440{{define "api.C++.InterceptDeviceProcAddr"}}
441  {{AssertType $ "API"}}
442
443  if (device == VK_NULL_HANDLE) {
444    ALOGE("vkGetDeviceProcAddr called with invalid device");
445    return nullptr;
446  }
447448  static const char* const known_non_device_names[] = {
449    {{range $f := SortBy (AllCommands $) "FunctionName"}}
450      {{if (Macro "IsFunctionSupported" $f)}}
451        {{if not (Macro "IsDeviceDispatched" $f)}}
452          "{{$f.Name}}",
453        {{end}}
454      {{end}}
455    {{end}}
456  };
457  // clang-format on
458  constexpr size_t count = sizeof(known_non_device_names) /
459    sizeof(known_non_device_names[0]);
460  if (!pName ||
461      std::binary_search(
462        known_non_device_names, known_non_device_names + count, pName,
463        [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
464    ALOGE("vkGetDeviceProcAddr called with %s", pName);
465    return nullptr;
466  }
467  // clang-format off
468469{{end}}
470
471
472{{/*
473------------------------------------------------------------------------------
474  Emits code to dispatch a function.
475------------------------------------------------------------------------------
476*/}}
477{{define "api.C++.Dispatch"}}
478  {{AssertType $ "Function"}}
479
480  {{if (Macro "api.IsIntercepted" $)}}// call into api.cpp{{end}}
481  {{if not (IsVoid $.Return.Type)}}return §{{end}}
482
483  {{if (Macro "api.IsIntercepted" $)}}
484    vulkan::api::§
485  {{else}}
486    {{$p0 := index $.CallParameters 0}}
487    vulkan::api::GetData({{$p0.Name}}).dispatch.§
488  {{end}}
489
490  {{Macro "BaseName" $}}({{Macro "Arguments" $}});
491{{end}}
492
493
494{{/*
495------------------------------------------------------------------------------
496  Emits a list of extensions intercepted by vulkan::driver.
497------------------------------------------------------------------------------
498*/}}
499{{define "driver.InterceptedExtensions"}}
500VK_ANDROID_native_buffer
501VK_EXT_debug_report
502VK_KHR_android_surface
503VK_KHR_surface
504VK_KHR_swapchain
505{{end}}
506
507
508{{/*
509------------------------------------------------------------------------------
510  Emits true if an extension is intercepted by vulkan::driver.
511------------------------------------------------------------------------------
512*/}}
513{{define "driver.IsExtensionIntercepted"}}
514  {{$ext_name := index $.Arguments 0}}
515  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
516
517  {{range $f := $filters}}
518    {{if eq $ext_name $f}}true{{end}}
519  {{end}}
520{{end}}
521
522
523{{/*
524------------------------------------------------------------------------------
525  Emits true if a function is intercepted by vulkan::driver.
526------------------------------------------------------------------------------
527*/}}
528{{define "driver.IsIntercepted"}}
529  {{AssertType $ "Function"}}
530
531  {{if (Macro "IsFunctionSupported" $)}}
532    {{/* Create functions of dispatchable objects */}}
533    {{     if eq $.Name "vkCreateInstance"}}true
534    {{else if eq $.Name "vkCreateDevice"}}true
535    {{else if eq $.Name "vkGetDeviceQueue"}}true
536    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
537
538    {{/* Destroy functions of dispatchable objects */}}
539    {{else if eq $.Name "vkDestroyInstance"}}true
540    {{else if eq $.Name "vkDestroyDevice"}}true
541
542    {{/* Enumeration of extensions */}}
543    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
544    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
545
546    {{/* We cache physical devices in loader.cpp */}}
547    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
548
549    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
550    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
551
552    {{end}}
553
554    {{$ext := GetAnnotation $ "extension"}}
555    {{if $ext}}
556      {{Macro "driver.IsExtensionIntercepted" $ext}}
557    {{end}}
558
559  {{end}}
560{{end}}
561
562
563{{/*
564------------------------------------------------------------------------------
565  Emits true if a function needs ProcHook stubs.
566------------------------------------------------------------------------------
567*/}}
568{{define "driver.NeedProcHookStubs"}}
569  {{AssertType $ "Function"}}
570
571  {{if (Macro "driver.IsIntercepted" $)}}
572    {{$ext := GetAnnotation $ "extension"}}
573    {{if $ext}}
574      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
575    {{end}}
576  {{end}}
577{{end}}
578
579
580{{/*
581-------------------------------------------------------------------------------
582  Emits definition of struct ProcHook.
583-------------------------------------------------------------------------------
584*/}}
585{{define "driver.C++.DefineProcHookType"}}
586  struct ProcHook {
587      enum Type {
588        GLOBAL,
589        INSTANCE,
590        DEVICE,
591      };
592
593      enum Extension {
594        {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
595        {{range $e := $exts}}
596          {{TrimPrefix "VK_" $e}},
597        {{end}}
598599        EXTENSION_CORE, // valid bit
600        EXTENSION_COUNT,
601        EXTENSION_UNKNOWN,
602      };
603604      const char* name;
605      Type type;
606      Extension extension;
607608      PFN_vkVoidFunction proc;
609      PFN_vkVoidFunction disabled_proc; // nullptr for global hooks
610      PFN_vkVoidFunction checked_proc;  // nullptr for global/instance hooks
611  };
612{{end}}
613
614
615{{/*
616-------------------------------------------------------------------------------
617  Emits definitions of stub functions for ProcHook.
618-------------------------------------------------------------------------------
619*/}}
620{{define "driver.C++.DefineProcHookStubs"}}
621  {{AssertType $ "Function"}}
622
623  {{if (Macro "driver.NeedProcHookStubs" $)}}
624    {{$ext := GetAnnotation $ "extension"}}
625    {{$ext_name := index $ext.Arguments 0}}
626
627    {{$base := (Macro "BaseName" $)}}
628    {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
629
630    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$unnamed_params}}) {
631      ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
632      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
633    }
634    {{if (Macro "IsDeviceDispatched" $)}}
635636      VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
637        {{if not (IsVoid $.Return.Type)}}return §{{end}}
638
639        {{$p0 := index $.CallParameters 0}}
640        {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
641        (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) ? §
642          {{$base}}_Bottom({{Macro "Arguments" $}}) : §
643          disabled{{$base}}({{Macro "Arguments" $}});
644      }
645    {{end}}
646647  {{end}}
648{{end}}
649
650
651{{/*
652-------------------------------------------------------------------------------
653  Emits definition of a global ProcHook.
654-------------------------------------------------------------------------------
655*/}}
656{{define "driver.C++.DefineGlobalProcHook"}}
657  {{AssertType $ "Function"}}
658
659  {{$base := (Macro "BaseName" $)}}
660
661  {{$ext := GetAnnotation $ "extension"}}
662  {{if $ext}}
663    {{Error "invalid global extension"}}
664  {{end}}
665
666  {
667    "{{$.Name}}",
668    ProcHook::GLOBAL,
669    ProcHook::EXTENSION_CORE,
670    {{if eq $.Name "vkEnumerateInstanceExtensionProperties"}}
671      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
672    {{else}}
673      reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
674    {{end}}
675    nullptr,
676    nullptr,
677  },
678{{end}}
679
680
681{{/*
682-------------------------------------------------------------------------------
683  Emits definition of an instance ProcHook.
684-------------------------------------------------------------------------------
685*/}}
686{{define "driver.C++.DefineInstanceProcHook"}}
687  {{AssertType $ "Function"}}
688
689  {{$base := (Macro "BaseName" $)}}
690
691  {
692    "{{$.Name}}",
693    ProcHook::INSTANCE,
694
695    {{$ext := GetAnnotation $ "extension"}}
696    {{if $ext}}
697      ProcHook::{{Macro "BaseName" $ext}},
698
699      {{if (Macro "IsExtensionInternal" $ext)}}
700        nullptr,
701        nullptr,
702        nullptr,
703      {{else}}
704        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
705        reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
706        nullptr,
707      {{end}}
708    {{else}}
709      ProcHook::EXTENSION_CORE,
710
711      {{if eq $.Name "vkGetInstanceProcAddr"}}
712        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
713      {{else}}
714        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
715      {{end}}
716      nullptr,
717      nullptr,
718    {{end}}
719  },
720{{end}}
721
722
723{{/*
724-------------------------------------------------------------------------------
725  Emits definition of a device ProcHook.
726-------------------------------------------------------------------------------
727*/}}
728{{define "driver.C++.DefineDeviceProcHook"}}
729  {{AssertType $ "Function"}}
730
731  {{$base := (Macro "BaseName" $)}}
732
733  {
734    "{{$.Name}}",
735    ProcHook::DEVICE,
736
737    {{$ext := GetAnnotation $ "extension"}}
738    {{if $ext}}
739      ProcHook::{{Macro "BaseName" $ext}},
740
741      {{if (Macro "IsExtensionInternal" $ext)}}
742        nullptr,
743        nullptr,
744        nullptr,
745      {{else}}
746        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
747        reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
748        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
749      {{end}}
750    {{else}}
751        ProcHook::EXTENSION_CORE,
752
753        {{if eq $.Name "vkGetDeviceProcAddr"}}
754          reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
755        {{else}}
756          reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
757        {{end}}
758        nullptr,
759        nullptr,
760    {{end}}
761  },
762{{end}}
763
764
765{{/*
766-------------------------------------------------------------------------------
767  Emits a function/extension name without the "vk"/"VK_" prefix.
768-------------------------------------------------------------------------------
769*/}}
770{{define "BaseName"}}
771  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
772  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
773  {{else}}{{Error "invalid use of BaseName"}}
774  {{end}}
775{{end}}
776
777
778{{/*
779-------------------------------------------------------------------------------
780  Emits a comma-separated list of C parameter names for the given command.
781-------------------------------------------------------------------------------
782*/}}
783{{define "Arguments"}}
784  {{AssertType $ "Function"}}
785
786  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
787{{end}}
788
789
790{{/*
791------------------------------------------------------------------------------
792------------------------------------------------------------------------------
793*/}}
794{{define "IsGloballyDispatched"}}
795  {{AssertType $ "Function"}}
796  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
797    true
798  {{end}}
799{{end}}
800
801
802{{/*
803------------------------------------------------------------------------------
804  Emit "true" for supported functions that undergo table dispatch. Only global
805  functions and functions handled in the loader top without calling into
806  lower layers are not dispatched.
807------------------------------------------------------------------------------
808*/}}
809{{define "IsInstanceDispatched"}}
810  {{AssertType $ "Function"}}
811  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
812    true
813  {{end}}
814{{end}}
815
816
817{{/*
818------------------------------------------------------------------------------
819  Emit "true" for supported functions that can have device-specific dispatch.
820------------------------------------------------------------------------------
821*/}}
822{{define "IsDeviceDispatched"}}
823  {{AssertType $ "Function"}}
824  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
825    true
826  {{end}}
827{{end}}
828
829
830{{/*
831------------------------------------------------------------------------------
832  Emit "true" if a function is core or from a supportable extension.
833------------------------------------------------------------------------------
834*/}}
835{{define "IsFunctionSupported"}}
836  {{AssertType $ "Function"}}
837  {{if not (GetAnnotation $ "pfn")}}
838    {{$ext := GetAnnotation $ "extension"}}
839    {{if not $ext}}true
840    {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
841    {{end}}
842  {{end}}
843{{end}}
844
845
846{{/*
847------------------------------------------------------------------------------
848  Decides whether a function should be exported from the Android Vulkan
849  library. Functions in the core API and in loader extensions are exported.
850------------------------------------------------------------------------------
851*/}}
852{{define "IsFunctionExported"}}
853  {{AssertType $ "Function"}}
854
855  {{if (Macro "IsFunctionSupported" $)}}
856    {{$ext := GetAnnotation $ "extension"}}
857    {{if $ext}}
858      {{Macro "IsExtensionExported" $ext}}
859    {{else}}
860      true
861    {{end}}
862  {{end}}
863{{end}}
864
865
866{{/*
867------------------------------------------------------------------------------
868  Emit "true" if an extension is unsupportable on Android.
869------------------------------------------------------------------------------
870*/}}
871{{define "IsExtensionBlacklisted"}}
872  {{$ext := index $.Arguments 0}}
873  {{     if eq $ext "VK_KHR_display"}}true
874  {{else if eq $ext "VK_KHR_display_swapchain"}}true
875  {{else if eq $ext "VK_KHR_xlib_surface"}}true
876  {{else if eq $ext "VK_KHR_xcb_surface"}}true
877  {{else if eq $ext "VK_KHR_wayland_surface"}}true
878  {{else if eq $ext "VK_KHR_mir_surface"}}true
879  {{else if eq $ext "VK_KHR_win32_surface"}}true
880  {{end}}
881{{end}}
882
883
884{{/*
885------------------------------------------------------------------------------
886  Reports whether an extension is implemented entirely by the loader,
887  so drivers should not enumerate it.
888------------------------------------------------------------------------------
889*/}}
890{{define "IsExtensionExported"}}
891  {{$ext := index $.Arguments 0}}
892  {{     if eq $ext "VK_KHR_surface"}}true
893  {{else if eq $ext "VK_KHR_swapchain"}}true
894  {{else if eq $ext "VK_KHR_android_surface"}}true
895  {{end}}
896{{end}}
897
898
899{{/*
900------------------------------------------------------------------------------
901  Reports whether an extension is internal to the loader and drivers,
902  so the loader should not enumerate it.
903------------------------------------------------------------------------------
904*/}}
905{{define "IsExtensionInternal"}}
906  {{$ext := index $.Arguments 0}}
907  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
908  {{end}}
909{{end}}
910