Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8925efd0 authored by Chia-I Wu's avatar Chia-I Wu
Browse files

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
parent cbe07ef2
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -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;
+77 −7
Original line number Diff line number Diff line
@@ -37,14 +37,81 @@ namespace api {
        }                                                              \
    } while (0)

// 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 {                                         \
        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;

+10 −2
Original line number Diff line number Diff line
@@ -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
+59 −6
Original line number Diff line number Diff line
@@ -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,13 +458,41 @@ 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 {                    \
      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.