libvulkan: Use a stub HAL when no real Vulkan HAL is present
This stub HAL enumerates zero VkPhysicalDevices. This allows a
VkInstane to be created and queried for physical devices successfully
even on devices without a Vulkan driver. Handling this with a stub HAL
avoids the need for NULL HAL and NULL driver function pointer checks
in many places throughout the loader, which would be more error-prone.
Fixes bug: 28100673
Change-Id: I76bea975929a85eda354730d6c815567b412b160
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 9dbdcc2..72b0981 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -23,6 +23,7 @@
#include <sys/prctl.h>
#include "driver.h"
+#include "stubhal.h"
// #define ENABLE_ALLOC_CALLSTACKS 1
#if ENABLE_ALLOC_CALLSTACKS
@@ -47,7 +48,7 @@
class CreateInfoWrapper {
public:
- CreateInfoWrapper(hwvulkan_device_t* hw_dev,
+ CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
const VkInstanceCreateInfo& create_info,
const VkAllocationCallbacks& allocator);
CreateInfoWrapper(VkPhysicalDevice physical_dev,
@@ -87,7 +88,7 @@
const VkAllocationCallbacks& allocator_;
union {
- hwvulkan_device_t* hw_dev_;
+ const hwvulkan_device_t* hw_dev_;
VkPhysicalDevice physical_dev_;
};
@@ -102,7 +103,7 @@
std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
};
-CreateInfoWrapper::CreateInfoWrapper(hwvulkan_device_t* hw_dev,
+CreateInfoWrapper::CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
const VkInstanceCreateInfo& create_info,
const VkAllocationCallbacks& allocator)
: is_instance_(true),
@@ -340,7 +341,7 @@
}
}
-hwvulkan_device_t* g_hwdevice = nullptr;
+const hwvulkan_device_t* g_hwdevice = nullptr;
VKAPI_ATTR void* DefaultAllocate(void*,
size_t size,
@@ -428,15 +429,17 @@
}
bool OpenHAL() {
- if (g_hwdevice)
- return true;
+ ALOG_ASSERT(!g_hwdevice, "OpenHAL called more than once");
+
+ // Use a stub device unless we successfully open a real HAL device.
+ g_hwdevice = &stubhal::kDevice;
const hwvulkan_module_t* module;
int result =
hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
if (result != 0) {
- ALOGE("failed to load vulkan hal: %s (%d)", strerror(-result), result);
- return false;
+ ALOGV("no Vulkan HAL present, using stub HAL");
+ return true;
}
hwvulkan_device_t* device;
@@ -444,7 +447,8 @@
module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
reinterpret_cast<hw_device_t**>(&device));
if (result != 0) {
- ALOGE("failed to open vulkan driver: %s (%d)", strerror(-result),
+ // Any device with a Vulkan HAL should be able to open the device.
+ ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
result);
return false;
}