code-generator.tmpl revision c56603e0b35e31c5f1cd134d6b916a16ff710504
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"
222223namespace vulkan {«
224namespace driver {«
225226namespace {«
227228// clang-format off
229230{{range $f := AllCommands $}}
231  {{Macro "driver.C++.DefineProcHookStubs" $f}}
232{{end}}
233// clang-format on
234235const ProcHook g_proc_hooks[] = {
236  // clang-format off
237  {{range $f := SortBy (AllCommands $) "FunctionName"}}
238    {{if (Macro "driver.IsIntercepted" $f)}}
239      {{     if (Macro "IsGloballyDispatched" $f)}}
240        {{Macro "driver.C++.DefineGlobalProcHook" $f}}
241      {{else if (Macro "IsInstanceDispatched" $f)}}
242        {{Macro "driver.C++.DefineInstanceProcHook" $f}}
243      {{else if (Macro "IsDeviceDispatched" $f)}}
244        {{Macro "driver.C++.DefineDeviceProcHook" $f}}
245      {{end}}
246    {{end}}
247  {{end}}
248  // clang-format on
249};
250251»} // anonymous
252253const ProcHook* GetProcHook(const char* name) {
254    const auto& begin = g_proc_hooks;
255    const auto& end = g_proc_hooks +
256      sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
257    const auto hook = std::lower_bound(begin, end, name,
258        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
259    return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
260}
261262ProcHook::Extension GetProcHookExtension(const char* name) {
263  {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
264  // clang-format off
265  {{range $e := $exts}}
266    if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
267  {{end}}
268  // clang-format on
269  return ProcHook::EXTENSION_UNKNOWN;
270}
271272{{Macro "C++.DefineInitProcMacro" "driver"}}
273274{{Macro "driver.C++.DefineInitProcExtMacro"}}
275276bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc)
277{
278    auto& data = GetData(instance);
279    bool success = true;
280281    // clang-format off
282    {{range $f := AllCommands $}}
283      {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
284        {{Macro "C++.InitProc" $f}}
285      {{end}}
286    {{end}}
287    // clang-format on
288289    return success;
290}
291292bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc)
293{
294    auto& data = GetData(dev);
295    bool success = true;
296297    // clang-format off
298    {{range $f := AllCommands $}}
299      {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
300        {{Macro "C++.InitProc" $f}}
301      {{end}}
302    {{end}}
303    // clang-format on
304305    return success;
306}
307308»} // namespace driver
309»} // namespace vulkan
310311// clang-format on
312¶{{end}}
313
314
315{{/*
316------------------------------------------------------------------------------
317  Emits a declaration of a dispatch/driver table entry.
318------------------------------------------------------------------------------
319*/}}
320{{define "C++.DeclareTableEntry"}}
321  {{AssertType $ "Function"}}
322
323  {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
324{{end}}
325
326
327{{/*
328-------------------------------------------------------------------------------
329  Emits INIT_PROC macro.
330-------------------------------------------------------------------------------
331*/}}
332{{define "C++.DefineInitProcMacro"}}
333  #define UNLIKELY(expr) __builtin_expect((expr), 0)
334335  #define INIT_PROC(obj, proc) do {                             \
336      data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
337              get_proc(obj, "vk" # proc));                      \
338      if (UNLIKELY(!data.{{$}}.proc)) {                         \
339          ALOGE("missing " # obj " proc: vk" # proc);           \
340          success = false;                                      \
341      }                                                         \
342  } while(0)
343{{end}}
344
345
346{{/*
347-------------------------------------------------------------------------------
348  Emits code to invoke INIT_PROC or INIT_PROC_EXT.
349-------------------------------------------------------------------------------
350*/}}
351{{define "C++.InitProc"}}
352  {{AssertType $ "Function"}}
353
354  {{$ext := GetAnnotation $ "extension"}}
355  {{if $ext}}
356    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
357  {{else}}
358    INIT_PROC(§
359  {{end}}
360
361  {{if (Macro "IsInstanceDispatched" $)}}
362    instance, §
363  {{else}}
364    dev, §
365  {{end}}
366
367  {{Macro "BaseName" $}});
368{{end}}
369
370
371{{/*
372------------------------------------------------------------------------------
373  Emits true if a function is exported and instance-dispatched.
374------------------------------------------------------------------------------
375*/}}
376{{define "api.IsInstanceDispatchTableEntry"}}
377  {{AssertType $ "Function"}}
378
379  {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
380    true
381  {{end}}
382{{end}}
383
384
385{{/*
386------------------------------------------------------------------------------
387  Emits true if a function is exported and device-dispatched.
388------------------------------------------------------------------------------
389*/}}
390{{define "api.IsDeviceDispatchTableEntry"}}
391  {{AssertType $ "Function"}}
392
393  {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
394    true
395  {{end}}
396{{end}}
397
398
399{{/*
400------------------------------------------------------------------------------
401  Emits true if a function is intercepted by vulkan::api.
402------------------------------------------------------------------------------
403*/}}
404{{define "api.IsIntercepted"}}
405  {{AssertType $ "Function"}}
406
407  {{if (Macro "IsFunctionSupported" $)}}
408    {{/* Global functions cannot be dispatched at all */}}
409    {{     if (Macro "IsGloballyDispatched" $)}}true
410
411    {{/* VkPhysicalDevice functions that manage device layers */}}
412    {{else if eq $.Name "vkCreateDevice"}}true
413    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
414    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
415
416    {{/* Destroy functions of dispatchable objects */}}
417    {{else if eq $.Name "vkDestroyInstance"}}true
418    {{else if eq $.Name "vkDestroyDevice"}}true
419
420    {{end}}
421  {{end}}
422{{end}}
423
424
425{{/*
426-------------------------------------------------------------------------------
427  Emits INIT_PROC_EXT macro for vulkan::api.
428-------------------------------------------------------------------------------
429*/}}
430{{define "api.C++.DefineInitProcExtMacro"}}
431  // TODO do we want to point to a stub or nullptr when ext is not enabled?
432  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
433      INIT_PROC(obj, proc);                                     \
434  } while(0)
435{{end}}
436
437
438{{/*
439------------------------------------------------------------------------------
440  Emits code for vkGetInstanceProcAddr for function interception.
441------------------------------------------------------------------------------
442*/}}
443{{define "api.C++.InterceptInstanceProcAddr"}}
444  {{AssertType $ "API"}}
445
446  // global functions
447  if (!instance) {
448    {{range $f := AllCommands $}}
449      {{if (Macro "IsGloballyDispatched" $f)}}
450        if (strcmp(pName, "{{$f.Name}}") == 0) return §
451          reinterpret_cast<PFN_vkVoidFunction>(§
452            vulkan::api::{{Macro "BaseName" $f}});
453      {{end}}
454    {{end}}
455456    ALOGE("vkGetInstanceProcAddr called with %s without instance",  pName);
457    return nullptr;
458  }
459460  static const struct Hook {
461    const char* name;
462    PFN_vkVoidFunction proc;
463  } hooks[] = {
464    {{range $f := SortBy (AllCommands $) "FunctionName"}}
465      {{if (Macro "IsFunctionExported" $f)}}
466        {{/* hide global functions */}}
467        {{if (Macro "IsGloballyDispatched" $f)}}
468          { "{{$f.Name}}", nullptr },
469
470        {{/* redirect intercepted functions */}}
471        {{else if (Macro "api.IsIntercepted" $f)}}
472          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
473            vulkan::api::{{Macro "BaseName" $f}}) },
474
475        {{/* redirect vkGetInstanceProcAddr to itself */}}
476        {{else if eq $f.Name "vkGetInstanceProcAddr"}}
477          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
478
479        {{/* redirect device functions to themselves as a workaround for
480             layers that do not intercept in their vkGetInstanceProcAddr */}}
481        {{else if (Macro "IsDeviceDispatched" $f)}}
482          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
483
484        {{end}}
485      {{end}}
486    {{end}}
487  };
488  // clang-format on
489  constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
490  auto hook = std::lower_bound(
491    hooks, hooks + count, pName,
492    [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
493  if (hook <  hooks + count && strcmp(hook->name, pName) == 0) {
494    if (!hook->proc)
495      ALOGE("vkGetInstanceProcAddr called with %s with instance",  pName);
496    return hook->proc;
497  }
498  // clang-format off
499500{{end}}
501
502
503{{/*
504------------------------------------------------------------------------------
505  Emits code for vkGetDeviceProcAddr for function interception.
506------------------------------------------------------------------------------
507*/}}
508{{define "api.C++.InterceptDeviceProcAddr"}}
509  {{AssertType $ "API"}}
510
511  if (device == VK_NULL_HANDLE) {
512    ALOGE("vkGetDeviceProcAddr called with invalid device");
513    return nullptr;
514  }
515516  static const char* const known_non_device_names[] = {
517    {{range $f := SortBy (AllCommands $) "FunctionName"}}
518      {{if (Macro "IsFunctionSupported" $f)}}
519        {{if not (Macro "IsDeviceDispatched" $f)}}
520          "{{$f.Name}}",
521        {{end}}
522      {{end}}
523    {{end}}
524  };
525  // clang-format on
526  constexpr size_t count = sizeof(known_non_device_names) /
527    sizeof(known_non_device_names[0]);
528  if (!pName ||
529      std::binary_search(
530        known_non_device_names, known_non_device_names + count, pName,
531        [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
532    ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
533    return nullptr;
534  }
535  // clang-format off
536537  {{range $f := AllCommands $}}
538    {{if (Macro "IsDeviceDispatched" $f)}}
539      {{     if (Macro "api.IsIntercepted" $f)}}
540        if (strcmp(pName, "{{$f.Name}}") == 0) return §
541          reinterpret_cast<PFN_vkVoidFunction>(§
542            vulkan::api::{{Macro "BaseName" $f}});
543      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
544        if (strcmp(pName, "{{$f.Name}}") == 0) return §
545          reinterpret_cast<PFN_vkVoidFunction>(§
546            {{$f.Name}});
547      {{end}}
548    {{end}}
549  {{end}}
550551{{end}}
552
553
554{{/*
555------------------------------------------------------------------------------
556  Emits code to dispatch a function.
557------------------------------------------------------------------------------
558*/}}
559{{define "api.C++.Dispatch"}}
560  {{AssertType $ "Function"}}
561
562  {{if (Macro "api.IsIntercepted" $)}}// call into api.cpp{{end}}
563  {{if not (IsVoid $.Return.Type)}}return §{{end}}
564
565  {{if (Macro "api.IsIntercepted" $)}}
566    vulkan::api::§
567  {{else}}
568    {{$p0 := index $.CallParameters 0}}
569    vulkan::api::GetData({{$p0.Name}}).dispatch.§
570  {{end}}
571
572  {{Macro "BaseName" $}}({{Macro "Arguments" $}});
573{{end}}
574
575
576{{/*
577------------------------------------------------------------------------------
578  Emits a list of extensions intercepted by vulkan::driver.
579------------------------------------------------------------------------------
580*/}}
581{{define "driver.InterceptedExtensions"}}
582VK_ANDROID_native_buffer
583VK_EXT_debug_report
584VK_KHR_android_surface
585VK_KHR_surface
586VK_KHR_swapchain
587{{end}}
588
589
590{{/*
591------------------------------------------------------------------------------
592  Emits true if an extension is intercepted by vulkan::driver.
593------------------------------------------------------------------------------
594*/}}
595{{define "driver.IsExtensionIntercepted"}}
596  {{$ext_name := index $.Arguments 0}}
597  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
598
599  {{range $f := $filters}}
600    {{if eq $ext_name $f}}true{{end}}
601  {{end}}
602{{end}}
603
604
605{{/*
606------------------------------------------------------------------------------
607  Emits true if a function is intercepted by vulkan::driver.
608------------------------------------------------------------------------------
609*/}}
610{{define "driver.IsIntercepted"}}
611  {{AssertType $ "Function"}}
612
613  {{if (Macro "IsFunctionSupported" $)}}
614    {{/* Create functions of dispatchable objects */}}
615    {{     if eq $.Name "vkCreateInstance"}}true
616    {{else if eq $.Name "vkCreateDevice"}}true
617    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
618    {{else if eq $.Name "vkGetDeviceQueue"}}true
619    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
620
621    {{/* Destroy functions of dispatchable objects */}}
622    {{else if eq $.Name "vkDestroyInstance"}}true
623    {{else if eq $.Name "vkDestroyDevice"}}true
624
625    {{/* Enumeration of extensions */}}
626    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
627    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
628
629    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
630    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
631
632    {{end}}
633
634    {{$ext := GetAnnotation $ "extension"}}
635    {{if $ext}}
636      {{Macro "driver.IsExtensionIntercepted" $ext}}
637    {{end}}
638
639  {{end}}
640{{end}}
641
642
643{{/*
644------------------------------------------------------------------------------
645  Emits true if a function needs ProcHook stubs.
646------------------------------------------------------------------------------
647*/}}
648{{define "driver.NeedProcHookStubs"}}
649  {{AssertType $ "Function"}}
650
651  {{if (Macro "driver.IsIntercepted" $)}}
652    {{$ext := GetAnnotation $ "extension"}}
653    {{if $ext}}
654      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
655    {{end}}
656  {{end}}
657{{end}}
658
659
660{{/*
661-------------------------------------------------------------------------------
662  Emits definition of struct ProcHook.
663-------------------------------------------------------------------------------
664*/}}
665{{define "driver.C++.DefineProcHookType"}}
666  struct ProcHook {
667      enum Type {
668        GLOBAL,
669        INSTANCE,
670        DEVICE,
671      };
672
673      enum Extension {
674        {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
675        {{range $e := $exts}}
676          {{TrimPrefix "VK_" $e}},
677        {{end}}
678679        EXTENSION_CORE, // valid bit
680        EXTENSION_COUNT,
681        EXTENSION_UNKNOWN,
682      };
683684      const char* name;
685      Type type;
686      Extension extension;
687688      PFN_vkVoidFunction proc;
689      PFN_vkVoidFunction disabled_proc; // nullptr for global hooks
690      PFN_vkVoidFunction checked_proc;  // nullptr for global/instance hooks
691  };
692{{end}}
693
694
695{{/*
696-------------------------------------------------------------------------------
697  Emits INIT_PROC_EXT macro for vulkan::driver.
698-------------------------------------------------------------------------------
699*/}}
700{{define "driver.C++.DefineInitProcExtMacro"}}
701  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
702      if (data.hal_extensions[ProcHook::ext])           \
703        INIT_PROC(obj, proc);                                   \
704  } while(0)
705{{end}}
706
707
708{{/*
709-------------------------------------------------------------------------------
710  Emits definitions of stub functions for ProcHook.
711-------------------------------------------------------------------------------
712*/}}
713{{define "driver.C++.DefineProcHookStubs"}}
714  {{AssertType $ "Function"}}
715
716  {{if (Macro "driver.NeedProcHookStubs" $)}}
717    {{$ext := GetAnnotation $ "extension"}}
718    {{$ext_name := index $ext.Arguments 0}}
719
720    {{$base := (Macro "BaseName" $)}}
721    {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
722
723    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$unnamed_params}}) {
724      ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
725      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
726    }
727    {{if (Macro "IsDeviceDispatched" $)}}
728729      VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
730        {{if not (IsVoid $.Return.Type)}}return §{{end}}
731
732        {{$p0 := index $.CallParameters 0}}
733        {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
734        (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) ? §
735          {{$base}}({{Macro "Arguments" $}}) : §
736          disabled{{$base}}({{Macro "Arguments" $}});
737      }
738    {{end}}
739740  {{end}}
741{{end}}
742
743
744{{/*
745-------------------------------------------------------------------------------
746  Emits definition of a global ProcHook.
747-------------------------------------------------------------------------------
748*/}}
749{{define "driver.C++.DefineGlobalProcHook"}}
750  {{AssertType $ "Function"}}
751
752  {{$base := (Macro "BaseName" $)}}
753
754  {{$ext := GetAnnotation $ "extension"}}
755  {{if $ext}}
756    {{Error "invalid global extension"}}
757  {{end}}
758
759  {
760    "{{$.Name}}",
761    ProcHook::GLOBAL,
762    ProcHook::EXTENSION_CORE,
763    reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
764    nullptr,
765    nullptr,
766  },
767{{end}}
768
769
770{{/*
771-------------------------------------------------------------------------------
772  Emits definition of an instance ProcHook.
773-------------------------------------------------------------------------------
774*/}}
775{{define "driver.C++.DefineInstanceProcHook"}}
776  {{AssertType $ "Function"}}
777
778  {{$base := (Macro "BaseName" $)}}
779
780  {
781    "{{$.Name}}",
782    ProcHook::INSTANCE,
783
784    {{$ext := GetAnnotation $ "extension"}}
785    {{if $ext}}
786      ProcHook::{{Macro "BaseName" $ext}},
787
788      {{if (Macro "IsExtensionInternal" $ext)}}
789        nullptr,
790        nullptr,
791        nullptr,
792      {{else}}
793        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
794        reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
795        nullptr,
796      {{end}}
797    {{else}}
798      ProcHook::EXTENSION_CORE,
799      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
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}}),
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