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

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

vulkan: rework driver::Get*ProcAddr

Introduce driver::ProcHook which is a struct to describe an intercepted
function.  Given a function name, GetProcHook returns a ProcHook if the
function is intercepted.  NULL otherwise.

A ProcHook has three function pointers.  ProcHook::proc points to the real
intercepting function.  ProcHook::disabled_proc points to a no-op function
that logs an error.  ProcHook::checked_proc points to a trampoline that
calls either ProcHook::proc or ProcHook::disabled_proc.

For core functions, driver::Get*ProcAddr simply return ProcHook::proc.
For extension functions, driver::Get*ProcAddr return ProcHook::proc when
the extension is known to be enabled.  They return ProcHook::disabled_proc
when the extension is known to be disabled.  Finally, they return
ProcHook::checked_proc when they do not know if the extension is enabled
or not.

All ProcHooks as well as their disabled_proc/checked_proc are generated in
driver_gen.cpp.  This allows us to get rid of all hand-written "_Disabled"
functions, all no-op "_Bottom" functions, and special cases for
VK_ANDROID_native_buffer.  The reworked driver::Get*ProcAddr also detects
more applications' errors and logs them.

Change-Id: I8e6f476f450688b5547fd75243c66cb603c516b5
parent b262ddcf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ LOCAL_SRC_FILES := \
	debug_report.cpp \
	dispatch_gen.cpp \
	driver.cpp \
	driver_gen.cpp \
	layers_extensions.cpp \
	loader.cpp \
	swapchain.cpp \
+390 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@
{{Macro "DefineGlobals" $}}
{{$ | Macro "api_gen.h"   | Format (Global "clang-format") | Write "api_gen.h"  }}
{{$ | Macro "api_gen.cpp" | Format (Global "clang-format") | Write "api_gen.cpp"}}
{{$ | Macro "driver_gen.h" | Format (Global "clang-format") | Write "driver_gen.h"}}
{{$ | Macro "driver_gen.cpp" | Format (Global "clang-format") | Write "driver_gen.cpp"}}

{{/*
-------------------------------------------------------------------------------
@@ -146,6 +148,110 @@ bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc) {
¶{{end}}


{{/*
-------------------------------------------------------------------------------
  driver_gen.h
-------------------------------------------------------------------------------
*/}}
{{define "driver_gen.h"}}
{{Macro "Copyright"}}

// WARNING: This file is generated. See ../README.md for instructions.

#ifndef LIBVULKAN_DRIVER_GEN_H
#define LIBVULKAN_DRIVER_GEN_H

#include <vulkan/vulkan.h>
#include <vulkan/vk_android_native_buffer.h>

namespace vulkan {«
namespace driver {«

{{Macro "driver.C++.DefineProcHookType"}}

const ProcHook* GetProcHook(const char* name);
ProcHook::Extension GetProcHookExtension(const char* name);

»} // namespace driver
»} // namespace vulkan

#endif // LIBVULKAN_DRIVER_TABLE_H
¶{{end}}


{{/*
-------------------------------------------------------------------------------
  driver_gen.cpp
-------------------------------------------------------------------------------
*/}}
{{define "driver_gen.cpp"}}
{{Macro "Copyright"}}

// WARNING: This file is generated. See ../README.md for instructions.

#include <string.h>
#include <algorithm>
#include <log/log.h>

#include "driver.h"
#include "loader.h"

namespace vulkan {«
namespace driver {«

namespace {«

// clang-format off

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

const ProcHook g_proc_hooks[] = {
  // clang-format off
  {{range $f := SortBy (AllCommands $) "FunctionName"}}
    {{if (Macro "driver.IsIntercepted" $f)}}
      {{     if (Macro "IsGloballyDispatched" $f)}}
        {{Macro "driver.C++.DefineGlobalProcHook" $f}}
      {{else if (Macro "IsInstanceDispatched" $f)}}
        {{Macro "driver.C++.DefineInstanceProcHook" $f}}
      {{else if (Macro "IsDeviceDispatched" $f)}}
        {{Macro "driver.C++.DefineDeviceProcHook" $f}}
      {{end}}
    {{end}}
  {{end}}
  // clang-format on
};

»} // anonymous

const ProcHook* GetProcHook(const char* name) {
    const auto& begin = g_proc_hooks;
    const auto& end = g_proc_hooks +
      sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
    const auto hook = std::lower_bound(begin, end, name,
        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
    return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
}

ProcHook::Extension GetProcHookExtension(const char* name) {
  {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
  // clang-format off
  {{range $e := $exts}}
    if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
  {{end}}
  // clang-format on
  return ProcHook::EXTENSION_UNKNOWN;
}

»} // namespace driver
»} // namespace vulkan

// clang-format on
¶{{end}}


{{/*
------------------------------------------------------------------------------
  Emits a declaration of a dispatch table entry.
@@ -385,6 +491,277 @@ bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc) {
{{end}}


{{/*
------------------------------------------------------------------------------
  Emits a list of extensions intercepted by vulkan::driver.
------------------------------------------------------------------------------
*/}}
{{define "driver.InterceptedExtensions"}}
VK_ANDROID_native_buffer
VK_EXT_debug_report
VK_KHR_android_surface
VK_KHR_surface
VK_KHR_swapchain
{{end}}


{{/*
------------------------------------------------------------------------------
  Emits true if an extension is intercepted by vulkan::driver.
------------------------------------------------------------------------------
*/}}
{{define "driver.IsExtensionIntercepted"}}
  {{$ext_name := index $.Arguments 0}}
  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}

