OSDN Git Service

vulkan: do not query non-enabled WSI functions
authorChia-I Wu <olv@google.com>
Wed, 13 Apr 2016 07:13:21 +0000 (15:13 +0800)
committerChia-I Wu <olv@google.com>
Thu, 14 Apr 2016 00:43:04 +0000 (08:43 +0800)
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

vulkan/libvulkan/api.cpp
vulkan/libvulkan/api_gen.cpp
vulkan/libvulkan/api_gen.h
vulkan/libvulkan/code-generator.tmpl

index eeb32d4..e7f10b3 100644 (file)
@@ -465,6 +465,7 @@ class LayerChain {
 
     VkExtensionProperties* driver_extensions_;
     uint32_t driver_extension_count_;
+    std::bitset<driver::ProcHook::EXTENSION_COUNT> enabled_extensions_;
 };
 
 LayerChain::LayerChain(bool is_instance, const VkAllocationCallbacks& allocator)
@@ -477,7 +478,9 @@ LayerChain::LayerChain(bool is_instance, const VkAllocationCallbacks& allocator)
       get_instance_proc_addr_(nullptr),
       get_device_proc_addr_(nullptr),
       driver_extensions_(nullptr),
-      driver_extension_count_(0) {}
+      driver_extension_count_(0) {
+    enabled_extensions_.set(driver::ProcHook::EXTENSION_CORE);
+}
 
 LayerChain::~LayerChain() {
     allocator_.pfnFree(allocator_.pUserData, driver_extensions_);
@@ -694,11 +697,11 @@ VkResult LayerChain::Create(const VkInstanceCreateInfo* create_info,
 
     // initialize InstanceData
     InstanceData& data = GetData(instance);
-    memset(&data, 0, sizeof(data));
 
     data.instance = instance;
 
-    if (!InitDispatchTable(instance, get_instance_proc_addr_)) {
+    if (!InitDispatchTable(instance, get_instance_proc_addr_,
+                           enabled_extensions_)) {
         if (data.dispatch.DestroyInstance)
             data.dispatch.DestroyInstance(instance, allocator);
 
@@ -774,9 +777,8 @@ VkResult LayerChain::Create(VkPhysicalDevice physical_dev,
 
     // initialize DeviceData
     DeviceData& data = GetData(dev);
-    memset(&data, 0, sizeof(data));
 
-    if (!InitDispatchTable(dev, get_device_proc_addr_)) {
+    if (!InitDispatchTable(dev, get_device_proc_addr_, enabled_extensions_)) {
         if (data.dispatch.DestroyDevice)
             data.dispatch.DestroyDevice(dev, allocator);
 
@@ -816,6 +818,10 @@ VkResult LayerChain::ValidateExtensions(const char* const* extension_names,
             ALOGE("Failed to enable missing instance extension %s", name);
             return VK_ERROR_EXTENSION_NOT_PRESENT;
         }
+
+        auto ext_bit = driver::GetProcHookExtension(name);
+        if (ext_bit != driver::ProcHook::EXTENSION_UNKNOWN)
+            enabled_extensions_.set(ext_bit);
     }
 
     return VK_SUCCESS;
@@ -849,6 +855,10 @@ VkResult LayerChain::ValidateExtensions(VkPhysicalDevice physical_dev,
             ALOGE("Failed to enable missing device extension %s", name);
             return VK_ERROR_EXTENSION_NOT_PRESENT;
         }
+
+        auto ext_bit = driver::GetProcHookExtension(name);
+        if (ext_bit != driver::ProcHook::EXTENSION_UNKNOWN)
+            enabled_extensions_.set(ext_bit);
     }
 
     return VK_SUCCESS;
index a8cca59..fe4136f 100644 (file)
@@ -37,14 +37,81 @@ namespace api {
         }                                                              \
     } while (0)
 
-// TODO do we want to point to a stub or nullptr when ext is not enabled?
-#define INIT_PROC_EXT(ext, obj, proc) \
-    do {                              \
-        INIT_PROC(obj, proc);         \
+// 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 {                                         \
+        if (extensions[driver::ProcHook::ext])   \
+            INIT_PROC(obj, proc);                \
+        else                                     \
+            data.dispatch.proc = disabled##proc; \
     } while (0)
 
-bool InitDispatchTable(VkInstance instance,
-                       PFN_vkGetInstanceProcAddr get_proc) {
+namespace {
+
+// clang-format off
+
+VKAPI_ATTR void disabledDestroySurfaceKHR(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks*) {
+    ALOGE("VK_KHR_surface not enabled. vkDestroySurfaceKHR not executed.");
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32*) {
+    ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceSupportKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR*) {
+    ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceCapabilitiesKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkSurfaceFormatKHR*) {
+    ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceFormatsKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkPresentModeKHR*) {
+    ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfacePresentModesKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledCreateSwapchainKHR(VkDevice, const VkSwapchainCreateInfoKHR*, const VkAllocationCallbacks*, VkSwapchainKHR*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR void disabledDestroySwapchainKHR(VkDevice, VkSwapchainKHR, const VkAllocationCallbacks*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed.");
+}
+
+VKAPI_ATTR VkResult disabledGetSwapchainImagesKHR(VkDevice, VkSwapchainKHR, uint32_t*, VkImage*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledAcquireNextImageKHR(VkDevice, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledQueuePresentKHR(VkQueue, const VkPresentInfoKHR*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) {
+    ALOGE("VK_KHR_android_surface not enabled. vkCreateAndroidSurfaceKHR not executed.");
+    return VK_SUCCESS;
+}
+
+// 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;
 
@@ -73,7 +140,10 @@ bool InitDispatchTable(VkInstance instance,
     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;
 
index 54be83b..779b654 100644 (file)
@@ -19,7 +19,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 {
@@ -179,8 +181,14 @@ struct DeviceDispatchTable {
     // 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
index ad1693a..9568f7f 100644 (file)
@@ -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 @@ struct DeviceDispatchTable {
   // 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 @@ namespace api {«
 ¶
 {{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 @@ bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc)
     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 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
 -------------------------------------------------------------------------------
 */}}
 {{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.
 ------------------------------------------------------------------------------