code-generator.tmpl revision 36cc00a1739f7d926cc20671ae9900a5460dd6ae
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#include "api.h"
9899namespace vulkan {«
100namespace api {«
101102{{Macro "C++.DefineInitProcMacro" "dispatch"}}
103104{{Macro "api.C++.DefineInitProcExtMacro"}}
105106namespace {«
107108// clang-format off
109110{{range $f := AllCommands $}}
111  {{Macro "api.C++.DefineExtensionStub" $f}}
112{{end}}
113// clang-format on
114115»} // anonymous
116117bool InitDispatchTable(
118    VkInstance instance,
119    PFN_vkGetInstanceProcAddr get_proc,
120    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
121    auto& data = GetData(instance);
122    bool success = true;
123124    // clang-format off
125    {{range $f := AllCommands $}}
126      {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
127        {{Macro "C++.InitProc" $f}}
128      {{end}}
129    {{end}}
130    // clang-format on
131132    return success;
133}
134135bool InitDispatchTable(
136    VkDevice dev,
137    PFN_vkGetDeviceProcAddr get_proc,
138    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
139    auto& data = GetData(dev);
140    bool success = true;
141142    // clang-format off
143    {{range $f := AllCommands $}}
144      {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
145        {{Macro "C++.InitProc" $f}}
146      {{end}}
147    {{end}}
148    // clang-format on
149150    return success;
151}
152153»} // namespace api
154»} // namespace vulkan
155156// clang-format off
157158{{range $f := AllCommands $}}
159  {{if (Macro "IsFunctionExported" $f)}}
160    __attribute__((visibility("default")))
161    VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
162      {{     if eq $f.Name "vkGetInstanceProcAddr"}}
163        {{Macro "api.C++.InterceptInstanceProcAddr" $}}
164      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
165        {{Macro "api.C++.InterceptDeviceProcAddr" $}}
166      {{end}}
167
168      {{Macro "api.C++.Dispatch" $f}}
169    }
170171  {{end}}
172{{end}}
173174// clang-format on
175¶{{end}}
176
177
178{{/*
179-------------------------------------------------------------------------------
180  driver_gen.h
181-------------------------------------------------------------------------------
182*/}}
183{{define "driver_gen.h"}}
184{{Macro "Copyright"}}
185186// WARNING: This file is generated. See ../README.md for instructions.
187188#ifndef LIBVULKAN_DRIVER_GEN_H
189#define LIBVULKAN_DRIVER_GEN_H
190191#include <bitset>
192#include <vulkan/vulkan.h>
193#include <vulkan/vk_android_native_buffer.h>
194195namespace vulkan {«
196namespace driver {«
197198{{Macro "driver.C++.DefineProcHookType"}}
199200struct InstanceDriverTable {
201  // clang-format off
202  {{range $f := AllCommands $}}
203    {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
204      {{Macro "C++.DeclareTableEntry" $f}};
205    {{end}}
206  {{end}}
207  // clang-format on
208};
209210struct DeviceDriverTable {
211  // clang-format off
212  {{range $f := AllCommands $}}
213    {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
214      {{Macro "C++.DeclareTableEntry" $f}};
215    {{end}}
216  {{end}}
217  // clang-format on
218};
219220const ProcHook* GetProcHook(const char* name);
221ProcHook::Extension GetProcHookExtension(const char* name);
222223bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
224                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
225bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
226                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
227228»} // namespace driver
229»} // namespace vulkan
230231#endif // LIBVULKAN_DRIVER_TABLE_H
232¶{{end}}
233
234
235{{/*
236-------------------------------------------------------------------------------
237  driver_gen.cpp
238-------------------------------------------------------------------------------
239*/}}
240{{define "driver_gen.cpp"}}
241{{Macro "Copyright"}}
242243// WARNING: This file is generated. See ../README.md for instructions.
244245#include <string.h>
246#include <algorithm>
247#include <log/log.h>
248249#include "driver.h"
250251namespace vulkan {«
252namespace driver {«
253254namespace {«
255256// clang-format off
257258{{range $f := AllCommands $}}
259  {{Macro "driver.C++.DefineProcHookStub" $f}}
260{{end}}
261// clang-format on
262263const ProcHook g_proc_hooks[] = {
264  // clang-format off
265  {{range $f := SortBy (AllCommands $) "FunctionName"}}
266    {{if (Macro "driver.IsIntercepted" $f)}}
267      {{     if (Macro "IsGloballyDispatched" $f)}}
268        {{Macro "driver.C++.DefineGlobalProcHook" $f}}
269      {{else if (Macro "IsInstanceDispatched" $f)}}
270        {{Macro "driver.C++.DefineInstanceProcHook" $f}}
271      {{else if (Macro "IsDeviceDispatched" $f)}}
272        {{Macro "driver.C++.DefineDeviceProcHook" $f}}
273      {{end}}
274    {{end}}
275  {{end}}
276  // clang-format on
277};
278279»} // anonymous
280281const ProcHook* GetProcHook(const char* name) {
282    const auto& begin = g_proc_hooks;
283    const auto& end = g_proc_hooks +
284      sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
285    const auto hook = std::lower_bound(begin, end, name,
286        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
287    return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
288}
289290ProcHook::Extension GetProcHookExtension(const char* name) {
291  {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
292  // clang-format off
293  {{range $e := $exts}}
294    if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
295  {{end}}
296  // clang-format on
297  return ProcHook::EXTENSION_UNKNOWN;
298}
299300{{Macro "C++.DefineInitProcMacro" "driver"}}
301302{{Macro "driver.C++.DefineInitProcExtMacro"}}
303304bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
305                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
306{
307    auto& data = GetData(instance);
308    bool success = true;
309310    // clang-format off
311    {{range $f := AllCommands $}}
312      {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
313        {{Macro "C++.InitProc" $f}}
314      {{end}}
315    {{end}}
316    // clang-format on
317318    return success;
319}
320321bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
322                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
323{
324    auto& data = GetData(dev);
325    bool success = true;
326327    // clang-format off
328    {{range $f := AllCommands $}}
329      {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
330        {{Macro "C++.InitProc" $f}}
331      {{end}}
332    {{end}}
333    // clang-format on
334335    return success;
336}
337338»} // namespace driver
339»} // namespace vulkan
340341// clang-format on
342¶{{end}}
343
344
345{{/*
346------------------------------------------------------------------------------
347  Emits a declaration of a dispatch/driver table entry.
348------------------------------------------------------------------------------
349*/}}
350{{define "C++.DeclareTableEntry"}}
351  {{AssertType $ "Function"}}
352
353  {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
354{{end}}
355
356
357{{/*
358-------------------------------------------------------------------------------
359  Emits INIT_PROC macro.
360-------------------------------------------------------------------------------
361*/}}
362{{define "C++.DefineInitProcMacro"}}
363  #define UNLIKELY(expr) __builtin_expect((expr), 0)
364365  #define INIT_PROC(obj, proc) do {                             \
366      data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
367              get_proc(obj, "vk" # proc));                      \
368      if (UNLIKELY(!data.{{$}}.proc)) {                         \
369          ALOGE("missing " # obj " proc: vk" # proc);           \
370          success = false;                                      \
371      }                                                         \
372  } while(0)
373{{end}}
374
375
376{{/*
377-------------------------------------------------------------------------------
378  Emits code to invoke INIT_PROC or INIT_PROC_EXT.
379-------------------------------------------------------------------------------
380*/}}
381{{define "C++.InitProc"}}
382  {{AssertType $ "Function"}}
383
384  {{$ext := GetAnnotation $ "extension"}}
385  {{if $ext}}
386    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
387  {{else}}
388    INIT_PROC(§
389  {{end}}
390
391  {{if (Macro "IsInstanceDispatched" $)}}
392    instance, §
393  {{else}}
394    dev, §
395  {{end}}
396
397  {{Macro "BaseName" $}});
398{{end}}
399
400
401{{/*
402------------------------------------------------------------------------------
403  Emits true if a function is exported and instance-dispatched.
404------------------------------------------------------------------------------
405*/}}
406{{define "api.IsInstanceDispatchTableEntry"}}
407  {{AssertType $ "Function"}}
408
409  {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
410    true
411  {{end}}
412{{end}}
413
414
415{{/*
416------------------------------------------------------------------------------
417  Emits true if a function is exported and device-dispatched.
418------------------------------------------------------------------------------
419*/}}
420{{define "api.IsDeviceDispatchTableEntry"}}
421  {{AssertType $ "Function"}}
422
423  {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
424    true
425  {{end}}
426{{end}}
427
428
429{{/*
430------------------------------------------------------------------------------
431  Emits true if a function is intercepted by vulkan::api.
432------------------------------------------------------------------------------
433*/}}
434{{define "api.IsIntercepted"}}
435  {{AssertType $ "Function"}}
436
437  {{if (Macro "IsFunctionSupported" $)}}
438    {{/* Global functions cannot be dispatched at all */}}
439    {{     if (Macro "IsGloballyDispatched" $)}}true
440
441    {{/* VkPhysicalDevice functions that manage device layers */}}
442    {{else if eq $.Name "vkCreateDevice"}}true
443    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
444    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
445
446    {{/* Destroy functions of dispatchable objects */}}
447    {{else if eq $.Name "vkDestroyInstance"}}true
448    {{else if eq $.Name "vkDestroyDevice"}}true
449
450    {{end}}
451  {{end}}
452{{end}}
453
454
455{{/*
456-------------------------------------------------------------------------------
457  Emits INIT_PROC_EXT macro for vulkan::api.
458-------------------------------------------------------------------------------
459*/}}
460{{define "api.C++.DefineInitProcExtMacro"}}
461  // Exported extension functions may be invoked even when their extensions
462  // are disabled.  Dispatch to stubs when that happens.
463  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
464      if (extensions[driver::ProcHook::ext])                    \
465        INIT_PROC(obj, proc);                                   \
466      else                                                      \
467        data.dispatch.proc = disabled ## proc;                  \
468  } while(0)
469{{end}}
470
471
472{{/*
473-------------------------------------------------------------------------------
474  Emits a stub for an exported extension function.
475-------------------------------------------------------------------------------
476*/}}
477{{define "api.C++.DefineExtensionStub"}}
478  {{AssertType $ "Function"}}
479
480  {{$ext := GetAnnotation $ "extension"}}
481  {{if and $ext (Macro "IsFunctionExported" $)}}
482    {{$ext_name := index $ext.Arguments 0}}
483
484    {{$base := (Macro "BaseName" $)}}
485    {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
486
487    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$unnamed_params}}) {
488      ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
489      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
490    }
491492  {{end}}
493{{end}}
494
495
496{{/*
497------------------------------------------------------------------------------
498  Emits code for vkGetInstanceProcAddr for function interception.
499------------------------------------------------------------------------------
500*/}}
501{{define "api.C++.InterceptInstanceProcAddr"}}
502  {{AssertType $ "API"}}
503
504  // global functions
505  if (!instance) {
506    {{range $f := AllCommands $}}
507      {{if (Macro "IsGloballyDispatched" $f)}}
508        if (strcmp(pName, "{{$f.Name}}") == 0) return §
509          reinterpret_cast<PFN_vkVoidFunction>(§
510            vulkan::api::{{Macro "BaseName" $f}});
511      {{end}}
512    {{end}}
513514    ALOGE("vkGetInstanceProcAddr called with %s without instance",  pName);
515    return nullptr;
516  }
517518  static const struct Hook {
519    const char* name;
520    PFN_vkVoidFunction proc;
521  } hooks[] = {
522    {{range $f := SortBy (AllCommands $) "FunctionName"}}
523      {{if (Macro "IsFunctionExported" $f)}}
524        {{/* hide global functions */}}
525        {{if (Macro "IsGloballyDispatched" $f)}}
526          { "{{$f.Name}}", nullptr },
527
528        {{/* redirect intercepted functions */}}
529        {{else if (Macro "api.IsIntercepted" $f)}}
530          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
531            vulkan::api::{{Macro "BaseName" $f}}) },
532
533        {{/* redirect vkGetInstanceProcAddr to itself */}}
534        {{else if eq $f.Name "vkGetInstanceProcAddr"}}
535          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
536
537        {{/* redirect device functions to themselves as a workaround for
538             layers that do not intercept in their vkGetInstanceProcAddr */}}
539        {{else if (Macro "IsDeviceDispatched" $f)}}
540          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
541
542        {{end}}
543      {{end}}
544    {{end}}
545  };
546  // clang-format on
547  constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
548  auto hook = std::lower_bound(
549    hooks, hooks + count, pName,
550    [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
551  if (hook <  hooks + count && strcmp(hook->name, pName) == 0) {
552    if (!hook->proc)
553      ALOGE("vkGetInstanceProcAddr called with %s with instance",  pName);
554    return hook->proc;
555  }
556  // clang-format off
557558{{end}}
559
560
561{{/*
562------------------------------------------------------------------------------
563  Emits code for vkGetDeviceProcAddr for function interception.
564------------------------------------------------------------------------------
565*/}}
566{{define "api.C++.InterceptDeviceProcAddr"}}
567  {{AssertType $ "API"}}
568
569  if (device == VK_NULL_HANDLE) {
570    ALOGE("vkGetDeviceProcAddr called with invalid device");
571    return nullptr;
572  }
573574  static const char* const known_non_device_names[] = {
575    {{range $f := SortBy (AllCommands $) "FunctionName"}}
576      {{if (Macro "IsFunctionSupported" $f)}}
577        {{if not (Macro "IsDeviceDispatched" $f)}}
578          "{{$f.Name}}",
579        {{end}}
580      {{end}}
581    {{end}}
582  };
583  // clang-format on
584  constexpr size_t count = sizeof(known_non_device_names) /
585    sizeof(known_non_device_names[0]);
586  if (!pName ||
587      std::binary_search(
588        known_non_device_names, known_non_device_names + count, pName,
589        [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
590    ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
591    return nullptr;
592  }
593  // clang-format off
594595  {{range $f := AllCommands $}}
596    {{if (Macro "IsDeviceDispatched" $f)}}
597      {{     if (Macro "api.IsIntercepted" $f)}}
598        if (strcmp(pName, "{{$f.Name}}") == 0) return §
599          reinterpret_cast<PFN_vkVoidFunction>(§
600            vulkan::api::{{Macro "BaseName" $f}});
601      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
602        if (strcmp(pName, "{{$f.Name}}") == 0) return §
603          reinterpret_cast<PFN_vkVoidFunction>(§
604            {{$f.Name}});
605      {{end}}
606    {{end}}
607  {{end}}
608609{{end}}
610
611
612{{/*
613------------------------------------------------------------------------------
614  Emits code to dispatch a function.
615------------------------------------------------------------------------------
616*/}}
617{{define "api.C++.Dispatch"}}
618  {{AssertType $ "Function"}}
619
620  {{if (Macro "api.IsIntercepted" $)}}// call into api.cpp{{end}}
621  {{if not (IsVoid $.Return.Type)}}return §{{end}}
622
623  {{if (Macro "api.IsIntercepted" $)}}
624    vulkan::api::§
625  {{else}}
626    {{$p0 := index $.CallParameters 0}}
627    vulkan::api::GetData({{$p0.Name}}).dispatch.§
628  {{end}}
629
630  {{Macro "BaseName" $}}({{Macro "Arguments" $}});
631{{end}}
632
633
634{{/*
635------------------------------------------------------------------------------
636  Emits a list of extensions intercepted by vulkan::driver.
637------------------------------------------------------------------------------
638*/}}
639{{define "driver.InterceptedExtensions"}}
640VK_ANDROID_native_buffer
641VK_EXT_debug_report
642VK_KHR_android_surface
643VK_KHR_surface
644VK_KHR_swapchain
645{{end}}
646
647
648{{/*
649------------------------------------------------------------------------------
650  Emits true if an extension is intercepted by vulkan::driver.
651------------------------------------------------------------------------------
652*/}}
653{{define "driver.IsExtensionIntercepted"}}
654  {{$ext_name := index $.Arguments 0}}
655  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
656
657  {{range $f := $filters}}
658    {{if eq $ext_name $f}}true{{end}}
659  {{end}}
660{{end}}
661
662
663{{/*
664------------------------------------------------------------------------------
665  Emits true if a function is intercepted by vulkan::driver.
666------------------------------------------------------------------------------
667*/}}
668{{define "driver.IsIntercepted"}}
669  {{AssertType $ "Function"}}
670
671  {{if (Macro "IsFunctionSupported" $)}}
672    {{/* Create functions of dispatchable objects */}}
673    {{     if eq $.Name "vkCreateInstance"}}true
674    {{else if eq $.Name "vkCreateDevice"}}true
675    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
676    {{else if eq $.Name "vkGetDeviceQueue"}}true
677    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
678
679    {{/* Destroy functions of dispatchable objects */}}
680    {{else if eq $.Name "vkDestroyInstance"}}true
681    {{else if eq $.Name "vkDestroyDevice"}}true
682
683    {{/* Enumeration of extensions */}}
684    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
685    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
686
687    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
688    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
689
690    {{end}}
691
692    {{$ext := GetAnnotation $ "extension"}}
693    {{if $ext}}
694      {{Macro "driver.IsExtensionIntercepted" $ext}}
695    {{end}}
696
697  {{end}}
698{{end}}
699
700
701{{/*
702------------------------------------------------------------------------------
703  Emits true if a function needs a ProcHook stub.
704------------------------------------------------------------------------------
705*/}}
706{{define "driver.NeedProcHookStub"}}
707  {{AssertType $ "Function"}}
708
709  {{if and (Macro "driver.IsIntercepted" $) (Macro "IsDeviceDispatched" $)}}
710    {{$ext := GetAnnotation $ "extension"}}
711    {{if $ext}}
712      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
713    {{end}}
714  {{end}}
715{{end}}
716
717
718{{/*
719-------------------------------------------------------------------------------
720  Emits definition of struct ProcHook.
721-------------------------------------------------------------------------------
722*/}}
723{{define "driver.C++.DefineProcHookType"}}
724  struct ProcHook {
725      enum Type {
726        GLOBAL,
727        INSTANCE,
728        DEVICE,
729      };
730
731      enum Extension {
732        {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
733        {{range $e := $exts}}
734          {{TrimPrefix "VK_" $e}},
735        {{end}}
736737        EXTENSION_CORE, // valid bit
738        EXTENSION_COUNT,
739        EXTENSION_UNKNOWN,
740      };
741742      const char* name;
743      Type type;
744      Extension extension;
745746      PFN_vkVoidFunction proc;
747      PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
748  };
749{{end}}
750
751
752{{/*
753-------------------------------------------------------------------------------
754  Emits INIT_PROC_EXT macro for vulkan::driver.
755-------------------------------------------------------------------------------
756*/}}
757{{define "driver.C++.DefineInitProcExtMacro"}}
758  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
759      if (extensions[ProcHook::ext])                            \
760        INIT_PROC(obj, proc);                                   \
761  } while(0)
762{{end}}
763
764
765{{/*
766-------------------------------------------------------------------------------
767  Emits a stub for ProcHook::checked_proc.
768-------------------------------------------------------------------------------
769*/}}
770{{define "driver.C++.DefineProcHookStub"}}
771  {{AssertType $ "Function"}}
772
773  {{if (Macro "driver.NeedProcHookStub" $)}}
774    {{$ext := GetAnnotation $ "extension"}}
775    {{$ext_name := index $ext.Arguments 0}}
776
777    {{$base := (Macro "BaseName" $)}}
778    {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
779
780    VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
781      {{$p0 := index $.CallParameters 0}}
782      {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
783
784      if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
785        {{if not (IsVoid $.Return.Type)}}return §{{end}}
786        {{$base}}({{Macro "Arguments" $}});
787      } else {
788        ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
789        {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
790      }
791    }
792793  {{end}}
794{{end}}
795
796
797{{/*
798-------------------------------------------------------------------------------
799  Emits definition of a global ProcHook.
800-------------------------------------------------------------------------------
801*/}}
802{{define "driver.C++.DefineGlobalProcHook"}}
803  {{AssertType $ "Function"}}
804
805  {{$base := (Macro "BaseName" $)}}
806
807  {{$ext := GetAnnotation $ "extension"}}
808  {{if $ext}}
809    {{Error "invalid global extension"}}
810  {{end}}
811
812  {
813    "{{$.Name}}",
814    ProcHook::GLOBAL,
815    ProcHook::EXTENSION_CORE,
816    reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
817    nullptr,
818  },
819{{end}}
820
821
822{{/*
823-------------------------------------------------------------------------------
824  Emits definition of an instance ProcHook.
825-------------------------------------------------------------------------------
826*/}}
827{{define "driver.C++.DefineInstanceProcHook"}}
828  {{AssertType $ "Function"}}
829
830  {{$base := (Macro "BaseName" $)}}
831
832  {
833    "{{$.Name}}",
834    ProcHook::INSTANCE,
835
836    {{$ext := GetAnnotation $ "extension"}}
837    {{if $ext}}
838      ProcHook::{{Macro "BaseName" $ext}},
839
840      {{if (Macro "IsExtensionInternal" $ext)}}
841        nullptr,
842        nullptr,
843      {{else}}
844        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
845        nullptr,
846      {{end}}
847    {{else}}
848      ProcHook::EXTENSION_CORE,
849      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
850      nullptr,
851    {{end}}
852  },
853{{end}}
854
855
856{{/*
857-------------------------------------------------------------------------------
858  Emits definition of a device ProcHook.
859-------------------------------------------------------------------------------
860*/}}
861{{define "driver.C++.DefineDeviceProcHook"}}
862  {{AssertType $ "Function"}}
863
864  {{$base := (Macro "BaseName" $)}}
865
866  {
867    "{{$.Name}}",
868    ProcHook::DEVICE,
869
870    {{$ext := GetAnnotation $ "extension"}}
871    {{if $ext}}
872      ProcHook::{{Macro "BaseName" $ext}},
873
874      {{if (Macro "IsExtensionInternal" $ext)}}
875        nullptr,
876        nullptr,
877      {{else}}
878        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
879        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
880      {{end}}
881    {{else}}
882      ProcHook::EXTENSION_CORE,
883      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
884      nullptr,
885    {{end}}
886  },
887{{end}}
888
889
890{{/*
891-------------------------------------------------------------------------------
892  Emits true if a function is needed by vulkan::driver.
893-------------------------------------------------------------------------------
894*/}}
895{{define "driver.IsDriverTableEntry"}}
896  {{AssertType $ "Function"}}
897
898  {{if (Macro "IsFunctionSupported" $)}}
899    {{/* Create functions of dispatchable objects */}}
900    {{     if eq $.Name "vkCreateDevice"}}true
901    {{else if eq $.Name "vkGetDeviceQueue"}}true
902    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
903
904    {{/* Destroy functions of dispatchable objects */}}
905    {{else if eq $.Name "vkDestroyInstance"}}true
906    {{else if eq $.Name "vkDestroyDevice"}}true
907
908    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
909
910    {{/* Enumeration of extensions */}}
911    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
912
913    {{/* We cache physical devices in loader.cpp */}}
914    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
915
916    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
917    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
918
919    {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
920    {{else if eq $.Name "vkCreateImage"}}true
921    {{else if eq $.Name "vkDestroyImage"}}true
922
923    {{end}}
924
925    {{$ext := GetAnnotation $ "extension"}}
926    {{if $ext}}
927      {{$ext_name := index $ext.Arguments 0}}
928      {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
929      {{else if eq $ext_name "VK_EXT_debug_report"}}true
930      {{end}}
931    {{end}}
932  {{end}}
933{{end}}
934
935
936{{/*
937------------------------------------------------------------------------------
938  Emits true if an instance-dispatched function is needed by vulkan::driver.
939------------------------------------------------------------------------------
940*/}}
941{{define "driver.IsInstanceDriverTableEntry"}}
942  {{AssertType $ "Function"}}
943
944  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
945    true
946  {{end}}
947{{end}}
948
949
950{{/*
951------------------------------------------------------------------------------
952  Emits true if a device-dispatched function is needed by vulkan::driver.
953------------------------------------------------------------------------------
954*/}}
955{{define "driver.IsDeviceDriverTableEntry"}}
956  {{AssertType $ "Function"}}
957
958  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
959    true
960  {{end}}
961{{end}}
962
963
964{{/*
965-------------------------------------------------------------------------------
966  Emits a function/extension name without the "vk"/"VK_" prefix.
967-------------------------------------------------------------------------------
968*/}}
969{{define "BaseName"}}
970  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
971  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
972  {{else}}{{Error "invalid use of BaseName"}}
973  {{end}}
974{{end}}
975
976
977{{/*
978-------------------------------------------------------------------------------
979  Emits a comma-separated list of C parameter names for the given command.
980-------------------------------------------------------------------------------
981*/}}
982{{define "Arguments"}}
983  {{AssertType $ "Function"}}
984
985  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
986{{end}}
987
988
989{{/*
990------------------------------------------------------------------------------
991------------------------------------------------------------------------------
992*/}}
993{{define "IsGloballyDispatched"}}
994  {{AssertType $ "Function"}}
995  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
996    true
997  {{end}}
998{{end}}
999
1000
1001{{/*
1002------------------------------------------------------------------------------
1003  Emit "true" for supported functions that undergo table dispatch. Only global
1004  functions and functions handled in the loader top without calling into
1005  lower layers are not dispatched.
1006------------------------------------------------------------------------------
1007*/}}
1008{{define "IsInstanceDispatched"}}
1009  {{AssertType $ "Function"}}
1010  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
1011    true
1012  {{end}}
1013{{end}}
1014
1015
1016{{/*
1017------------------------------------------------------------------------------
1018  Emit "true" for supported functions that can have device-specific dispatch.
1019------------------------------------------------------------------------------
1020*/}}
1021{{define "IsDeviceDispatched"}}
1022  {{AssertType $ "Function"}}
1023  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
1024    true
1025  {{end}}
1026{{end}}
1027
1028
1029{{/*
1030------------------------------------------------------------------------------
1031  Emit "true" if a function is core or from a supportable extension.
1032------------------------------------------------------------------------------
1033*/}}
1034{{define "IsFunctionSupported"}}
1035  {{AssertType $ "Function"}}
1036  {{if not (GetAnnotation $ "pfn")}}
1037    {{$ext := GetAnnotation $ "extension"}}
1038    {{if not $ext}}true
1039    {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
1040    {{end}}
1041  {{end}}
1042{{end}}
1043
1044
1045{{/*
1046------------------------------------------------------------------------------
1047  Decides whether a function should be exported from the Android Vulkan
1048  library. Functions in the core API and in loader extensions are exported.
1049------------------------------------------------------------------------------
1050*/}}
1051{{define "IsFunctionExported"}}
1052  {{AssertType $ "Function"}}
1053
1054  {{if (Macro "IsFunctionSupported" $)}}
1055    {{$ext := GetAnnotation $ "extension"}}
1056    {{if $ext}}
1057      {{Macro "IsExtensionExported" $ext}}
1058    {{else}}
1059      true
1060    {{end}}
1061  {{end}}
1062{{end}}
1063
1064
1065{{/*
1066------------------------------------------------------------------------------
1067  Emit "true" if an extension is unsupportable on Android.
1068------------------------------------------------------------------------------
1069*/}}
1070{{define "IsExtensionBlacklisted"}}
1071  {{$ext := index $.Arguments 0}}
1072  {{     if eq $ext "VK_KHR_display"}}true
1073  {{else if eq $ext "VK_KHR_display_swapchain"}}true
1074  {{else if eq $ext "VK_KHR_xlib_surface"}}true
1075  {{else if eq $ext "VK_KHR_xcb_surface"}}true
1076  {{else if eq $ext "VK_KHR_wayland_surface"}}true
1077  {{else if eq $ext "VK_KHR_mir_surface"}}true
1078  {{else if eq $ext "VK_KHR_win32_surface"}}true
1079  {{end}}
1080{{end}}
1081
1082
1083{{/*
1084------------------------------------------------------------------------------
1085  Reports whether an extension is implemented entirely by the loader,
1086  so drivers should not enumerate it.
1087------------------------------------------------------------------------------
1088*/}}
1089{{define "IsExtensionExported"}}
1090  {{$ext := index $.Arguments 0}}
1091  {{     if eq $ext "VK_KHR_surface"}}true
1092  {{else if eq $ext "VK_KHR_swapchain"}}true
1093  {{else if eq $ext "VK_KHR_android_surface"}}true
1094  {{end}}
1095{{end}}
1096
1097
1098{{/*
1099------------------------------------------------------------------------------
1100  Reports whether an extension is internal to the loader and drivers,
1101  so the loader should not enumerate it.
1102------------------------------------------------------------------------------
1103*/}}
1104{{define "IsExtensionInternal"}}
1105  {{$ext := index $.Arguments 0}}
1106  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
1107  {{end}}
1108{{end}}
1109