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