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>
9495#include <algorithm>
9697#include <log/log.h>
9899// to catch mismatches between vulkan.h and this file
100#undef VK_NO_PROTOTYPES
101#include "api.h"
102103namespace vulkan {«
104namespace api {«
105106{{Macro "C++.DefineInitProcMacro" "dispatch"}}
107108{{Macro "api.C++.DefineInitProcExtMacro"}}
109110namespace {«
111112// clang-format off
113114{{range $f := AllCommands $}}
115  {{Macro "api.C++.DefineExtensionStub" $f}}
116{{end}}
117// clang-format on
118119»} // anonymous
120121bool InitDispatchTable(
122    VkInstance instance,
123    PFN_vkGetInstanceProcAddr get_proc,
124    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
125    auto& data = GetData(instance);
126    bool success = true;
127128    // clang-format off
129    {{range $f := AllCommands $}}
130      {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
131        {{Macro "C++.InitProc" $f}}
132      {{end}}
133    {{end}}
134    // clang-format on
135136    return success;
137}
138139bool InitDispatchTable(
140    VkDevice dev,
141    PFN_vkGetDeviceProcAddr get_proc,
142    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
143    auto& data = GetData(dev);
144    bool success = true;
145146    // clang-format off
147    {{range $f := AllCommands $}}
148      {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
149        {{Macro "C++.InitProc" $f}}
150      {{end}}
151    {{end}}
152    // clang-format on
153154    return success;
155}
156157// clang-format off
158159namespace {«
160161// forward declarations needed by GetInstanceProcAddr and GetDeviceProcAddr
162{{range $f := AllCommands $}}
163  {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
164    VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}});
165  {{end}}
166{{end}}
167168{{range $f := AllCommands $}}
169  {{if and (Macro "IsFunctionExported" $f) (not (Macro "api.IsIntercepted" $f))}}
170    VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}}) {
171      {{     if eq $f.Name "vkGetInstanceProcAddr"}}
172        {{Macro "api.C++.InterceptInstanceProcAddr" $}}
173      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
174        {{Macro "api.C++.InterceptDeviceProcAddr" $}}
175      {{end}}
176
177      {{Macro "api.C++.Dispatch" $f}}
178    }
179180  {{end}}
181{{end}}
182183»}  // anonymous namespace
184185// clang-format on
186187»} // namespace api
188»} // namespace vulkan
189190// clang-format off
191192{{range $f := AllCommands $}}
193  {{if (Macro "IsFunctionExported" $f)}}
194    __attribute__((visibility("default")))
195    VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
196      {{if not (IsVoid $f.Return.Type)}}return §{{end}}
197      vulkan::api::{{Macro "BaseName" $f}}({{Macro "Arguments" $f}});
198    }
199200  {{end}}
201{{end}}
202203// clang-format on
204¶{{end}}
205
206
207{{/*
208-------------------------------------------------------------------------------
209  driver_gen.h
210-------------------------------------------------------------------------------
211*/}}
212{{define "driver_gen.h"}}
213{{Macro "Copyright"}}
214215// WARNING: This file is generated. See ../README.md for instructions.
216217#ifndef LIBVULKAN_DRIVER_GEN_H
218#define LIBVULKAN_DRIVER_GEN_H
219220#include <bitset>
221#include <vulkan/vulkan.h>
222#include <vulkan/vk_android_native_buffer.h>
223224namespace vulkan {«
225namespace driver {«
226227{{Macro "driver.C++.DefineProcHookType"}}
228229struct InstanceDriverTable {
230  // clang-format off
231  {{range $f := AllCommands $}}
232    {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
233      {{Macro "C++.DeclareTableEntry" $f}};
234    {{end}}
235  {{end}}
236  // clang-format on
237};
238239struct DeviceDriverTable {
240  // clang-format off
241  {{range $f := AllCommands $}}
242    {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
243      {{Macro "C++.DeclareTableEntry" $f}};
244    {{end}}
245  {{end}}
246  // clang-format on
247};
248249const ProcHook* GetProcHook(const char* name);
250ProcHook::Extension GetProcHookExtension(const char* name);
251252bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
253                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
254bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
255                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
256257»} // namespace driver
258»} // namespace vulkan
259260#endif // LIBVULKAN_DRIVER_TABLE_H
261¶{{end}}
262
263
264{{/*
265-------------------------------------------------------------------------------
266  driver_gen.cpp
267-------------------------------------------------------------------------------
268*/}}
269{{define "driver_gen.cpp"}}
270{{Macro "Copyright"}}
271272// WARNING: This file is generated. See ../README.md for instructions.
273274#include <string.h>
275276#include <algorithm>
277278#include <log/log.h>
279280#include "driver.h"
281282namespace vulkan {«
283namespace driver {«
284285namespace {«
286287// clang-format off
288289{{range $f := AllCommands $}}
290  {{Macro "driver.C++.DefineProcHookStub" $f}}
291{{end}}
292// clang-format on
293294const ProcHook g_proc_hooks[] = {
295  // clang-format off
296  {{range $f := SortBy (AllCommands $) "FunctionName"}}
297    {{if (Macro "driver.IsIntercepted" $f)}}
298      {{     if (Macro "IsGloballyDispatched" $f)}}
299        {{Macro "driver.C++.DefineGlobalProcHook" $f}}
300      {{else if (Macro "IsInstanceDispatched" $f)}}
301        {{Macro "driver.C++.DefineInstanceProcHook" $f}}
302      {{else if (Macro "IsDeviceDispatched" $f)}}
303        {{Macro "driver.C++.DefineDeviceProcHook" $f}}
304      {{end}}
305    {{end}}
306  {{end}}
307  // clang-format on
308};
309310»} // anonymous
311312const ProcHook* GetProcHook(const char* name) {
313    const auto& begin = g_proc_hooks;
314    const auto& end = g_proc_hooks +
315      sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
316    const auto hook = std::lower_bound(begin, end, name,
317        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
318    return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
319}
320321ProcHook::Extension GetProcHookExtension(const char* name) {
322  {{$exts := Strings (Macro "driver.KnownExtensions") | SplitOn "\n"}}
323  // clang-format off
324  {{range $e := $exts}}
325    if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
326  {{end}}
327  // clang-format on
328  return ProcHook::EXTENSION_UNKNOWN;
329}
330331{{Macro "C++.DefineInitProcMacro" "driver"}}
332333{{Macro "driver.C++.DefineInitProcExtMacro"}}
334335bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
336                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
337{
338    auto& data = GetData(instance);
339    bool success = true;
340341    // clang-format off
342    {{range $f := AllCommands $}}
343      {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
344        {{Macro "C++.InitProc" $f}}
345      {{end}}
346    {{end}}
347    // clang-format on
348349    return success;
350}
351352bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
353                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
354{
355    auto& data = GetData(dev);
356    bool success = true;
357358    // clang-format off
359    {{range $f := AllCommands $}}
360      {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
361        {{Macro "C++.InitProc" $f}}
362      {{end}}
363    {{end}}
364    // clang-format on
365366    return success;
367}
368369»} // namespace driver
370»} // namespace vulkan
371372// clang-format on
373¶{{end}}
374
375
376{{/*
377------------------------------------------------------------------------------
378  Emits a declaration of a dispatch/driver table entry.
379------------------------------------------------------------------------------
380*/}}
381{{define "C++.DeclareTableEntry"}}
382  {{AssertType $ "Function"}}
383
384  {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
385{{end}}
386
387
388{{/*
389-------------------------------------------------------------------------------
390  Emits INIT_PROC macro.
391-------------------------------------------------------------------------------
392*/}}
393{{define "C++.DefineInitProcMacro"}}
394  #define UNLIKELY(expr) __builtin_expect((expr), 0)
395396  #define INIT_PROC(required, obj, proc) do {                   \
397      data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
398              get_proc(obj, "vk" # proc));                      \
399      if (UNLIKELY(required && !data.{{$}}.proc)) {             \
400          ALOGE("missing " # obj " proc: vk" # proc);           \
401          success = false;                                      \
402      }                                                         \
403  } while(0)
404{{end}}
405
406
407{{/*
408-------------------------------------------------------------------------------
409  Emits code to invoke INIT_PROC or INIT_PROC_EXT.
410-------------------------------------------------------------------------------
411*/}}
412{{define "C++.InitProc"}}
413  {{AssertType $ "Function"}}
414
415  {{$ext := GetAnnotation $ "extension"}}
416  {{if $ext}}
417    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
418  {{else}}
419    INIT_PROC(§
420  {{end}}
421
422  {{if GetAnnotation $ "optional"}}false{{else}}true{{end}}, §
423
424  {{if (Macro "IsInstanceDispatched" $)}}
425    instance, §
426  {{else}}
427    dev, §
428  {{end}}
429
430  {{Macro "BaseName" $}});
431{{end}}
432
433
434{{/*
435------------------------------------------------------------------------------
436  Emits true if a function is exported and instance-dispatched.
437------------------------------------------------------------------------------
438*/}}
439{{define "api.IsInstanceDispatchTableEntry"}}
440  {{AssertType $ "Function"}}
441
442  {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
443    {{/* deprecated and unused internally */}}
444    {{if not (eq $.Name "vkEnumerateDeviceLayerProperties")}}
445      true
446    {{end}}
447  {{end}}
448{{end}}
449
450
451{{/*
452------------------------------------------------------------------------------
453  Emits true if a function is exported and device-dispatched.
454------------------------------------------------------------------------------
455*/}}
456{{define "api.IsDeviceDispatchTableEntry"}}
457  {{AssertType $ "Function"}}
458
459  {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
460    true
461  {{end}}
462{{end}}
463
464
465{{/*
466------------------------------------------------------------------------------
467  Emits true if a function is intercepted by vulkan::api.
468------------------------------------------------------------------------------
469*/}}
470{{define "api.IsIntercepted"}}
471  {{AssertType $ "Function"}}
472
473  {{if (Macro "IsFunctionSupported" $)}}
474    {{/* Global functions cannot be dispatched at all */}}
475    {{     if (Macro "IsGloballyDispatched" $)}}true
476
477    {{/* VkPhysicalDevice functions that manage device layers */}}
478    {{else if eq $.Name "vkCreateDevice"}}true
479    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
480    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
481
482    {{/* Destroy functions of dispatchable objects */}}
483    {{else if eq $.Name "vkDestroyInstance"}}true
484    {{else if eq $.Name "vkDestroyDevice"}}true
485
486    {{end}}
487  {{end}}
488{{end}}
489
490
491{{/*
492-------------------------------------------------------------------------------
493  Emits INIT_PROC_EXT macro for vulkan::api.
494-------------------------------------------------------------------------------
495*/}}
496{{define "api.C++.DefineInitProcExtMacro"}}
497  // Exported extension functions may be invoked even when their extensions
498  // are disabled.  Dispatch to stubs when that happens.
499  #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
500      if (extensions[driver::ProcHook::ext])                    \
501        INIT_PROC(required, obj, proc);                         \
502      else                                                      \
503        data.dispatch.proc = disabled ## proc;                  \
504  } while(0)
505{{end}}
506
507
508{{/*
509-------------------------------------------------------------------------------
510  Emits a stub for an exported extension function.
511-------------------------------------------------------------------------------
512*/}}
513{{define "api.C++.DefineExtensionStub"}}
514  {{AssertType $ "Function"}}
515
516  {{$ext := GetAnnotation $ "extension"}}
517  {{if and $ext (Macro "IsFunctionExported" $)}}
518    {{$ext_name := index $ext.Arguments 0}}
519
520    {{$base := (Macro "BaseName" $)}}
521
522    {{$p0 := (index $.CallParameters 0)}}
523    {{$ptail := (Tail 1 $.CallParameters)}}
524
525    {{$first_type := (Macro "Parameter" $p0)}}
526    {{$tail_types := (ForEach $ptail "ParameterType" | JoinWith ", ")}}
527
528    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$first_type}}, {{$tail_types}}) {
529      driver::Logger({{$p0.Name}}).Err({{$p0.Name}}, §
530        "{{$ext_name}} not enabled. Exported {{$.Name}} not executed.");
531      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
532    }
533534  {{end}}
535{{end}}
536
537
538{{/*
539------------------------------------------------------------------------------
540  Emits code for vkGetInstanceProcAddr for function interception.
541------------------------------------------------------------------------------
542*/}}
543{{define "api.C++.InterceptInstanceProcAddr"}}
544  {{AssertType $ "API"}}
545
546  // global functions
547  if (instance == VK_NULL_HANDLE) {
548    {{range $f := AllCommands $}}
549      {{if (Macro "IsGloballyDispatched" $f)}}
550        if (strcmp(pName, "{{$f.Name}}") == 0) return §
551          reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}});
552      {{end}}
553    {{end}}
554555    ALOGE("invalid vkGetInstanceProcAddr(VK_NULL_HANDLE, \"%s\") call", pName);
556    return nullptr;
557  }
558559  static const struct Hook {
560    const char* name;
561    PFN_vkVoidFunction proc;
562  } hooks[] = {
563    {{range $f := SortBy (AllCommands $) "FunctionName"}}
564      {{if (Macro "IsFunctionExported" $f)}}
565        {{/* hide global functions */}}
566        {{if (Macro "IsGloballyDispatched" $f)}}
567          { "{{$f.Name}}", nullptr },
568
569        {{/* redirect intercepted functions */}}
570        {{else if (Macro "api.IsIntercepted" $f)}}
571          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
572            {{Macro "BaseName" $f}}) },
573
574        {{/* redirect vkGetInstanceProcAddr to itself */}}
575        {{else if eq $f.Name "vkGetInstanceProcAddr"}}
576          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}}) },
577
578        {{/* redirect device functions to themselves as a workaround for
579             layers that do not intercept in their vkGetInstanceProcAddr */}}
580        {{else if (Macro "IsDeviceDispatched" $f)}}
581          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "BaseName" $f}}) },
582
583        {{end}}
584      {{end}}
585    {{end}}
586  };
587  // clang-format on
588  constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
589  auto hook = std::lower_bound(
590    hooks, hooks + count, pName,
591    [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
592  if (hook <  hooks + count && strcmp(hook->name, pName) == 0) {
593    if (!hook->proc) {
594      vulkan::driver::Logger(instance).Err(
595        instance, "invalid vkGetInstanceProcAddr(%p, \"%s\") call",
596        instance, pName);
597    }
598    return hook->proc;
599  }
600  // clang-format off
601602{{end}}
603
604
605{{/*
606------------------------------------------------------------------------------
607  Emits code for vkGetDeviceProcAddr for function interception.
608------------------------------------------------------------------------------
609*/}}
610{{define "api.C++.InterceptDeviceProcAddr"}}
611  {{AssertType $ "API"}}
612
613  if (device == VK_NULL_HANDLE) {
614    ALOGE("invalid vkGetDeviceProcAddr(VK_NULL_HANDLE, ...) call");
615    return nullptr;
616  }
617618  static const char* const known_non_device_names[] = {
619    {{range $f := SortBy (AllCommands $) "FunctionName"}}
620      {{if (Macro "IsFunctionSupported" $f)}}
621        {{if not (Macro "IsDeviceDispatched" $f)}}
622          "{{$f.Name}}",
623        {{end}}
624      {{end}}
625    {{end}}
626  };
627  // clang-format on
628  constexpr size_t count = sizeof(known_non_device_names) /
629    sizeof(known_non_device_names[0]);
630  if (!pName ||
631      std::binary_search(
632        known_non_device_names, known_non_device_names + count, pName,
633        [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
634    vulkan::driver::Logger(device).Err(§
635      device, "invalid vkGetDeviceProcAddr(%p, \"%s\") call", device,§
636      (pName) ? pName : "(null)");
637    return nullptr;
638  }
639  // clang-format off
640641  {{range $f := AllCommands $}}
642    {{if (Macro "IsDeviceDispatched" $f)}}
643      {{     if (Macro "api.IsIntercepted" $f)}}
644        if (strcmp(pName, "{{$f.Name}}") == 0) return §
645          reinterpret_cast<PFN_vkVoidFunction>(§
646            {{Macro "BaseName" $f}});
647      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
648        if (strcmp(pName, "{{$f.Name}}") == 0) return §
649          reinterpret_cast<PFN_vkVoidFunction>(§
650            {{Macro "BaseName" $f}});
651      {{end}}
652    {{end}}
653  {{end}}
654655{{end}}
656
657
658{{/*
659------------------------------------------------------------------------------
660  Emits code to dispatch a function.
661------------------------------------------------------------------------------
662*/}}
663{{define "api.C++.Dispatch"}}
664  {{AssertType $ "Function"}}
665  {{if (Macro "api.IsIntercepted" $)}}
666    {{Error "$.Name should not be generated"}}
667  {{end}}
668
669  {{if not (IsVoid $.Return.Type)}}return §{{end}}
670
671  {{$p0 := index $.CallParameters 0}}
672  GetData({{$p0.Name}}).dispatch.§
673  {{Macro "BaseName" $}}({{Macro "Arguments" $}});
674{{end}}
675
676
677{{/*
678------------------------------------------------------------------------------
679  Emits a list of extensions intercepted by vulkan::driver.
680------------------------------------------------------------------------------
681*/}}
682{{define "driver.InterceptedExtensions"}}
683VK_ANDROID_native_buffer
684VK_EXT_debug_report
685VK_EXT_hdr_metadata
686VK_EXT_swapchain_colorspace
687VK_GOOGLE_display_timing
688VK_KHR_android_surface
689VK_KHR_incremental_present
690VK_KHR_shared_presentable_image
691VK_KHR_surface
692VK_KHR_swapchain
693VK_KHR_get_surface_capabilities2
694{{end}}
695
696
697{{/*
698------------------------------------------------------------------------------
699  Emits a list of extensions known to vulkan::driver.
700------------------------------------------------------------------------------
701*/}}
702{{define "driver.KnownExtensions"}}
703{{Macro "driver.InterceptedExtensions"}}
704VK_KHR_get_physical_device_properties2
705{{end}}
706
707
708{{/*
709------------------------------------------------------------------------------
710  Emits true if an extension is intercepted by vulkan::driver.
711------------------------------------------------------------------------------
712*/}}
713{{define "driver.IsExtensionIntercepted"}}
714  {{$ext_name := index $.Arguments 0}}
715  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
716
717  {{range $f := $filters}}
718    {{if eq $ext_name $f}}true{{end}}
719  {{end}}
720{{end}}
721
722
723{{/*
724------------------------------------------------------------------------------
725  Emits true if a function is intercepted by vulkan::driver.
726------------------------------------------------------------------------------
727*/}}
728{{define "driver.IsIntercepted"}}
729  {{AssertType $ "Function"}}
730
731  {{if (Macro "IsFunctionSupported" $)}}
732    {{/* Create functions of dispatchable objects */}}
733    {{     if eq $.Name "vkCreateInstance"}}true
734    {{else if eq $.Name "vkCreateDevice"}}true
735    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
736    {{else if eq $.Name "vkGetDeviceQueue"}}true
737    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
738
739    {{/* Destroy functions of dispatchable objects */}}
740    {{else if eq $.Name "vkDestroyInstance"}}true
741    {{else if eq $.Name "vkDestroyDevice"}}true
742
743    {{/* Enumeration of extensions */}}
744    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
745    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
746
747    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
748    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
749
750    {{end}}
751
752    {{$ext := GetAnnotation $ "extension"}}
753    {{if $ext}}
754      {{Macro "driver.IsExtensionIntercepted" $ext}}
755    {{end}}
756
757  {{end}}
758{{end}}
759
760
761{{/*
762------------------------------------------------------------------------------
763  Emits true if a function needs a ProcHook stub.
764------------------------------------------------------------------------------
765*/}}
766{{define "driver.NeedProcHookStub"}}
767  {{AssertType $ "Function"}}
768
769  {{if and (Macro "driver.IsIntercepted" $) (Macro "IsDeviceDispatched" $)}}
770    {{$ext := GetAnnotation $ "extension"}}
771    {{if $ext}}
772      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
773    {{end}}
774  {{end}}
775{{end}}
776
777
778{{/*
779-------------------------------------------------------------------------------
780  Emits definition of struct ProcHook.
781-------------------------------------------------------------------------------
782*/}}
783{{define "driver.C++.DefineProcHookType"}}
784  struct ProcHook {
785      enum Type {
786        GLOBAL,
787        INSTANCE,
788        DEVICE,
789      };
790
791      enum Extension {
792        {{$exts := Strings (Macro "driver.KnownExtensions") | SplitOn "\n"}}
793        {{range $e := $exts}}
794          {{TrimPrefix "VK_" $e}},
795        {{end}}
796797        EXTENSION_CORE, // valid bit
798        EXTENSION_COUNT,
799        EXTENSION_UNKNOWN,
800      };
801802      const char* name;
803      Type type;
804      Extension extension;
805806      PFN_vkVoidFunction proc;
807      PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
808  };
809{{end}}
810
811
812{{/*
813-------------------------------------------------------------------------------
814  Emits INIT_PROC_EXT macro for vulkan::driver.
815-------------------------------------------------------------------------------
816*/}}
817{{define "driver.C++.DefineInitProcExtMacro"}}
818  #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
819      if (extensions[ProcHook::ext])                            \
820        INIT_PROC(required, obj, proc);                         \
821  } while(0)
822{{end}}
823
824
825{{/*
826-------------------------------------------------------------------------------
827  Emits a stub for ProcHook::checked_proc.
828-------------------------------------------------------------------------------
829*/}}
830{{define "driver.C++.DefineProcHookStub"}}
831  {{AssertType $ "Function"}}
832
833  {{if (Macro "driver.NeedProcHookStub" $)}}
834    {{$ext := GetAnnotation $ "extension"}}
835    {{$ext_name := index $ext.Arguments 0}}
836
837    {{$base := (Macro "BaseName" $)}}
838
839    VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
840      {{$p0 := index $.CallParameters 0}}
841      {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
842
843      if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
844        {{if not (IsVoid $.Return.Type)}}return §{{end}}
845        {{$base}}({{Macro "Arguments" $}});
846      } else {
847        Logger({{$p0.Name}}).Err({{$p0.Name}}, "{{$ext_name}} not enabled. {{$.Name}} not executed.");
848        {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
849      }
850    }
851852  {{end}}
853{{end}}
854
855
856{{/*
857-------------------------------------------------------------------------------
858  Emits definition of a global ProcHook.
859-------------------------------------------------------------------------------
860*/}}
861{{define "driver.C++.DefineGlobalProcHook"}}
862  {{AssertType $ "Function"}}
863
864  {{$base := (Macro "BaseName" $)}}
865
866  {{$ext := GetAnnotation $ "extension"}}
867  {{if $ext}}
868    {{Error "invalid global extension"}}
869  {{end}}
870
871  {
872    "{{$.Name}}",
873    ProcHook::GLOBAL,
874    ProcHook::EXTENSION_CORE,
875    reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
876    nullptr,
877  },
878{{end}}
879
880
881{{/*
882-------------------------------------------------------------------------------
883  Emits definition of an instance ProcHook.
884-------------------------------------------------------------------------------
885*/}}
886{{define "driver.C++.DefineInstanceProcHook"}}
887  {{AssertType $ "Function"}}
888
889  {{$base := (Macro "BaseName" $)}}
890
891  {
892    "{{$.Name}}",
893    ProcHook::INSTANCE,
894
895    {{$ext := GetAnnotation $ "extension"}}
896    {{if $ext}}
897      ProcHook::{{Macro "BaseName" $ext}},
898
899      {{if (Macro "IsExtensionInternal" $ext)}}
900        nullptr,
901        nullptr,
902      {{else}}
903        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
904        nullptr,
905      {{end}}
906    {{else}}
907      ProcHook::EXTENSION_CORE,
908      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
909      nullptr,
910    {{end}}
911  },
912{{end}}
913
914
915{{/*
916-------------------------------------------------------------------------------
917  Emits definition of a device ProcHook.
918-------------------------------------------------------------------------------
919*/}}
920{{define "driver.C++.DefineDeviceProcHook"}}
921  {{AssertType $ "Function"}}
922
923  {{$base := (Macro "BaseName" $)}}
924
925  {
926    "{{$.Name}}",
927    ProcHook::DEVICE,
928
929    {{$ext := GetAnnotation $ "extension"}}
930    {{if $ext}}
931      ProcHook::{{Macro "BaseName" $ext}},
932
933      {{if (Macro "IsExtensionInternal" $ext)}}
934        nullptr,
935        nullptr,
936      {{else}}
937        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
938        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
939      {{end}}
940    {{else}}
941      ProcHook::EXTENSION_CORE,
942      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
943      nullptr,
944    {{end}}
945  },
946{{end}}
947
948
949{{/*
950-------------------------------------------------------------------------------
951  Emits true if a function is needed by vulkan::driver.
952-------------------------------------------------------------------------------
953*/}}
954{{define "driver.IsDriverTableEntry"}}
955  {{AssertType $ "Function"}}
956
957  {{if (Macro "IsFunctionSupported" $)}}
958    {{/* Create functions of dispatchable objects */}}
959    {{     if eq $.Name "vkCreateDevice"}}true
960    {{else if eq $.Name "vkGetDeviceQueue"}}true
961    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
962
963    {{/* Destroy functions of dispatchable objects */}}
964    {{else if eq $.Name "vkDestroyInstance"}}true
965    {{else if eq $.Name "vkDestroyDevice"}}true
966
967    {{/* Enumeration of extensions */}}
968    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
969
970    {{/* We cache physical devices in loader.cpp */}}
971    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
972
973    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
974    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
975
976    {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
977    {{else if eq $.Name "vkCreateImage"}}true
978    {{else if eq $.Name "vkDestroyImage"}}true
979
980    {{else if eq $.Name "vkGetPhysicalDeviceProperties"}}true
981    {{else if eq $.Name "vkGetPhysicalDeviceProperties2KHR"}}true
982    {{end}}
983
984    {{$ext := GetAnnotation $ "extension"}}
985    {{if $ext}}
986      {{$ext_name := index $ext.Arguments 0}}
987      {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
988      {{else if eq $ext_name "VK_EXT_debug_report"}}true
989      {{end}}
990    {{end}}
991  {{end}}
992{{end}}
993
994
995{{/*
996------------------------------------------------------------------------------
997  Emits true if an instance-dispatched function is needed by vulkan::driver.
998------------------------------------------------------------------------------
999*/}}
1000{{define "driver.IsInstanceDriverTableEntry"}}
1001  {{AssertType $ "Function"}}
1002
1003  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
1004    true
1005  {{end}}
1006{{end}}
1007
1008
1009{{/*
1010------------------------------------------------------------------------------
1011  Emits true if a device-dispatched function is needed by vulkan::driver.
1012------------------------------------------------------------------------------
1013*/}}
1014{{define "driver.IsDeviceDriverTableEntry"}}
1015  {{AssertType $ "Function"}}
1016
1017  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
1018    true
1019  {{end}}
1020{{end}}
1021
1022
1023{{/*
1024-------------------------------------------------------------------------------
1025  Emits a function/extension name without the "vk"/"VK_" prefix.
1026-------------------------------------------------------------------------------
1027*/}}
1028{{define "BaseName"}}
1029  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
1030  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
1031  {{else}}{{Error "invalid use of BaseName"}}
1032  {{end}}
1033{{end}}
1034
1035
1036{{/*
1037-------------------------------------------------------------------------------
1038  Emits a comma-separated list of C parameter names for the given command.
1039-------------------------------------------------------------------------------
1040*/}}
1041{{define "Arguments"}}
1042  {{AssertType $ "Function"}}
1043
1044  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
1045{{end}}
1046
1047
1048{{/*
1049------------------------------------------------------------------------------
1050------------------------------------------------------------------------------
1051*/}}
1052{{define "IsGloballyDispatched"}}
1053  {{AssertType $ "Function"}}
1054  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
1055    true
1056  {{end}}
1057{{end}}
1058
1059
1060{{/*
1061------------------------------------------------------------------------------
1062  Emit "true" for supported functions that undergo table dispatch. Only global
1063  functions and functions handled in the loader top without calling into
1064  lower layers are not dispatched.
1065------------------------------------------------------------------------------
1066*/}}
1067{{define "IsInstanceDispatched"}}
1068  {{AssertType $ "Function"}}
1069  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
1070    true
1071  {{end}}
1072{{end}}
1073
1074
1075{{/*
1076------------------------------------------------------------------------------
1077  Emit "true" for supported functions that can have device-specific dispatch.
1078------------------------------------------------------------------------------
1079*/}}
1080{{define "IsDeviceDispatched"}}
1081  {{AssertType $ "Function"}}
1082  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
1083    true
1084  {{end}}
1085{{end}}
1086
1087
1088{{/*
1089------------------------------------------------------------------------------
1090  Emit "true" if a function is core or from a supportable extension.
1091------------------------------------------------------------------------------
1092*/}}
1093{{define "IsFunctionSupported"}}
1094  {{AssertType $ "Function"}}
1095  {{if not (GetAnnotation $ "pfn")}}
1096    {{$ext := GetAnnotation $ "extension"}}
1097    {{if not $ext}}true
1098    {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
1099    {{end}}
1100  {{end}}
1101{{end}}
1102
1103
1104{{/*
1105------------------------------------------------------------------------------
1106  Decides whether a function should be exported from the Android Vulkan
1107  library. Functions in the core API and in loader extensions are exported.
1108------------------------------------------------------------------------------
1109*/}}
1110{{define "IsFunctionExported"}}
1111  {{AssertType $ "Function"}}
1112
1113  {{if (Macro "IsFunctionSupported" $)}}
1114    {{$ext := GetAnnotation $ "extension"}}
1115    {{if $ext}}
1116      {{Macro "IsExtensionExported" $ext}}
1117    {{else}}
1118      true
1119    {{end}}
1120  {{end}}
1121{{end}}
1122
1123
1124{{/*
1125------------------------------------------------------------------------------
1126  Emit "true" if an extension is unsupportable on Android.
1127------------------------------------------------------------------------------
1128*/}}
1129{{define "IsExtensionBlacklisted"}}
1130  {{$ext := index $.Arguments 0}}
1131  {{     if eq $ext "VK_KHR_display"}}true
1132  {{else if eq $ext "VK_KHR_display_swapchain"}}true
1133  {{else if eq $ext "VK_KHR_mir_surface"}}true
1134  {{else if eq $ext "VK_KHR_xcb_surface"}}true
1135  {{else if eq $ext "VK_KHR_xlib_surface"}}true
1136  {{else if eq $ext "VK_KHR_wayland_surface"}}true
1137  {{else if eq $ext "VK_KHR_win32_surface"}}true
1138  {{else if eq $ext "VK_KHX_external_memory_win32"}}true
1139  {{else if eq $ext "VK_KHX_win32_keyed_mutex"}}true
1140  {{else if eq $ext "VK_KHX_external_semaphore_win32"}}true
1141  {{else if eq $ext "VK_EXT_acquire_xlib_display"}}true
1142  {{else if eq $ext "VK_EXT_direct_mode_display"}}true
1143  {{else if eq $ext "VK_EXT_display_surface_counter"}}true
1144  {{else if eq $ext "VK_EXT_display_control"}}true
1145  {{else if eq $ext "VK_MVK_ios_surface"}}true
1146  {{else if eq $ext "VK_MVK_macos_surface"}}true
1147  {{else if eq $ext "VK_NN_vi_surface"}}true
1148  {{else if eq $ext "VK_NV_external_memory_win32"}}true
1149  {{else if eq $ext "VK_NV_win32_keyed_mutex"}}true
1150  {{end}}
1151{{end}}
1152
1153
1154{{/*
1155------------------------------------------------------------------------------
1156  Reports whether an extension has functions exported by the loader.
1157  E.g. applications can directly link to an extension function.
1158  Currently only support WSI extensions this way.
1159------------------------------------------------------------------------------
1160*/}}
1161{{define "IsExtensionExported"}}
1162  {{$ext := index $.Arguments 0}}
1163  {{     if eq $ext "VK_KHR_surface"}}true
1164  {{else if eq $ext "VK_KHR_swapchain"}}true
1165  {{else if eq $ext "VK_KHR_android_surface"}}true
1166  {{end}}
1167{{end}}
1168
1169
1170{{/*
1171------------------------------------------------------------------------------
1172  Reports whether an extension is internal to the loader and drivers,
1173  so the loader should not enumerate it.
1174------------------------------------------------------------------------------
1175*/}}
1176{{define "IsExtensionInternal"}}
1177  {{$ext := index $.Arguments 0}}
1178  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
1179  {{end}}
1180{{end}}
1181