code-generator.tmpl revision ff4a6c772aaf3ff0b71348647330031a059b1f51
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 "vkEnumeratePhysicalDevices"}}true
605    {{else if eq $.Name "vkGetDeviceQueue"}}true
606    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
607
608    {{/* Destroy functions of dispatchable objects */}}
609    {{else if eq $.Name "vkDestroyInstance"}}true
610    {{else if eq $.Name "vkDestroyDevice"}}true
611
612    {{/* Enumeration of extensions */}}
613    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
614    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
615
616    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
617    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
618
619    {{end}}
620
621    {{$ext := GetAnnotation $ "extension"}}
622    {{if $ext}}
623      {{Macro "driver.IsExtensionIntercepted" $ext}}
624    {{end}}
625
626  {{end}}
627{{end}}
628
629
630{{/*
631------------------------------------------------------------------------------
632  Emits true if a function needs ProcHook stubs.
633------------------------------------------------------------------------------
634*/}}
635{{define "driver.NeedProcHookStubs"}}
636  {{AssertType $ "Function"}}
637
638  {{if (Macro "driver.IsIntercepted" $)}}
639    {{$ext := GetAnnotation $ "extension"}}
640    {{if $ext}}
641      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
642    {{end}}
643  {{end}}
644{{end}}
645
646
647{{/*
648-------------------------------------------------------------------------------
649  Emits definition of struct ProcHook.
650-------------------------------------------------------------------------------
651*/}}
652{{define "driver.C++.DefineProcHookType"}}
653  struct ProcHook {
654      enum Type {
655        GLOBAL,
656        INSTANCE,
657        DEVICE,
658      };
659
660      enum Extension {
661        {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
662        {{range $e := $exts}}
663          {{TrimPrefix "VK_" $e}},
664        {{end}}
665666        EXTENSION_CORE, // valid bit
667        EXTENSION_COUNT,
668        EXTENSION_UNKNOWN,
669      };
670671      const char* name;
672      Type type;
673      Extension extension;
674675      PFN_vkVoidFunction proc;
676      PFN_vkVoidFunction disabled_proc; // nullptr for global hooks
677      PFN_vkVoidFunction checked_proc;  // nullptr for global/instance hooks
678  };
679{{end}}
680
681
682{{/*
683-------------------------------------------------------------------------------
684  Emits INIT_PROC_EXT macro for vulkan::driver.
685-------------------------------------------------------------------------------
686*/}}
687{{define "driver.C++.DefineInitProcExtMacro"}}
688  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
689      if (data.hal_extensions[ProcHook::ext])           \
690        INIT_PROC(obj, proc);                                   \
691  } while(0)
692{{end}}
693
694
695{{/*
696-------------------------------------------------------------------------------
697  Emits definitions of stub functions for ProcHook.
698-------------------------------------------------------------------------------
699*/}}
700{{define "driver.C++.DefineProcHookStubs"}}
701  {{AssertType $ "Function"}}
702
703  {{if (Macro "driver.NeedProcHookStubs" $)}}
704    {{$ext := GetAnnotation $ "extension"}}
705    {{$ext_name := index $ext.Arguments 0}}
706
707    {{$base := (Macro "BaseName" $)}}
708    {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
709
710    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$unnamed_params}}) {
711      ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
712      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
713    }
714    {{if (Macro "IsDeviceDispatched" $)}}
715716      VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
717        {{if not (IsVoid $.Return.Type)}}return §{{end}}
718
719        {{$p0 := index $.CallParameters 0}}
720        {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
721        (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) ? §
722          {{$base}}_Bottom({{Macro "Arguments" $}}) : §
723          disabled{{$base}}({{Macro "Arguments" $}});
724      }
725    {{end}}
726727  {{end}}
728{{end}}
729
730
731{{/*
732-------------------------------------------------------------------------------
733  Emits definition of a global ProcHook.
734-------------------------------------------------------------------------------
735*/}}
736{{define "driver.C++.DefineGlobalProcHook"}}
737  {{AssertType $ "Function"}}
738
739  {{$base := (Macro "BaseName" $)}}
740
741  {{$ext := GetAnnotation $ "extension"}}
742  {{if $ext}}
743    {{Error "invalid global extension"}}
744  {{end}}
745
746  {
747    "{{$.Name}}",
748    ProcHook::GLOBAL,
749    ProcHook::EXTENSION_CORE,
750    reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
751    nullptr,
752    nullptr,
753  },
754{{end}}
755
756
757{{/*
758-------------------------------------------------------------------------------
759  Emits definition of an instance ProcHook.
760-------------------------------------------------------------------------------
761*/}}
762{{define "driver.C++.DefineInstanceProcHook"}}
763  {{AssertType $ "Function"}}
764
765  {{$base := (Macro "BaseName" $)}}
766
767  {
768    "{{$.Name}}",
769    ProcHook::INSTANCE,
770
771    {{$ext := GetAnnotation $ "extension"}}
772    {{if $ext}}
773      ProcHook::{{Macro "BaseName" $ext}},
774
775      {{if (Macro "IsExtensionInternal" $ext)}}
776        nullptr,
777        nullptr,
778        nullptr,
779      {{else}}
780        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
781        reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
782        nullptr,
783      {{end}}
784    {{else}}
785      ProcHook::EXTENSION_CORE,
786      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
787      nullptr,
788      nullptr,
789    {{end}}
790  },
791{{end}}
792
793
794{{/*
795-------------------------------------------------------------------------------
796  Emits definition of a device ProcHook.
797-------------------------------------------------------------------------------
798*/}}
799{{define "driver.C++.DefineDeviceProcHook"}}
800  {{AssertType $ "Function"}}
801
802  {{$base := (Macro "BaseName" $)}}
803
804  {
805    "{{$.Name}}",
806    ProcHook::DEVICE,
807
808    {{$ext := GetAnnotation $ "extension"}}
809    {{if $ext}}
810      ProcHook::{{Macro "BaseName" $ext}},
811
812      {{if (Macro "IsExtensionInternal" $ext)}}
813        nullptr,
814        nullptr,
815        nullptr,
816      {{else}}
817        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
818        reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
819        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
820      {{end}}
821    {{else}}
822      ProcHook::EXTENSION_CORE,
823      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
824      nullptr,
825      nullptr,
826    {{end}}
827  },
828{{end}}
829
830
831{{/*
832-------------------------------------------------------------------------------
833  Emits true if a function is needed by vulkan::driver.
834-------------------------------------------------------------------------------
835*/}}
836{{define "driver.IsDriverTableEntry"}}
837  {{AssertType $ "Function"}}
838
839  {{if (Macro "IsFunctionSupported" $)}}
840    {{/* Create functions of dispatchable objects */}}
841    {{     if eq $.Name "vkCreateDevice"}}true
842    {{else if eq $.Name "vkGetDeviceQueue"}}true
843    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
844
845    {{/* Destroy functions of dispatchable objects */}}
846    {{else if eq $.Name "vkDestroyInstance"}}true
847    {{else if eq $.Name "vkDestroyDevice"}}true
848
849    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
850
851    {{/* Enumeration of extensions */}}
852    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
853
854    {{/* We cache physical devices in loader.cpp */}}
855    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
856
857    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
858    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
859
860    {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
861    {{else if eq $.Name "vkCreateImage"}}true
862    {{else if eq $.Name "vkDestroyImage"}}true
863
864    {{end}}
865
866    {{$ext := GetAnnotation $ "extension"}}
867    {{if $ext}}
868      {{$ext_name := index $ext.Arguments 0}}
869      {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
870      {{else if eq $ext_name "VK_EXT_debug_report"}}true
871      {{end}}
872    {{end}}
873  {{end}}
874{{end}}
875
876
877{{/*
878------------------------------------------------------------------------------
879  Emits true if an instance-dispatched function is needed by vulkan::driver.
880------------------------------------------------------------------------------
881*/}}
882{{define "driver.IsInstanceDriverTableEntry"}}
883  {{AssertType $ "Function"}}
884
885  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
886    true
887  {{end}}
888{{end}}
889
890
891{{/*
892------------------------------------------------------------------------------
893  Emits true if a device-dispatched function is needed by vulkan::driver.
894------------------------------------------------------------------------------
895*/}}
896{{define "driver.IsDeviceDriverTableEntry"}}
897  {{AssertType $ "Function"}}
898
899  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
900    true
901  {{end}}
902{{end}}
903
904
905{{/*
906-------------------------------------------------------------------------------
907  Emits a function/extension name without the "vk"/"VK_" prefix.
908-------------------------------------------------------------------------------
909*/}}
910{{define "BaseName"}}
911  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
912  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
913  {{else}}{{Error "invalid use of BaseName"}}
914  {{end}}
915{{end}}
916
917
918{{/*
919-------------------------------------------------------------------------------
920  Emits a comma-separated list of C parameter names for the given command.
921-------------------------------------------------------------------------------
922*/}}
923{{define "Arguments"}}
924  {{AssertType $ "Function"}}
925
926  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
927{{end}}
928
929
930{{/*
931------------------------------------------------------------------------------
932------------------------------------------------------------------------------
933*/}}
934{{define "IsGloballyDispatched"}}
935  {{AssertType $ "Function"}}
936  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
937    true
938  {{end}}
939{{end}}
940
941
942{{/*
943------------------------------------------------------------------------------
944  Emit "true" for supported functions that undergo table dispatch. Only global
945  functions and functions handled in the loader top without calling into
946  lower layers are not dispatched.
947------------------------------------------------------------------------------
948*/}}
949{{define "IsInstanceDispatched"}}
950  {{AssertType $ "Function"}}
951  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
952    true
953  {{end}}
954{{end}}
955
956
957{{/*
958------------------------------------------------------------------------------
959  Emit "true" for supported functions that can have device-specific dispatch.
960------------------------------------------------------------------------------
961*/}}
962{{define "IsDeviceDispatched"}}
963  {{AssertType $ "Function"}}
964  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
965    true
966  {{end}}
967{{end}}
968
969
970{{/*
971------------------------------------------------------------------------------
972  Emit "true" if a function is core or from a supportable extension.
973------------------------------------------------------------------------------
974*/}}
975{{define "IsFunctionSupported"}}
976  {{AssertType $ "Function"}}
977  {{if not (GetAnnotation $ "pfn")}}
978    {{$ext := GetAnnotation $ "extension"}}
979    {{if not $ext}}true
980    {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
981    {{end}}
982  {{end}}
983{{end}}
984
985
986{{/*
987------------------------------------------------------------------------------
988  Decides whether a function should be exported from the Android Vulkan
989  library. Functions in the core API and in loader extensions are exported.
990------------------------------------------------------------------------------
991*/}}
992{{define "IsFunctionExported"}}
993  {{AssertType $ "Function"}}
994
995  {{if (Macro "IsFunctionSupported" $)}}
996    {{$ext := GetAnnotation $ "extension"}}
997    {{if $ext}}
998      {{Macro "IsExtensionExported" $ext}}
999    {{else}}
1000      true
1001    {{end}}
1002  {{end}}
1003{{end}}
1004
1005
1006{{/*
1007------------------------------------------------------------------------------
1008  Emit "true" if an extension is unsupportable on Android.
1009------------------------------------------------------------------------------
1010*/}}
1011{{define "IsExtensionBlacklisted"}}
1012  {{$ext := index $.Arguments 0}}
1013  {{     if eq $ext "VK_KHR_display"}}true
1014  {{else if eq $ext "VK_KHR_display_swapchain"}}true
1015  {{else if eq $ext "VK_KHR_xlib_surface"}}true
1016  {{else if eq $ext "VK_KHR_xcb_surface"}}true
1017  {{else if eq $ext "VK_KHR_wayland_surface"}}true
1018  {{else if eq $ext "VK_KHR_mir_surface"}}true
1019  {{else if eq $ext "VK_KHR_win32_surface"}}true
1020  {{end}}
1021{{end}}
1022
1023
1024{{/*
1025------------------------------------------------------------------------------
1026  Reports whether an extension is implemented entirely by the loader,
1027  so drivers should not enumerate it.
1028------------------------------------------------------------------------------
1029*/}}
1030{{define "IsExtensionExported"}}
1031  {{$ext := index $.Arguments 0}}
1032  {{     if eq $ext "VK_KHR_surface"}}true
1033  {{else if eq $ext "VK_KHR_swapchain"}}true
1034  {{else if eq $ext "VK_KHR_android_surface"}}true
1035  {{end}}
1036{{end}}
1037
1038
1039{{/*
1040------------------------------------------------------------------------------
1041  Reports whether an extension is internal to the loader and drivers,
1042  so the loader should not enumerate it.
1043------------------------------------------------------------------------------
1044*/}}
1045{{define "IsExtensionInternal"}}
1046  {{$ext := index $.Arguments 0}}
1047  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
1048  {{end}}
1049{{end}}
1050