diff options
author | 2016-03-24 09:11:06 +0800 | |
---|---|---|
committer | 2016-04-07 21:15:03 +0800 | |
commit | eb7db124e46da9a9210cf868353f5ea79502ffec (patch) | |
tree | 58801422f306957db776bcaa000e648ce7b6bd82 /vulkan/libvulkan/driver.cpp | |
parent | b262ddcfaba592ca153beddb120aeb68b64e6e63 (diff) |
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
Diffstat (limited to 'vulkan/libvulkan/driver.cpp')
-rw-r--r-- | vulkan/libvulkan/driver.cpp | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index 4acc867201..68ae5c8314 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -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 |