  {{range $f := $filters}}
    {{if eq $ext_name $f}}true{{end}}
  {{end}}
{{end}}


{{/*
------------------------------------------------------------------------------
  Emits true if a function is intercepted by vulkan::driver.
------------------------------------------------------------------------------
*/}}
{{define "driver.IsIntercepted"}}
  {{AssertType $ "Function"}}

  {{if (Macro "IsFunctionSupported" $)}}
    {{/* Create functions of dispatchable objects */}}
    {{     if eq $.Name "vkCreateInstance"}}true
    {{else if eq $.Name "vkCreateDevice"}}true
    {{else if eq $.Name "vkGetDeviceQueue"}}true
    {{else if eq $.Name "vkAllocateCommandBuffers"}}true

    {{/* Destroy functions of dispatchable objects */}}
    {{else if eq $.Name "vkDestroyInstance"}}true
    {{else if eq $.Name "vkDestroyDevice"}}true

    {{/* Enumeration of extensions */}}
    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true

    {{/* We cache physical devices in loader.cpp */}}
    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true

    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
    {{else if eq $.Name "vkGetDeviceProcAddr"}}true

    {{end}}

    {{$ext := GetAnnotation $ "extension"}}
    {{if $ext}}
      {{Macro "driver.IsExtensionIntercepted" $ext}}
    {{end}}

  {{end}}
{{end}}


{{/*
------------------------------------------------------------------------------
  Emits true if a function needs ProcHook stubs.
------------------------------------------------------------------------------
*/}}
{{define "driver.NeedProcHookStubs"}}
  {{AssertType $ "Function"}}

  {{if (Macro "driver.IsIntercepted" $)}}
    {{$ext := GetAnnotation $ "extension"}}
    {{if $ext}}
      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
    {{end}}
  {{end}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits definition of struct ProcHook.
-------------------------------------------------------------------------------
*/}}
{{define "driver.C++.DefineProcHookType"}}
  struct ProcHook {
      enum Type {
        GLOBAL,
        INSTANCE,
        DEVICE,
      };

      enum Extension {
        {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
        {{range $e := $exts}}
          {{TrimPrefix "VK_" $e}},
        {{end}}

        EXTENSION_CORE, // valid bit
        EXTENSION_COUNT,
        EXTENSION_UNKNOWN,
      };

      const char* name;
      Type type;
      Extension extension;

      PFN_vkVoidFunction proc;
      PFN_vkVoidFunction disabled_proc; // nullptr for global hooks
      PFN_vkVoidFunction checked_proc;  // nullptr for global/instance hooks
  };
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits definitions of stub functions for ProcHook.
-------------------------------------------------------------------------------
*/}}
{{define "driver.C++.DefineProcHookStubs"}}
  {{AssertType $ "Function"}}

  {{if (Macro "driver.NeedProcHookStubs" $)}}
    {{$ext := GetAnnotation $ "extension"}}
    {{$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}}
    }
    {{if (Macro "IsDeviceDispatched" $)}}

      VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
        {{if not (IsVoid $.Return.Type)}}return §{{end}}

        {{$p0 := index $.CallParameters 0}}
        {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
        (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) ? §
          {{$base}}_Bottom({{Macro "Arguments" $}}) : §
          disabled{{$base}}({{Macro "Arguments" $}});
      }
    {{end}}

  {{end}}
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits definition of a global ProcHook.
-------------------------------------------------------------------------------
*/}}
{{define "driver.C++.DefineGlobalProcHook"}}
  {{AssertType $ "Function"}}

  {{$base := (Macro "BaseName" $)}}

  {{$ext := GetAnnotation $ "extension"}}
  {{if $ext}}
    {{Error "invalid global extension"}}
  {{end}}

  {
    "{{$.Name}}",
    ProcHook::GLOBAL,
    ProcHook::EXTENSION_CORE,
    {{if eq $.Name "vkEnumerateInstanceExtensionProperties"}}
      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
    {{else}}
      reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
    {{end}}
    nullptr,
    nullptr,
  },
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits definition of an instance ProcHook.
-------------------------------------------------------------------------------
*/}}
{{define "driver.C++.DefineInstanceProcHook"}}
  {{AssertType $ "Function"}}

  {{$base := (Macro "BaseName" $)}}

  {
    "{{$.Name}}",
    ProcHook::INSTANCE,

    {{$ext := GetAnnotation $ "extension"}}
    {{if $ext}}
      ProcHook::{{Macro "BaseName" $ext}},

      {{if (Macro "IsExtensionInternal" $ext)}}
        nullptr,
        nullptr,
        nullptr,
      {{else}}
        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
        reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
        nullptr,
      {{end}}
    {{else}}
      ProcHook::EXTENSION_CORE,

      {{if eq $.Name "vkGetInstanceProcAddr"}}
        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
      {{else}}
        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
      {{end}}
      nullptr,
      nullptr,
    {{end}}
  },
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits definition of a device ProcHook.
-------------------------------------------------------------------------------
*/}}
{{define "driver.C++.DefineDeviceProcHook"}}
  {{AssertType $ "Function"}}

  {{$base := (Macro "BaseName" $)}}

  {
    "{{$.Name}}",
    ProcHook::DEVICE,

    {{$ext := GetAnnotation $ "extension"}}
    {{if $ext}}
      ProcHook::{{Macro "BaseName" $ext}},

      {{if (Macro "IsExtensionInternal" $ext)}}
        nullptr,
        nullptr,
        nullptr,
      {{else}}
        reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
        reinterpret_cast<PFN_vkVoidFunction>(disabled{{$base}}),
        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
      {{end}}
    {{else}}
        ProcHook::EXTENSION_CORE,

        {{if eq $.Name "vkGetDeviceProcAddr"}}
          reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
        {{else}}
          reinterpret_cast<PFN_vkVoidFunction>({{$base}}_Bottom),
        {{end}}
        nullptr,
        nullptr,
    {{end}}
  },
{{end}}


