VkExtensionProperties* driver_extensions_;
uint32_t driver_extension_count_;
+ std::bitset<driver::ProcHook::EXTENSION_COUNT> enabled_extensions_;
};
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_);
// 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);
// 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);
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;
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;
} \
} 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;
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;
#ifndef LIBVULKAN_API_GEN_H
#define LIBVULKAN_API_GEN_H
+#include <bitset>
#include <vulkan/vulkan.h>
+#include "driver_gen.h"
namespace vulkan {
namespace api {
// 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
#ifndef LIBVULKAN_API_GEN_H
#define LIBVULKAN_API_GEN_H
¶
+#include <bitset>
#include <vulkan/vulkan.h>
+#include "driver_gen.h"
¶
namespace vulkan {«
namespace api {«
// 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
¶
{{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;
¶
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;
¶
-------------------------------------------------------------------------------
*/}}
{{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.
------------------------------------------------------------------------------