code-generator.tmpl revision ba0be41afe39dcbed0a712a32d1ab6c341797007
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}}
796        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
797      {{end}}
798      nullptr,
799      nullptr,
800    {{end}}
801  },
802{{end}}
803
804
805{{/*
806-------------------------------------------------------------------------------
807  Emits definition of a device ProcHook.
808-------------------------------------------------------------------------------
809*/}}
810{{define "driver.C++.DefineDeviceProcHook"}}
811  {{AssertType $ "Function"}}
812
813  {{$base := (Macro "BaseName" $)}}
814
815  {
816    "{{$.Name}}",
817    ProcHook::DEVICE,
818
819    {{$ext := GetAnnotation $ "extension"}}
820    {{if $ext}}
821      ProcHook::{{Macro "BaseName" $ext}},
822
823      {{if (Macro "IsExtensionInternal" $ext)}}
824        nullptr,
825        nullptr,
826        nullptr,
827      {{else}}
828        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
829        reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
830        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
831      {{end}}
832    {{else}}
833        ProcHook::EXTENSION_CORE,
834
835        {{if eq $.Name "vkGetDeviceProcAddr"}}
836          reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
837        {{else if eq $.Name "vkGetDeviceQueue"}}
838          reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
839        {{else}}
840          reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
841        {{end}}
842        nullptr,
843        nullptr,
844    {{end}}
845  },
846{{end}}
847
848
849{{/*
850-------------------------------------------------------------------------------
851  Emits true if a function is needed by vulkan::driver.
852-------------------------------------------------------------------------------
853*/}}
854{{define "driver.IsDriverTableEntry"}}
855  {{AssertType $ "Function"}}
856
857  {{if (Macro "IsFunctionSupported" $)}}
858    {{/* Create functions of dispatchable objects */}}
859    {{     if eq $.Name "vkCreateDevice"}}true
860    {{else if eq $.Name "vkGetDeviceQueue"}}true
861    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
862
863    {{/* Destroy functions of dispatchable objects */}}
864    {{else if eq $.Name "vkDestroyInstance"}}true
865    {{else if eq $.Name "vkDestroyDevice"}}true
866
867    {{/* Enumeration of extensions */}}
868    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
869
870    {{/* We cache physical devices in loader.cpp */}}
871    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
872
873    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
874    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
875
876    {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
877    {{else if eq $.Name "vkCreateImage"}}true
878    {{else if eq $.Name "vkDestroyImage"}}true
879
880    {{end}}
881
882    {{$ext := GetAnnotation $ "extension"}}
883    {{if $ext}}
884      {{$ext_name := index $ext.Arguments 0}}
885      {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
886      {{else if eq $ext_name "VK_EXT_debug_report"}}true
887      {{end}}
888    {{end}}
889  {{end}}
890{{end}}
891
892
893{{/*
894------------------------------------------------------------------------------
895  Emits true if an instance-dispatched function is needed by vulkan::driver.
896------------------------------------------------------------------------------
897*/}}
898{{define "driver.IsInstanceDriverTableEntry"}}
899  {{AssertType $ "Function"}}
900
901  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
902    true
903  {{end}}
904{{end}}
905
906
907{{/*
908------------------------------------------------------------------------------
909  Emits true if a device-dispatched function is needed by vulkan::driver.
910------------------------------------------------------------------------------
911*/}}
912{{define "driver.IsDeviceDriverTableEntry"}}
913  {{AssertType $ "Function"}}
914
915  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
916    true
917  {{end}}
918{{end}}
919
920
921{{/*
922-------------------------------------------------------------------------------
923  Emits a function/extension name without the "vk"/"VK_" prefix.
924-------------------------------------------------------------------------------
925*/}}
926{{define "BaseName"}}
927  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
928  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
929  {{else}}{{Error "invalid use of BaseName"}}
930  {{end}}
931{{end}}
932
933
934{{/*
935-------------------------------------------------------------------------------
936  Emits a comma-separated list of C parameter names for the given command.
937-------------------------------------------------------------------------------
938*/}}
939{{define "Arguments"}}
940  {{AssertType $ "Function"}}
941
942  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
943{{end}}
944
945
946{{/*
947------------------------------------------------------------------------------
948------------------------------------------------------------------------------
949*/}}
950{{define "IsGloballyDispatched"}}
951  {{AssertType $ "Function"}}
952  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
953    true
954  {{end}}
955{{end}}
956
957
958{{/*
959------------------------------------------------------------------------------
960  Emit "true" for supported functions that undergo table dispatch. Only global
961  functions and functions handled in the loader top without calling into
962  lower layers are not dispatched.
963------------------------------------------------------------------------------
964*/}}
965{{define "IsInstanceDispatched"}}
966  {{AssertType $ "Function"}}
967  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
968    true
969  {{end}}
970{{end}}
971
972
973{{/*
974------------------------------------------------------------------------------
975  Emit "true" for supported functions that can have device-specific dispatch.
976------------------------------------------------------------------------------
977*/}}
978{{define "IsDeviceDispatched"}}
979  {{AssertType $ "Function"}}
980  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
981    true
982  {{end}}
983{{end}}
984
985
986{{/*
987------------------------------------------------------------------------------
988  Emit "true" if a function is core or from a supportable extension.
989------------------------------------------------------------------------------
990*/}}
991{{define "IsFunctionSupported"}}
992  {{AssertType $ "Function"}}
993  {{if not (GetAnnotation $ "pfn")}}
994    {{$ext := GetAnnotation $ "extension"}}
995    {{if not $ext}}true
996    {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
997    {{end}}
998  {{end}}
999{{end}}
1000
1001
1002{{/*
1003------------------------------------------------------------------------------
1004  Decides whether a function should be exported from the Android Vulkan
1005  library. Functions in the core API and in loader extensions are exported.
1006------------------------------------------------------------------------------
1007*/}}
1008{{define "IsFunctionExported"}}
1009  {{AssertType $ "Function"}}
1010
1011  {{if (Macro "IsFunctionSupported" $)}}
1012    {{$ext := GetAnnotation $ "extension"}}
1013    {{if $ext}}
1014      {{Macro "IsExtensionExported" $ext}}
1015    {{else}}
1016      true
1017    {{end}}
1018  {{end}}
1019{{end}}
1020
1021
1022{{/*
1023------------------------------------------------------------------------------
1024  Emit "true" if an extension is unsupportable on Android.
1025------------------------------------------------------------------------------
1026*/}}
1027{{define "IsExtensionBlacklisted"}}
1028  {{$ext := index $.Arguments 0}}
1029  {{     if eq $ext "VK_KHR_display"}}true
1030  {{else if eq $ext "VK_KHR_display_swapchain"}}true
1031  {{else if eq $ext "VK_KHR_xlib_surface"}}true
1032  {{else if eq $ext "VK_KHR_xcb_surface"}}true
1033  {{else if eq $ext "VK_KHR_wayland_surface"}}true
1034  {{else if eq $ext "VK_KHR_mir_surface"}}true
1035  {{else if eq $ext "VK_KHR_win32_surface"}}true
1036  {{end}}
1037{{end}}
1038
1039
1040{{/*
1041------------------------------------------------------------------------------
1042  Reports whether an extension is implemented entirely by the loader,
1043  so drivers should not enumerate it.
1044------------------------------------------------------------------------------
1045*/}}
1046{{define "IsExtensionExported"}}
1047  {{$ext := index $.Arguments 0}}
1048  {{     if eq $ext "VK_KHR_surface"}}true
1049  {{else if eq $ext "VK_KHR_swapchain"}}true
1050  {{else if eq $ext "VK_KHR_android_surface"}}true
1051  {{end}}
1052{{end}}
1053
1054
1055{{/*
1056------------------------------------------------------------------------------
1057  Reports whether an extension is internal to the loader and drivers,
1058  so the loader should not enumerate it.
1059------------------------------------------------------------------------------
1060*/}}
1061{{define "IsExtensionInternal"}}
1062  {{$ext := index $.Arguments 0}}
1063  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
1064  {{end}}
1065{{end}}
1066