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 <bitset>
41#include <vulkan/vulkan.h>
42#include "driver_gen.h"
4344namespace vulkan {«
45namespace api {«
4647struct InstanceDispatchTable {
48  // clang-format off
49  {{range $f := AllCommands $}}
50    {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
51      {{Macro "C++.DeclareTableEntry" $f}};
52    {{end}}
53  {{end}}
54  // clang-format on
55};
5657struct DeviceDispatchTable {
58  // clang-format off
59  {{range $f := AllCommands $}}
60    {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
61      {{Macro "C++.DeclareTableEntry" $f}};
62    {{end}}
63  {{end}}
64  // clang-format on
65};
6667bool InitDispatchTable(
68    VkInstance instance,
69    PFN_vkGetInstanceProcAddr get_proc,
70    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
71bool InitDispatchTable(
72    VkDevice dev,
73    PFN_vkGetDeviceProcAddr get_proc,
74    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
7576»} // namespace api
77»} // namespace vulkan
7879#endif // LIBVULKAN_API_GEN_H
80¶{{end}}
81
82
83{{/*
84-------------------------------------------------------------------------------
85  api_gen.cpp
86-------------------------------------------------------------------------------
87*/}}
88{{define "api_gen.cpp"}}
89{{Macro "Copyright"}}
9091// WARNING: This file is generated. See ../README.md for instructions.
9293#include <string.h>
94#include <algorithm>
95#include <log/log.h>
9697// to catch mismatches between vulkan.h and this file
98#undef VK_NO_PROTOTYPES
99#include "api.h"
100101namespace vulkan {«
102namespace api {«
103104{{Macro "C++.DefineInitProcMacro" "dispatch"}}
105106{{Macro "api.C++.DefineInitProcExtMacro"}}
107108namespace {«
109110// clang-format off
111112{{range $f := AllCommands $}}
113  {{Macro "api.C++.DefineExtensionStub" $f}}
114{{end}}
115// clang-format on
116117»} // anonymous
118119bool InitDispatchTable(
120    VkInstance instance,
121    PFN_vkGetInstanceProcAddr get_proc,
122    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
123    auto& data = GetData(instance);
124    bool success = true;
125126    // clang-format off
127    {{range $f := AllCommands $}}
128      {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
129        {{Macro "C++.InitProc" $f}}
130      {{end}}
131    {{end}}
132    // clang-format on
133134    return success;
135}
136137bool InitDispatchTable(
138    VkDevice dev,
139    PFN_vkGetDeviceProcAddr get_proc,
140    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
141    auto& data = GetData(dev);
142    bool success = true;
143144    // clang-format off
145    {{range $f := AllCommands $}}
146      {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
147        {{Macro "C++.InitProc" $f}}
148      {{end}}
149    {{end}}
150    // clang-format on
151152    return success;
153}
154155// clang-format off
156157namespace {«
158159// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr
160{{range $f := AllCommands $}}
161  {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
162    VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}});
163  {{end}}
164{{end}}
165166{{range $f := AllCommands $}}
167  {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
168    VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}}) {
169      {{     if eq $f.Name "vkGetInstanceProcAddr"}}
170        {{Macro "api.C++.InterceptInstanceProcAddr" $}}
171      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
172        {{Macro "api.C++.InterceptDeviceProcAddr" $}}
173      {{end}}
174
175      {{Macro "api.C++.Dispatch" $f}}
176    }
177178  {{end}}
179{{end}}
180181»}  // anonymous namespace
182183// clang-format on
184185»} // namespace api
186»} // namespace vulkan
187188// clang-format off
189190{{range $f := AllCommands $}}
191  {{if (Macro "IsFunctionExported" $f)}}
192    __attribute__((visibility("default")))
193    VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
194      {{if not (IsVoid $f.Return.Type)}}return §{{end}}
195      vulkan::api::{{Macro "BaseName" $f}}({{Macro "Arguments" $f}});
196    }
197198  {{end}}
199{{end}}
200201// clang-format on
202¶{{end}}
203
204
205{{/*
206-------------------------------------------------------------------------------
207  driver_gen.h
208-------------------------------------------------------------------------------
209*/}}
210{{define "driver_gen.h"}}
211{{Macro "Copyright"}}
212213// WARNING: This file is generated. See ../README.md for instructions.
214215#ifndef LIBVULKAN_DRIVER_GEN_H
216#define LIBVULKAN_DRIVER_GEN_H
217218#include <bitset>
219#include <vulkan/vulkan.h>
220#include <vulkan/vk_android_native_buffer.h>
221222namespace vulkan {«
223namespace driver {«
224225{{Macro "driver.C++.DefineProcHookType"}}
226227struct InstanceDriverTable {
228  // clang-format off
229  {{range $f := AllCommands $}}
230    {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
231      {{Macro "C++.DeclareTableEntry" $f}};
232    {{end}}
233  {{end}}
234  // clang-format on
235};
236237struct DeviceDriverTable {
238  // clang-format off
239  {{range $f := AllCommands $}}
240    {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
241      {{Macro "C++.DeclareTableEntry" $f}};
242    {{end}}
243  {{end}}
244  // clang-format on
245};
246247const ProcHook* GetProcHook(const char* name);
248ProcHook::Extension GetProcHookExtension(const char* name);
249250bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
251                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
252bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
253                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
254255»} // namespace driver
256»} // namespace vulkan
257258#endif // LIBVULKAN_DRIVER_TABLE_H
259¶{{end}}
260
261
262{{/*
263-------------------------------------------------------------------------------
264  driver_gen.cpp
265-------------------------------------------------------------------------------
266*/}}
267{{define "driver_gen.cpp"}}
268{{Macro "Copyright"}}
269270// WARNING: This file is generated. See ../README.md for instructions.
271272#include <string.h>
273#include <algorithm>
274#include <log/log.h>
275276#include "driver.h"
277278namespace vulkan {«
279namespace driver {«
280281namespace {«
282283// clang-format off
284285{{range $f := AllCommands $}}
286  {{Macro "driver.C++.DefineProcHookStub" $f}}
287{{end}}
288// clang-format on
289290const ProcHook g_proc_hooks[] = {
291  // clang-format off
292  {{range $f := SortBy (AllCommands $) "FunctionName"}}
293    {{if (Macro "driver.IsIntercepted" $f)}}
294      {{     if (Macro "IsGloballyDispatched" $f)}}
295        {{Macro "driver.C++.DefineGlobalProcHook" $f}}
296      {{else if (Macro "IsInstanceDispatched" $f)}}
297        {{Macro "driver.C++.DefineInstanceProcHook" $f}}
298      {{else if (Macro "IsDeviceDispatched" $f)}}
299        {{Macro "driver.C++.DefineDeviceProcHook" $f}}
300      {{end}}
301    {{end}}
302  {{end}}
303  // clang-format on
304};
305306»} // anonymous
307308const ProcHook* GetProcHook(const char* name) {
309    const auto& begin = g_proc_hooks;
310    const auto& end = g_proc_hooks +
311      sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
312    const auto hook = std::lower_bound(begin, end, name,
313        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
314    return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
315}
316317ProcHook::Extension GetProcHookExtension(const char* name) {
318  {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
319  // clang-format off
320  {{range $e := $exts}}
321    if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
322  {{end}}
323  // clang-format on
324  return ProcHook::EXTENSION_UNKNOWN;
325}
326327{{Macro "C++.DefineInitProcMacro" "driver"}}
328329{{Macro "driver.C++.DefineInitProcExtMacro"}}
330331bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
332                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
333{
334    auto& data = GetData(instance);
335    bool success = true;
336337    // clang-format off
338    {{range $f := AllCommands $}}
339      {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
340        {{Macro "C++.InitProc" $f}}
341      {{end}}
342    {{end}}
343    // clang-format on
344345    return success;
346}
347348bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
349                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
350{
351    auto& data = GetData(dev);
352    bool success = true;
353354    // clang-format off
355    {{range $f := AllCommands $}}
356      {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
357        {{Macro "C++.InitProc" $f}}
358      {{end}}
359    {{end}}
360    // clang-format on
361362    return success;
363}
364365»} // namespace driver
366»} // namespace vulkan
367368// clang-format on
369¶{{end}}
370
371
372{{/*
373------------------------------------------------------------------------------
374  Emits a declaration of a dispatch/driver table entry.
375------------------------------------------------------------------------------
376*/}}
377{{define "C++.DeclareTableEntry"}}
378  {{AssertType $ "Function"}}
379
380  {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
381{{end}}
382
383
384{{/*
385-------------------------------------------------------------------------------
386  Emits INIT_PROC macro.
387-------------------------------------------------------------------------------
388*/}}
389{{define "C++.DefineInitProcMacro"}}
390  #define UNLIKELY(expr) __builtin_expect((expr), 0)
391392  #define INIT_PROC(obj, proc) do {                             \
393      data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
394              get_proc(obj, "vk" # proc));                      \
395      if (UNLIKELY(!data.{{$}}.proc)) {                         \
396          ALOGE("missing " # obj " proc: vk" # proc);           \
397          success = false;                                      \
398      }                                                         \
399  } while(0)
400{{end}}
401
402
403{{/*
404-------------------------------------------------------------------------------
405  Emits code to invoke INIT_PROC or INIT_PROC_EXT.
406-------------------------------------------------------------------------------
407*/}}
408{{define "C++.InitProc"}}
409  {{AssertType $ "Function"}}
410
411  {{$ext := GetAnnotation $ "extension"}}
412  {{if $ext}}
413    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
414  {{else}}
415    INIT_PROC(§
416  {{end}}
417
418  {{if (Macro "IsInstanceDispatched" $)}}
419    instance, §
420  {{else}}
421    dev, §
422  {{end}}
423
424  {{Macro "BaseName" $}});
425{{end}}
426
427
428{{/*
429------------------------------------------------------------------------------
430  Emits true if a function is exported and instance-dispatched.
431------------------------------------------------------------------------------
432*/}}
433{{define "api.IsInstanceDispatchTableEntry"}}
434  {{AssertType $ "Function"}}
435
436  {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
437    {{/* deprecated and unused internally */}}
438    {{if not (eq $.Name "vkEnumerateDeviceLayerProperties")}}
439      true
440    {{end}}
441  {{end}}
442{{end}}
443
444
445{{/*
446------------------------------------------------------------------------------
447  Emits true if a function is exported and device-dispatched.
448------------------------------------------------------------------------------
449*/}}
450{{define "api.IsDeviceDispatchTableEntry"}}
451  {{AssertType $ "Function"}}
452
453  {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
454    true
455  {{end}}
456{{end}}
457
458
459{{/*
460------------------------------------------------------------------------------
461  Emits true if a function is intercepted by vulkan::api.
462------------------------------------------------------------------------------
463*/}}
464{{define "api.IsIntercepted"}}
465  {{AssertType $ "Function"}}
466
467  {{if (Macro "IsFunctionSupported" $)}}
468    {{/* Global functions cannot be dispatched at all */}}
469    {{     if (Macro "IsGloballyDispatched" $)}}true
470
471    {{/* VkPhysicalDevice functions that manage device layers */}}
472    {{else if eq $.Name "vkCreateDevice"}}true
473    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
474    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
475
476    {{/* Destroy functions of dispatchable objects */}}
477    {{else if eq $.Name "vkDestroyInstance"}}true
478    {{else if eq $.Name "vkDestroyDevice"}}true
479
480    {{end}}
481  {{end}}
482{{end}}
483
484
485{{/*
486-------------------------------------------------------------------------------
487  Emits INIT_PROC_EXT macro for vulkan::api.
488-------------------------------------------------------------------------------
489*/}}
490{{define "api.C++.DefineInitProcExtMacro"}}
491  // Exported extension functions may be invoked even when their extensions
492  // are disabled.  Dispatch to stubs when that happens.
493  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
494      if (extensions[driver::ProcHook::ext])                    \
495        INIT_PROC(obj, proc);                                   \
496      else                                                      \
497        data.dispatch.proc = disabled ## proc;                  \
498  } while(0)
499{{end}}
500
501
502{{/*
503-------------------------------------------------------------------------------
504  Emits a stub for an exported extension function.
505-------------------------------------------------------------------------------
506*/}}
507{{define "api.C++.DefineExtensionStub"}}
508  {{AssertType $ "Function"}}
509
510  {{$ext := GetAnnotation $ "extension"}}
511  {{if and $ext (Macro "IsFunctionExported" $)}}
512    {{$ext_name := index $ext.Arguments 0}}
513
514    {{$base := (Macro "BaseName" $)}}
515
516    {{$p0 := (index $.CallParameters 0)}}
517    {{$ptail := (Tail 1 $.CallParameters)}}
518
519    {{$first_type := (Macro "Parameter" $p0)}}
520    {{$tail_types := (ForEach $ptail "ParameterType" | JoinWith ", ")}}
521
522    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$first_type}}, {{$tail_types}}) {
523      driver::Logger({{$p0.Name}}).Err({{$p0.Name}}, §
524        "{{$ext_name}} not enabled. Exported {{$.Name}} not executed.");
525      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
526    }
527528  {{end}}
529{{end}}
530
531
532{{/*
533------------------------------------------------------------------------------
534  Emits code for vkGetInstanceProcAddr for function interception.
535------------------------------------------------------------------------------
536*/}}
537{{define "api.C++.InterceptInstanceProcAddr"}}
538  {{AssertType $ "API"}}
539
540  // global functions
541  if (instance == VK_NULL_HANDLE) {
542    {{range $f := AllCommands $}}
543      {{if (Macro "IsGloballyDispatched" $f)}}
544        if (strcmp(pName, "{{$f.Name}}") == 0) return §
545          reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}});
546      {{end}}
547    {{end}}
548549    ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", pName);
550    return nullptr;
551  }
552553  static const struct Hook {
554    const char* name;
555    PFN_vkVoidFunction proc;
556  } hooks[] = {
557    {{range $f := SortBy (AllCommands $) "FunctionName"}}
558      {{if (Macro "IsFunctionExported" $f)}}
559        {{/* hide global functions */}}
560        {{if (Macro "IsGloballyDispatched" $f)}}
561          { "{{$f.Name}}", nullptr },
562
563        {{/* redirect intercepted functions */}}
564        {{else if (Macro "api.IsIntercepted" $f)}}
565          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
566            {{Macro "BaseName" $f}}) },
567
568        {{/* redirect vkGetInstanceProcAddr to itself */}}
569        {{else if eq $f.Name "vkGetInstanceProcAddr"}}
570          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}}) },
571
572        {{/* redirect device functions to themselves as a workaround for
573             layers that do not intercept in their vkGetInstanceProcAddr */}}
574        {{else if (Macro "IsDeviceDispatched" $f)}}
575          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}}) },
576
577        {{end}}
578      {{end}}
579    {{end}}
580  };
581  // clang-format on
582  constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
583  auto hook = std::lower_bound(
584    hooks, hooks + count, pName,
585    [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
586  if (hook <  hooks + count && strcmp(hook->name, pName) == 0) {
587    if (!hook->proc) {
588      vulkan::driver::Logger(instance).Err(
589        instance, "invalid vkGetInstanceProcAddr(%p, \"%s\") call",
590        instance, pName);
591    }
592    return hook->proc;
593  }
594  // clang-format off
595596{{end}}
597
598
599{{/*
600------------------------------------------------------------------------------
601  Emits code for vkGetDeviceProcAddr for function interception.
602------------------------------------------------------------------------------
603*/}}
604{{define "api.C++.InterceptDeviceProcAddr"}}
605  {{AssertType $ "API"}}
606
607  if (device == VK_NULL_HANDLE) {
608    ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
609    return nullptr;
610  }
611612  static const char* const known_non_device_names[] = {
613    {{range $f := SortBy (AllCommands $) "FunctionName"}}
614      {{if (Macro "IsFunctionSupported" $f)}}
615        {{if not (Macro "IsDeviceDispatched" $f)}}
616          "{{$f.Name}}",
617        {{end}}
618      {{end}}
619    {{end}}
620  };
621  // clang-format on
622  constexpr size_t count = sizeof(known_non_device_names) /
623    sizeof(known_non_device_names[0]);
624  if (!pName ||
625      std::binary_search(
626        known_non_device_names, known_non_device_names + count, pName,
627        [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
628    vulkan::driver::Logger(device).Err(§
629      device, "invalid vkGetDeviceProcAddr(%p, \"%s\") call", device,§
630      (pName) ? pName : "(null)");
631    return nullptr;
632  }
633  // clang-format off
634635  {{range $f := AllCommands $}}
636    {{if (Macro "IsDeviceDispatched" $f)}}
637      {{     if (Macro "api.IsIntercepted" $f)}}
638        if (strcmp(pName, "{{$f.Name}}") == 0) return §
639          reinterpret_cast<PFN_vkVoidFunction>(§
640            {{Macro "BaseName" $f}});
641      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
642        if (strcmp(pName, "{{$f.Name}}") == 0) return §
643          reinterpret_cast<PFN_vkVoidFunction>(§
644            {{Macro "BaseName" $f}});
645      {{end}}
646    {{end}}
647  {{end}}
648649{{end}}
650
651
652{{/*
653------------------------------------------------------------------------------
654  Emits code to dispatch a function.
655------------------------------------------------------------------------------
656*/}}
657{{define "api.C++.Dispatch"}}
658  {{AssertType $ "Function"}}
659  {{if (Macro "api.IsIntercepted" $)}}
660    {{Error "$.Name should not be generated"}}
661  {{end}}
662
663  {{if not (IsVoid $.Return.Type)}}return §{{end}}
664
665  {{$p0 := index $.CallParameters 0}}
666  GetData({{$p0.Name}}).dispatch.§
667  {{Macro "BaseName" $}}({{Macro "Arguments" $}});
668{{end}}
669
670
671{{/*
672------------------------------------------------------------------------------
673  Emits a list of extensions intercepted by vulkan::driver.
674------------------------------------------------------------------------------
675*/}}
676{{define "driver.InterceptedExtensions"}}
677VK_ANDROID_native_buffer
678VK_EXT_debug_report
679VK_KHR_android_surface
680VK_KHR_surface
681VK_KHR_swapchain
682{{end}}
683
684
685{{/*
686------------------------------------------------------------------------------
687  Emits true if an extension is intercepted by vulkan::driver.
688------------------------------------------------------------------------------
689*/}}
690{{define "driver.IsExtensionIntercepted"}}
691  {{$ext_name := index $.Arguments 0}}
692  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
693
694  {{range $f := $filters}}
695    {{if eq $ext_name $f}}true{{end}}
696  {{end}}
697{{end}}
698
699
700{{/*
701------------------------------------------------------------------------------
702  Emits true if a function is intercepted by vulkan::driver.
703------------------------------------------------------------------------------
704*/}}
705{{define "driver.IsIntercepted"}}
706  {{AssertType $ "Function"}}
707
708  {{if (Macro "IsFunctionSupported" $)}}
709    {{/* Create functions of dispatchable objects */}}
710    {{     if eq $.Name "vkCreateInstance"}}true
711    {{else if eq $.Name "vkCreateDevice"}}true
712    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
713    {{else if eq $.Name "vkGetDeviceQueue"}}true
714    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
715
716    {{/* Destroy functions of dispatchable objects */}}
717    {{else if eq $.Name "vkDestroyInstance"}}true
718    {{else if eq $.Name "vkDestroyDevice"}}true
719
720    {{/* Enumeration of extensions */}}
721    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
722    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
723
724    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
725    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
726
727    {{end}}
728
729    {{$ext := GetAnnotation $ "extension"}}
730    {{if $ext}}
731      {{Macro "driver.IsExtensionIntercepted" $ext}}
732    {{end}}
733
734  {{end}}
735{{end}}
736
737
738{{/*
739------------------------------------------------------------------------------
740  Emits true if a function needs a ProcHook stub.
741------------------------------------------------------------------------------
742*/}}
743{{define "driver.NeedProcHookStub"}}
744  {{AssertType $ "Function"}}
745
746  {{if and (Macro "driver.IsIntercepted" $) (Macro "IsDeviceDispatched" $)}}
747    {{$ext := GetAnnotation $ "extension"}}
748    {{if $ext}}
749      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
750    {{end}}
751  {{end}}
752{{end}}
753
754
755{{/*
756-------------------------------------------------------------------------------
757  Emits definition of struct ProcHook.
758-------------------------------------------------------------------------------
759*/}}
760{{define "driver.C++.DefineProcHookType"}}
761  struct ProcHook {
762      enum Type {
763        GLOBAL,
764        INSTANCE,
765        DEVICE,
766      };
767
768      enum Extension {
769        {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
770        {{range $e := $exts}}
771          {{TrimPrefix "VK_" $e}},
772        {{end}}
773774        EXTENSION_CORE, // valid bit
775        EXTENSION_COUNT,
776        EXTENSION_UNKNOWN,
777      };
778779      const char* name;
780      Type type;
781      Extension extension;
782783      PFN_vkVoidFunction proc;
784      PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
785  };
786{{end}}
787
788
789{{/*
790-------------------------------------------------------------------------------
791  Emits INIT_PROC_EXT macro for vulkan::driver.
792-------------------------------------------------------------------------------
793*/}}
794{{define "driver.C++.DefineInitProcExtMacro"}}
795  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
796      if (extensions[ProcHook::ext])                            \
797        INIT_PROC(obj, proc);                                   \
798  } while(0)
799{{end}}
800
801
802{{/*
803-------------------------------------------------------------------------------
804  Emits a stub for ProcHook::checked_proc.
805-------------------------------------------------------------------------------
806*/}}
807{{define "driver.C++.DefineProcHookStub"}}
808  {{AssertType $ "Function"}}
809
810  {{if (Macro "driver.NeedProcHookStub" $)}}
811    {{$ext := GetAnnotation $ "extension"}}
812    {{$ext_name := index $ext.Arguments 0}}
813
814    {{$base := (Macro "BaseName" $)}}
815
816    VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
817      {{$p0 := index $.CallParameters 0}}
818      {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
819
820      if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
821        {{if not (IsVoid $.Return.Type)}}return §{{end}}
822        {{$base}}({{Macro "Arguments" $}});
823      } else {
824        Logger({{$p0.Name}}).Err({{$p0.Name}}, "{{$ext_name}} not enabled. {{$.Name}} not executed.");
825        {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
826      }
827    }
828829  {{end}}
830{{end}}
831
832
833{{/*
834-------------------------------------------------------------------------------
835  Emits definition of a global ProcHook.
836-------------------------------------------------------------------------------
837*/}}
838{{define "driver.C++.DefineGlobalProcHook"}}
839  {{AssertType $ "Function"}}
840
841  {{$base := (Macro "BaseName" $)}}
842
843  {{$ext := GetAnnotation $ "extension"}}
844  {{if $ext}}
845    {{Error "invalid global extension"}}
846  {{end}}
847
848  {
849    "{{$.Name}}",
850    ProcHook::GLOBAL,
851    ProcHook::EXTENSION_CORE,
852    reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
853    nullptr,
854  },
855{{end}}
856
857
858{{/*
859-------------------------------------------------------------------------------
860  Emits definition of an instance ProcHook.
861-------------------------------------------------------------------------------
862*/}}
863{{define "driver.C++.DefineInstanceProcHook"}}
864  {{AssertType $ "Function"}}
865
866  {{$base := (Macro "BaseName" $)}}
867
868  {
869    "{{$.Name}}",
870    ProcHook::INSTANCE,
871
872    {{$ext := GetAnnotation $ "extension"}}
873    {{if $ext}}
874      ProcHook::{{Macro "BaseName" $ext}},
875
876      {{if (Macro "IsExtensionInternal" $ext)}}
877        nullptr,
878        nullptr,
879      {{else}}
880        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
881        nullptr,
882      {{end}}
883    {{else}}
884      ProcHook::EXTENSION_CORE,
885      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
886      nullptr,
887    {{end}}
888  },
889{{end}}
890
891
892{{/*
893-------------------------------------------------------------------------------
894  Emits definition of a device ProcHook.
895-------------------------------------------------------------------------------
896*/}}
897{{define "driver.C++.DefineDeviceProcHook"}}
898  {{AssertType $ "Function"}}
899
900  {{$base := (Macro "BaseName" $)}}
901
902  {
903    "{{$.Name}}",
904    ProcHook::DEVICE,
905
906    {{$ext := GetAnnotation $ "extension"}}
907    {{if $ext}}
908      ProcHook::{{Macro "BaseName" $ext}},
909
910      {{if (Macro "IsExtensionInternal" $ext)}}
911        nullptr,
912        nullptr,
913      {{else}}
914        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
915        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
916      {{end}}
917    {{else}}
918      ProcHook::EXTENSION_CORE,
919      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
920      nullptr,
921    {{end}}
922  },
923{{end}}
924
925
926{{/*
927-------------------------------------------------------------------------------
928  Emits true if a function is needed by vulkan::driver.
929-------------------------------------------------------------------------------
930*/}}
931{{define "driver.IsDriverTableEntry"}}
932  {{AssertType $ "Function"}}
933
934  {{if (Macro "IsFunctionSupported" $)}}
935    {{/* Create functions of dispatchable objects */}}
936    {{     if eq $.Name "vkCreateDevice"}}true
937    {{else if eq $.Name "vkGetDeviceQueue"}}true
938    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
939
940    {{/* Destroy functions of dispatchable objects */}}
941    {{else if eq $.Name "vkDestroyInstance"}}true
942    {{else if eq $.Name "vkDestroyDevice"}}true
943
944    {{/* Enumeration of extensions */}}
945    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
946
947    {{/* We cache physical devices in loader.cpp */}}
948    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
949
950    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
951    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
952
953    {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
954    {{else if eq $.Name "vkCreateImage"}}true
955    {{else if eq $.Name "vkDestroyImage"}}true
956
957    {{end}}
958
959    {{$ext := GetAnnotation $ "extension"}}
960    {{if $ext}}
961      {{$ext_name := index $ext.Arguments 0}}
962      {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
963      {{else if eq $ext_name "VK_EXT_debug_report"}}true
964      {{end}}
965    {{end}}
966  {{end}}
967{{end}}
968
969
970{{/*
971------------------------------------------------------------------------------
972  Emits true if an instance-dispatched function is needed by vulkan::driver.
973------------------------------------------------------------------------------
974*/}}
975{{define "driver.IsInstanceDriverTableEntry"}}
976  {{AssertType $ "Function"}}
977
978  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
979    true
980  {{end}}
981{{end}}
982
983
984{{/*
985------------------------------------------------------------------------------
986  Emits true if a device-dispatched function is needed by vulkan::driver.
987------------------------------------------------------------------------------
988*/}}
989{{define "driver.IsDeviceDriverTableEntry"}}
990  {{AssertType $ "Function"}}
991
992  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
993    true
994  {{end}}
995{{end}}
996
997
998{{/*
999-------------------------------------------------------------------------------
1000  Emits a function/extension name without the "vk"/"VK_" prefix.
1001-------------------------------------------------------------------------------
1002*/}}
1003{{define "BaseName"}}
1004  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
1005  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
1006  {{else}}{{Error "invalid use of BaseName"}}
1007  {{end}}
1008{{end}}
1009
1010
1011{{/*
1012-------------------------------------------------------------------------------
1013  Emits a comma-separated list of C parameter names for the given command.
1014-------------------------------------------------------------------------------
1015*/}}
1016{{define "Arguments"}}
1017  {{AssertType $ "Function"}}
1018
1019  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
1020{{end}}
1021
1022
1023{{/*
1024------------------------------------------------------------------------------
1025------------------------------------------------------------------------------
1026*/}}
1027{{define "IsGloballyDispatched"}}
1028  {{AssertType $ "Function"}}
1029  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
1030    true
1031  {{end}}
1032{{end}}
1033
1034
1035{{/*
1036------------------------------------------------------------------------------
1037  Emit "true" for supported functions that undergo table dispatch. Only global
1038  functions and functions handled in the loader top without calling into
1039  lower layers are not dispatched.
1040------------------------------------------------------------------------------
1041*/}}
1042{{define "IsInstanceDispatched"}}
1043  {{AssertType $ "Function"}}
1044  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
1045    true
1046  {{end}}
1047{{end}}
1048
1049
1050{{/*
1051------------------------------------------------------------------------------
1052  Emit "true" for supported functions that can have device-specific dispatch.
1053------------------------------------------------------------------------------
1054*/}}
1055{{define "IsDeviceDispatched"}}
1056  {{AssertType $ "Function"}}
1057  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
1058    true
1059  {{end}}
1060{{end}}
1061
1062
1063{{/*
1064------------------------------------------------------------------------------
1065  Emit "true" if a function is core or from a supportable extension.
1066------------------------------------------------------------------------------
1067*/}}
1068{{define "IsFunctionSupported"}}
1069  {{AssertType $ "Function"}}
1070  {{if not (GetAnnotation $ "pfn")}}
1071    {{$ext := GetAnnotation $ "extension"}}
1072    {{if not $ext}}true
1073    {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
1074    {{end}}
1075  {{end}}
1076{{end}}
1077
1078
1079{{/*
1080------------------------------------------------------------------------------
1081  Decides whether a function should be exported from the Android Vulkan
1082  library. Functions in the core API and in loader extensions are exported.
1083------------------------------------------------------------------------------
1084*/}}
1085{{define "IsFunctionExported"}}
1086  {{AssertType $ "Function"}}
1087
1088  {{if (Macro "IsFunctionSupported" $)}}
1089    {{$ext := GetAnnotation $ "extension"}}
1090    {{if $ext}}
1091      {{Macro "IsExtensionExported" $ext}}
1092    {{else}}
1093      true
1094    {{end}}
1095  {{end}}
1096{{end}}
1097
1098
1099{{/*
1100------------------------------------------------------------------------------
1101  Emit "true" if an extension is unsupportable on Android.
1102------------------------------------------------------------------------------
1103*/}}
1104{{define "IsExtensionBlacklisted"}}
1105  {{$ext := index $.Arguments 0}}
1106  {{     if eq $ext "VK_KHR_display"}}true
1107  {{else if eq $ext "VK_KHR_display_swapchain"}}true
1108  {{else if eq $ext "VK_KHR_xlib_surface"}}true
1109  {{else if eq $ext "VK_KHR_xcb_surface"}}true
1110  {{else if eq $ext "VK_KHR_wayland_surface"}}true
1111  {{else if eq $ext "VK_KHR_mir_surface"}}true
1112  {{else if eq $ext "VK_KHR_win32_surface"}}true
1113  {{end}}
1114{{end}}
1115
1116
1117{{/*
1118------------------------------------------------------------------------------
1119  Reports whether an extension is implemented entirely by the loader,
1120  so drivers should not enumerate it.
1121------------------------------------------------------------------------------
1122*/}}
1123{{define "IsExtensionExported"}}
1124  {{$ext := index $.Arguments 0}}
1125  {{     if eq $ext "VK_KHR_surface"}}true
1126  {{else if eq $ext "VK_KHR_swapchain"}}true
1127  {{else if eq $ext "VK_KHR_android_surface"}}true
1128  {{end}}
1129{{end}}
1130
1131
1132{{/*
1133------------------------------------------------------------------------------
1134  Reports whether an extension is internal to the loader and drivers,
1135  so the loader should not enumerate it.
1136------------------------------------------------------------------------------
1137*/}}
1138{{define "IsExtensionInternal"}}
1139  {{$ext := index $.Arguments 0}}
1140  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
1141  {{end}}
1142{{end}}
1143