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 if GetAnnotation $ "vulkan1_1"}}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
705VK_ANDROID_external_memory_android_hardware_buffer
706VK_KHR_bind_memory2
707{{end}}
708
709
710{{/*
711------------------------------------------------------------------------------
712  Emits true if an extension is intercepted by vulkan::driver.
713------------------------------------------------------------------------------
714*/}}
715{{define "driver.IsExtensionIntercepted"}}
716  {{$ext_name := index $.Arguments 0}}
717  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
718
719  {{range $f := $filters}}
720    {{if eq $ext_name $f}}true{{end}}
721  {{end}}
722{{end}}
723
724
725{{/*
726------------------------------------------------------------------------------
727  Emits true if a function is intercepted by vulkan::driver.
728------------------------------------------------------------------------------
729*/}}
730{{define "driver.IsIntercepted"}}
731  {{AssertType $ "Function"}}
732
733  {{if (Macro "IsFunctionSupported" $)}}
734    {{/* Create functions of dispatchable objects */}}
735    {{     if eq $.Name "vkCreateInstance"}}true
736    {{else if eq $.Name "vkCreateDevice"}}true
737    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
738    {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
739    {{else if eq $.Name "vkGetDeviceQueue"}}true
740    {{else if eq $.Name "vkGetDeviceQueue2"}}true
741    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
742
743    {{/* Destroy functions of dispatchable objects */}}
744    {{else if eq $.Name "vkDestroyInstance"}}true
745    {{else if eq $.Name "vkDestroyDevice"}}true
746
747    {{/* Enumeration of extensions */}}
748    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
749    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
750
751    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
752    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
753
754    {{/* VK_KHR_swapchain v69 requirement */}}
755    {{else if eq $.Name "vkBindImageMemory2"}}true
756    {{else if eq $.Name "vkBindImageMemory2KHR"}}true
757    {{end}}
758
759    {{$ext := GetAnnotation $ "extension"}}
760    {{if $ext}}
761      {{Macro "driver.IsExtensionIntercepted" $ext}}
762    {{end}}
763
764  {{end}}
765{{end}}
766
767
768
769{{/*
770------------------------------------------------------------------------------
771  Emits the ProcHook enum for core Vulkan API verions.
772------------------------------------------------------------------------------
773*/}}
774{{define "driver.GetProcHookEnum"}}
775  {{if GetAnnotation $ "vulkan1_1"}}ProcHook::EXTENSION_CORE_1_1
776  {{else}}ProcHook::EXTENSION_CORE_1_0
777  {{end}}
778{{end}}
779
780
781{{/*
782------------------------------------------------------------------------------
783  Emits true if a function needs a ProcHook stub.
784------------------------------------------------------------------------------
785*/}}
786{{define "driver.NeedProcHookStub"}}
787  {{AssertType $ "Function"}}
788
789  {{if and (Macro "driver.IsIntercepted" $) (Macro "IsDeviceDispatched" $)}}
790    {{$ext := GetAnnotation $ "extension"}}
791    {{if $ext}}
792      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
793    {{end}}
794
795    {{if GetAnnotation $ "vulkan1_1"}}true{{end}}
796  {{end}}
797{{end}}
798
799
800{{/*
801-------------------------------------------------------------------------------
802  Emits definition of struct ProcHook.
803-------------------------------------------------------------------------------
804*/}}
805{{define "driver.C++.DefineProcHookType"}}
806  struct ProcHook {
807      enum Type {
808        GLOBAL,
809        INSTANCE,
810        DEVICE,
811      };
812
813      enum Extension {
814        {{$exts := Strings (Macro "driver.KnownExtensions") | SplitOn "\n"}}
815        {{range $e := $exts}}
816          {{TrimPrefix "VK_" $e}},
817        {{end}}
818819        EXTENSION_CORE_1_0,
820        EXTENSION_CORE_1_1,
821        EXTENSION_COUNT,
822        EXTENSION_UNKNOWN,
823      };
824825      const char* name;
826      Type type;
827      Extension extension;
828829      PFN_vkVoidFunction proc;
830      PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
831  };
832{{end}}
833
834
835{{/*
836-------------------------------------------------------------------------------
837  Emits INIT_PROC_EXT macro for vulkan::driver.
838-------------------------------------------------------------------------------
839*/}}
840{{define "driver.C++.DefineInitProcExtMacro"}}
841  #define INIT_PROC_EXT(ext, required, obj, proc) do {          \
842      if (extensions[ProcHook::ext])                            \
843        INIT_PROC(required, obj, proc);                         \
844  } while(0)
845{{end}}
846
847
848{{/*
849-------------------------------------------------------------------------------
850  Emits a stub for ProcHook::checked_proc.
851-------------------------------------------------------------------------------
852*/}}
853{{define "driver.C++.DefineProcHookStub"}}
854  {{AssertType $ "Function"}}
855
856  {{if (Macro "driver.NeedProcHookStub" $)}}
857    {{$ext_name := Strings ("")}}
858    {{$ext_hook := Strings ("")}}
859    {{$ext := GetAnnotation $ "extension"}}
860    {{if $ext}}
861      {{$ext_name = index $ext.Arguments 0}}
862      {{$ext_hook = Strings ("ProcHook::") (Macro "BaseName" $ext)}}
863    {{else}}
864      {{$ext_name = Strings ("VK_VERSION_1_0")}}
865      {{$ext_hook = (Macro "driver.GetProcHookEnum" $)}}
866    {{end}}
867
868    {{$base := (Macro "BaseName" $)}}
869
870    VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
871      {{$p0 := index $.CallParameters 0}}
872
873      if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
874        {{if not (IsVoid $.Return.Type)}}return §{{end}}
875        {{$base}}({{Macro "Arguments" $}});
876      } else {
877        Logger({{$p0.Name}}).Err({{$p0.Name}}, "{{$ext_name}} not enabled. {{$.Name}} not executed.");
878        {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
879      }
880    }
881882  {{end}}
883{{end}}
884
885
886{{/*
887-------------------------------------------------------------------------------
888  Emits definition of a global ProcHook.
889-------------------------------------------------------------------------------
890*/}}
891{{define "driver.C++.DefineGlobalProcHook"}}
892  {{AssertType $ "Function"}}
893
894  {{$base := (Macro "BaseName" $)}}
895
896  {{$ext := GetAnnotation $ "extension"}}
897  {{if $ext}}
898    {{Error "invalid global extension"}}
899  {{end}}
900
901  {
902    "{{$.Name}}",
903    ProcHook::GLOBAL,
904    {{Macro "driver.GetProcHookEnum" $}},
905    reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
906    nullptr,
907  },
908{{end}}
909
910
911{{/*
912-------------------------------------------------------------------------------
913  Emits definition of an instance ProcHook.
914-------------------------------------------------------------------------------
915*/}}
916{{define "driver.C++.DefineInstanceProcHook"}}
917  {{AssertType $ "Function"}}
918
919  {{$base := (Macro "BaseName" $)}}
920
921  {
922    "{{$.Name}}",
923    ProcHook::INSTANCE,
924
925    {{$ext := GetAnnotation $ "extension"}}
926    {{if $ext}}
927      ProcHook::{{Macro "BaseName" $ext}},
928
929      {{if (Macro "IsExtensionInternal" $ext)}}
930        nullptr,
931        nullptr,
932      {{else}}
933        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
934        nullptr,
935      {{end}}
936    {{else}}
937      {{Macro "driver.GetProcHookEnum" $}},
938      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
939      nullptr,
940    {{end}}
941  },
942{{end}}
943
944
945{{/*
946-------------------------------------------------------------------------------
947  Emits definition of a device ProcHook.
948-------------------------------------------------------------------------------
949*/}}
950{{define "driver.C++.DefineDeviceProcHook"}}
951  {{AssertType $ "Function"}}
952
953  {{$base := (Macro "BaseName" $)}}
954
955  {
956    "{{$.Name}}",
957    ProcHook::DEVICE,
958
959    {{$ext := GetAnnotation $ "extension"}}
960    {{if or $ext (GetAnnotation $ "vulkan1_1")}}
961      {{if $ext}}
962        ProcHook::{{Macro "BaseName" $ext}},
963        {{if Macro "IsExtensionInternal" $ext}}
964          nullptr,
965          nullptr,
966        {{else}}
967          reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
968          reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
969        {{end}}
970      {{else}}
971        {{Macro "driver.GetProcHookEnum" $}},
972        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
973        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
974      {{end}}
975    {{else}}
976      {{Macro "driver.GetProcHookEnum" $}},
977      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
978      nullptr,
979    {{end}}
980  },
981{{end}}
982
983
984{{/*
985-------------------------------------------------------------------------------
986  Emits true if a function is needed by vulkan::driver.
987-------------------------------------------------------------------------------
988*/}}
989{{define "driver.IsDriverTableEntry"}}
990  {{AssertType $ "Function"}}
991
992  {{if (Macro "IsFunctionSupported" $)}}
993    {{/* Create functions of dispatchable objects */}}
994    {{     if eq $.Name "vkCreateDevice"}}true
995    {{else if eq $.Name "vkGetDeviceQueue"}}true
996    {{else if eq $.Name "vkGetDeviceQueue2"}}true
997    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
998
999    {{/* Destroy functions of dispatchable objects */}}
1000    {{else if eq $.Name "vkDestroyInstance"}}true
1001    {{else if eq $.Name "vkDestroyDevice"}}true
1002
1003    {{/* Enumeration of extensions */}}
1004    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
1005
1006    {{/* We cache physical devices in loader.cpp */}}
1007    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
1008    {{else if eq $.Name "vkEnumeratePhysicalDeviceGroups"}}true
1009
1010    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
1011    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
1012
1013    {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
1014    {{else if eq $.Name "vkCreateImage"}}true
1015    {{else if eq $.Name "vkDestroyImage"}}true
1016
1017    {{else if eq $.Name "vkGetPhysicalDeviceProperties"}}true
1018    {{else if eq $.Name "vkGetPhysicalDeviceProperties2"}}true
1019    {{else if eq $.Name "vkGetPhysicalDeviceProperties2KHR"}}true
1020
1021    {{/* VK_KHR_swapchain v69 requirement */}}
1022    {{else if eq $.Name "vkBindImageMemory2"}}true
1023    {{else if eq $.Name "vkBindImageMemory2KHR"}}true
1024    {{end}}
1025
1026    {{$ext := GetAnnotation $ "extension"}}
1027    {{if $ext}}
1028      {{$ext_name := index $ext.Arguments 0}}
1029      {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
1030      {{else if eq $ext_name "VK_EXT_debug_report"}}true
1031      {{end}}
1032    {{end}}
1033  {{end}}
1034{{end}}
1035
1036
1037{{/*
1038------------------------------------------------------------------------------
1039  Emits true if an instance-dispatched function is needed by vulkan::driver.
1040------------------------------------------------------------------------------
1041*/}}
1042{{define "driver.IsInstanceDriverTableEntry"}}
1043  {{AssertType $ "Function"}}
1044
1045  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
1046    true
1047  {{end}}
1048{{end}}
1049
1050
1051{{/*
1052------------------------------------------------------------------------------
1053  Emits true if a device-dispatched function is needed by vulkan::driver.
1054------------------------------------------------------------------------------
1055*/}}
1056{{define "driver.IsDeviceDriverTableEntry"}}
1057  {{AssertType $ "Function"}}
1058
1059  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
1060    true
1061  {{end}}
1062{{end}}
1063
1064
1065{{/*
1066-------------------------------------------------------------------------------
1067  Emits a function/extension name without the "vk"/"VK_" prefix.
1068-------------------------------------------------------------------------------
1069*/}}
1070{{define "BaseName"}}
1071  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
1072  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
1073  {{else}}{{Error "invalid use of BaseName"}}
1074  {{end}}
1075{{end}}
1076
1077
1078{{/*
1079-------------------------------------------------------------------------------
1080  Emits a comma-separated list of C parameter names for the given command.
1081-------------------------------------------------------------------------------
1082*/}}
1083{{define "Arguments"}}
1084  {{AssertType $ "Function"}}
1085
1086  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
1087{{end}}
1088
1089
1090{{/*
1091------------------------------------------------------------------------------
1092------------------------------------------------------------------------------
1093*/}}
1094{{define "IsGloballyDispatched"}}
1095  {{AssertType $ "Function"}}
1096  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
1097    true
1098  {{end}}
1099{{end}}
1100
1101
1102{{/*
1103------------------------------------------------------------------------------
1104  Emit "true" for supported functions that undergo table dispatch. Only global
1105  functions and functions handled in the loader top without calling into
1106  lower layers are not dispatched.
1107------------------------------------------------------------------------------
1108*/}}
1109{{define "IsInstanceDispatched"}}
1110  {{AssertType $ "Function"}}
1111  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
1112    true
1113  {{end}}
1114{{end}}
1115
1116
1117{{/*
1118------------------------------------------------------------------------------
1119  Emit "true" for supported functions that can have device-specific dispatch.
1120------------------------------------------------------------------------------
1121*/}}
1122{{define "IsDeviceDispatched"}}
1123  {{AssertType $ "Function"}}
1124  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
1125    true
1126  {{end}}
1127{{end}}
1128
1129
1130{{/*
1131------------------------------------------------------------------------------
1132  Emit "true" if a function is core or from a supportable extension.
1133------------------------------------------------------------------------------
1134*/}}
1135{{define "IsFunctionSupported"}}
1136  {{AssertType $ "Function"}}
1137  {{if not (GetAnnotation $ "pfn")}}
1138    {{$ext := GetAnnotation $ "extension"}}
1139    {{if not $ext}}true
1140    {{else if not (Macro "IsExtensionBlocked" $ext)}}true
1141    {{end}}
1142  {{end}}
1143{{end}}
1144
1145
1146{{/*
1147------------------------------------------------------------------------------
1148  Decides whether a function should be exported from the Android Vulkan
1149  library. Functions in the core API and in loader extensions are exported.
1150------------------------------------------------------------------------------
1151*/}}
1152{{define "IsFunctionExported"}}
1153  {{AssertType $ "Function"}}
1154
1155  {{if (Macro "IsFunctionSupported" $)}}
1156    {{$ext := GetAnnotation $ "extension"}}
1157    {{if $ext}}
1158      {{Macro "IsExtensionExported" $ext}}
1159    {{else}}
1160      true
1161    {{end}}
1162  {{end}}
1163{{end}}
1164
1165
1166{{/*
1167------------------------------------------------------------------------------
1168  Emit "true" if an extension is unsupportable on Android.
1169------------------------------------------------------------------------------
1170*/}}
1171{{define "IsExtensionBlocked"}}
1172  {{$ext := index $.Arguments 0}}
1173  {{     if eq $ext "VK_KHR_display"}}true
1174  {{else if eq $ext "VK_KHR_display_swapchain"}}true
1175  {{else if eq $ext "VK_KHR_mir_surface"}}true
1176  {{else if eq $ext "VK_KHR_xcb_surface"}}true
1177  {{else if eq $ext "VK_KHR_xlib_surface"}}true
1178  {{else if eq $ext "VK_KHR_wayland_surface"}}true
1179  {{else if eq $ext "VK_KHR_win32_surface"}}true
1180  {{else if eq $ext "VK_KHR_external_memory_win32"}}true
1181  {{else if eq $ext "VK_KHR_win32_keyed_mutex"}}true
1182  {{else if eq $ext "VK_KHR_external_semaphore_win32"}}true
1183  {{else if eq $ext "VK_KHR_external_fence_win32"}}true
1184  {{else if eq $ext "VK_EXT_acquire_xlib_display"}}true
1185  {{else if eq $ext "VK_EXT_direct_mode_display"}}true
1186  {{else if eq $ext "VK_EXT_display_surface_counter"}}true
1187  {{else if eq $ext "VK_EXT_display_control"}}true
1188  {{else if eq $ext "VK_FUCHSIA_imagepipe_surface"}}true
1189  {{else if eq $ext "VK_MVK_ios_surface"}}true
1190  {{else if eq $ext "VK_MVK_macos_surface"}}true
1191  {{else if eq $ext "VK_NN_vi_surface"}}true
1192  {{else if eq $ext "VK_NV_external_memory_win32"}}true
1193  {{else if eq $ext "VK_NV_win32_keyed_mutex"}}true
1194  {{end}}
1195{{end}}
1196
1197
1198{{/*
1199------------------------------------------------------------------------------
1200  Reports whether an extension has functions exported by the loader.
1201  E.g. applications can directly link to an extension function.
1202------------------------------------------------------------------------------
1203*/}}
1204{{define "IsExtensionExported"}}
1205  {{$ext := index $.Arguments 0}}
1206  {{     if eq $ext "VK_KHR_surface"}}true
1207  {{else if eq $ext "VK_KHR_swapchain"}}true
1208  {{else if eq $ext "VK_KHR_android_surface"}}true
1209  {{else if eq $ext "VK_ANDROID_external_memory_android_hardware_buffer"}}true
1210  {{end}}
1211{{end}}
1212
1213
1214{{/*
1215------------------------------------------------------------------------------
1216  Reports whether an extension is internal to the loader and drivers,
1217  so the loader should not enumerate it.
1218------------------------------------------------------------------------------
1219*/}}
1220{{define "IsExtensionInternal"}}
1221  {{$ext := index $.Arguments 0}}
1222  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
1223  {{end}}
1224{{end}}
1225