{{/*
-------------------------------------------------------------------------------
  Emits a function/extension name without the "vk"/"VK_" prefix.
@@ -517,3 +894,16 @@ bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc) {
  {{else if eq $ext "VK_KHR_android_surface"}}true
  {{end}}
{{end}}


{{/*
------------------------------------------------------------------------------
  Reports whether an extension is internal to the loader and drivers,
  so the loader should not enumerate it.
------------------------------------------------------------------------------
*/}}
{{define "IsExtensionInternal"}}
  {{$ext := index $.Arguments 0}}
  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
  {{end}}
{{end}}
+0 −39
Original line number Diff line number Diff line
@@ -118,47 +118,8 @@ struct DriverDispatchTable {«

using namespace vulkan;

namespace {

struct NameProc {
    const char* name;
    PFN_vkVoidFunction proc;
};

PFN_vkVoidFunction Lookup(const char* name, const NameProc* begin, const NameProc* end) {
    const auto& entry = std::lower_bound(
        begin, end, name,
        [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
    if (entry == end || strcmp(entry->name, name) != 0)
        return nullptr;
    return entry->proc;
}

template <size_t N>
PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
    return Lookup(name, procs, procs + N);
}

const NameProc kLoaderBottomProcs[] = {«
    // clang-format off
  {{range $f := SortBy (AllCommands $) "FunctionName"}}
    {{if (Macro "HasLoaderBottomImpl" $f)}}
    {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
        static_cast<{{Macro "FunctionPtrName" $f}}>(§
            {{Macro "BaseName" $f}}_Bottom))},
    {{end}}
  {{end}}
    // clang-format on
»};

} // anonymous namespace

namespace vulkan {

PFN_vkVoidFunction GetLoaderBottomProcAddr(const char* name) {
    return Lookup(name, kLoaderBottomProcs);
}

bool LoadDriverDispatchTable(VkInstance instance,
                             PFN_vkGetInstanceProcAddr get_proc_addr,
                             const InstanceExtensionSet& extensions,
+0 −66
Original line number Diff line number Diff line
@@ -24,74 +24,8 @@

using namespace vulkan;

namespace {

struct NameProc {
    const char* name;
    PFN_vkVoidFunction proc;
};

PFN_vkVoidFunction Lookup(const char* name,
                          const NameProc* begin,
                          const NameProc* end) {
    const auto& entry = std::lower_bound(
        begin, end, name,
        [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
    if (entry == end || strcmp(entry->name, name) != 0)
        return nullptr;
    return entry->proc;
}

template <size_t N>
PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
    return Lookup(name, procs, procs + N);
}

const NameProc kLoaderBottomProcs[] = {
    // clang-format off
    {"vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAcquireNextImageKHR>(AcquireNextImageKHR_Bottom))},
    {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAllocateCommandBuffers>(AllocateCommandBuffers_Bottom))},
    {"vkCreateAndroidSurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateAndroidSurfaceKHR>(CreateAndroidSurfaceKHR_Bottom))},
    {"vkCreateDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDebugReportCallbackEXT>(CreateDebugReportCallbackEXT_Bottom))},
    {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDevice>(CreateDevice_Bottom))},
    {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance_Bottom))},
    {"vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSwapchainKHR>(CreateSwapchainKHR_Bottom))},
    {"vkDebugReportMessageEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDebugReportMessageEXT>(DebugReportMessageEXT_Bottom))},
    {"vkDestroyDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDebugReportCallbackEXT>(DestroyDebugReportCallbackEXT_Bottom))},
    {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDevice>(DestroyDevice_Bottom))},
    {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyInstance>(DestroyInstance_Bottom))},
    {"vkDestroySurfaceKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySurfaceKHR>(DestroySurfaceKHR_Bottom))},
    {"vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySwapchainKHR>(DestroySwapchainKHR_Bottom))},
    {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceExtensionProperties>(EnumerateDeviceExtensionProperties_Bottom))},
    {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceLayerProperties>(EnumerateDeviceLayerProperties_Bottom))},
    {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumeratePhysicalDevices>(EnumeratePhysicalDevices_Bottom))},
    {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr_Bottom))},
    {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue_Bottom))},
    {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr_Bottom))},
    {"vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures>(GetPhysicalDeviceFeatures_Bottom))},
    {"vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties>(GetPhysicalDeviceFormatProperties_Bottom))},
    {"vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(GetPhysicalDeviceImageFormatProperties_Bottom))},
    {"vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(GetPhysicalDeviceMemoryProperties_Bottom))},
    {"vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties>(GetPhysicalDeviceProperties_Bottom))},
    {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(GetPhysicalDeviceQueueFamilyProperties_Bottom))},
    {"vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(GetPhysicalDeviceSparseImageFormatProperties_Bottom))},
    {"vkGetPhysicalDeviceSurfaceCapabilitiesKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(GetPhysicalDeviceSurfaceCapabilitiesKHR_Bottom))},
    {"vkGetPhysicalDeviceSurfaceFormatsKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(GetPhysicalDeviceSurfaceFormatsKHR_Bottom))},
    {"vkGetPhysicalDeviceSurfacePresentModesKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>(GetPhysicalDeviceSurfacePresentModesKHR_Bottom))},
    {"vkGetPhysicalDeviceSurfaceSupportKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(GetPhysicalDeviceSurfaceSupportKHR_Bottom))},
    {"vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSwapchainImagesKHR>(GetSwapchainImagesKHR_Bottom))},
    {"vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkQueuePresentKHR>(QueuePresentKHR_Bottom))},
    // clang-format on
};

}  // anonymous namespace

namespace vulkan {

PFN_vkVoidFunction GetLoaderBottomProcAddr(const char* name) {
    return Lookup(name, kLoaderBottomProcs);
}

bool LoadDriverDispatchTable(VkInstance instance,
                             PFN_vkGetInstanceProcAddr get_proc_addr,
                             const InstanceExtensionSet& extensions,
+62 −0
Original line number Diff line number Diff line
@@ -143,5 +143,67 @@ const VkAllocationCallbacks& GetDefaultAllocator() {
    return kDefaultAllocCallbacks;
}

PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
    const ProcHook* hook = GetProcHook(pName);
    if (!hook)
        return g_hwdevice->GetInstanceProcAddr(instance, pName);

    if (!instance) {
        if (hook->type == ProcHook::GLOBAL)
            return hook->proc;

        ALOGE(
            "Invalid use of vkGetInstanceProcAddr to query %s without an "
            "instance",
            pName);

        // Some naughty layers expect
        //
        //   vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
        //
        // to work.
        return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
    }

    PFN_vkVoidFunction proc;

    switch (hook->type) {
        case ProcHook::INSTANCE:
            proc = (GetData(instance).hook_extensions[hook->extension])
                       ? hook->proc
                       : hook->disabled_proc;
            break;
        case ProcHook::DEVICE:
            proc = (hook->extension == ProcHook::EXTENSION_CORE)
                       ? hook->proc
                       : hook->checked_proc;
            break;
        default:
            ALOGE(
                "Invalid use of vkGetInstanceProcAddr to query %s with an "
                "instance",
                pName);
            proc = nullptr;
            break;
    }

    return proc;
}

PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
    const ProcHook* hook = GetProcHook(pName);
    if (!hook)
        return GetData(device).get_device_proc_addr(device, pName);

    if (hook->type != ProcHook::DEVICE) {
        ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName);
        return nullptr;
    }

    return (GetData(device).hook_extensions[hook->extension])
               ? hook->proc
               : hook->disabled_proc;
}

}  // namespace driver
}  // namespace vulkan
Loading