vulkan: do not query non-enabled WSI functions

Initialize dispatch table entries for non-enabled WSI functions to stubs.
We do not want to initialize them to NULL because they may still be
invoked through the exported WSI entrypoints.

Bug: 25850852
Change-Id: I25b715700990ad7432740f031764d70396024d32
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
index ad1693a..9568f7f 100644
--- a/vulkan/libvulkan/code-generator.tmpl
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -37,7 +37,9 @@
 #ifndef LIBVULKAN_API_GEN_H
 #define LIBVULKAN_API_GEN_H

+#include <bitset>
 #include <vulkan/vulkan.h>
+#include "driver_gen.h"

 namespace vulkan {«
 namespace api {«
@@ -62,8 +64,14 @@
   // clang-format on
 };

-bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc);
-bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc);
+bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
+bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);

 »} // namespace api
 »} // namespace vulkan
@@ -95,7 +103,21 @@

 {{Macro "api.C++.DefineInitProcExtMacro"}}

-bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc) {
+namespace {«

+// clang-format off

+{{range $f := AllCommands $}}
+  {{Macro "api.C++.DefineExtensionStub" $f}}
+{{end}}
+// clang-format on

+»} // anonymous

+bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
     auto& data = GetData(instance);
     bool success = true;

@@ -110,7 +132,10 @@
     return success;
 }

-bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc) {
+bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
     auto& data = GetData(dev);
     bool success = true;

@@ -433,14 +458,42 @@
 -------------------------------------------------------------------------------
 */}}
 {{define "api.C++.DefineInitProcExtMacro"}}
-  // TODO do we want to point to a stub or nullptr when ext is not enabled?
+  // Exported extension functions may be invoked even when their extensions
+  // are disabled.  Dispatch to stubs when that happens.
   #define INIT_PROC_EXT(ext, obj, proc) do {                    \
-      INIT_PROC(obj, proc);                                     \
+      if (extensions[driver::ProcHook::ext])                    \
+        INIT_PROC(obj, proc);                                   \
+      else                                                      \
+        data.dispatch.proc = disabled ## proc;                  \
   } while(0)
 {{end}}
 
 
 {{/*
+-------------------------------------------------------------------------------
+  Emits a stub for an exported extension function.
+-------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.DefineExtensionStub"}}
+  {{AssertType $ "Function"}}
+
+  {{$ext := GetAnnotation $ "extension"}}
+  {{if and $ext (Macro "IsFunctionExported" $)}}
+    {{$ext_name := index $ext.Arguments 0}}
+
+    {{$base := (Macro "BaseName" $)}}
+    {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
+
+    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$unnamed_params}}) {
+      ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
+      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
+    }
+    ¶
+  {{end}}
+{{end}}
+
+
+{{/*
 ------------------------------------------------------------------------------
   Emits code for vkGetInstanceProcAddr for function interception.
 ------------------------------------------------------------------------------