[vulkan] Add feature flag
bug: 111137294
This allows us to build the HAL, but not activate it unless a
feature flag is enabled.
If the feature flag is not enabled, the stub hal is used.
Change-Id: I678a1eea0f36fd1574c78a400676f7189a8fc53c
diff --git a/system/vulkan/goldfish_vulkan.cpp b/system/vulkan/goldfish_vulkan.cpp
index 0fc48e0..4e80c45 100644
--- a/system/vulkan/goldfish_vulkan.cpp
+++ b/system/vulkan/goldfish_vulkan.cpp
@@ -24,6 +24,105 @@
#include "func_table.h"
+#include <array>
+#include <bitset>
+#include <mutex>
+
+// Used when there is no Vulkan support on the host.
+// Copied from frameworks/native/vulkan/libvulkan/stubhal.cpp
+namespace vkstubhal {
+
+const size_t kMaxInstances = 32;
+static std::mutex g_instance_mutex;
+static std::bitset<kMaxInstances> g_instance_used(false);
+static std::array<hwvulkan_dispatch_t, kMaxInstances> g_instances;
+
+[[noreturn]] VKAPI_ATTR void NoOp() {
+ LOG_ALWAYS_FATAL("invalid stub function called");
+}
+
+VkResult
+EnumerateInstanceExtensionProperties(const char* /*layer_name*/,
+ uint32_t* count,
+ VkExtensionProperties* /*properties*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+VkResult
+EnumerateInstanceLayerProperties(uint32_t* count,
+ VkLayerProperties* /*properties*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
+ const VkAllocationCallbacks* /*allocator*/,
+ VkInstance* instance) {
+ std::lock_guard<std::mutex> lock(g_instance_mutex);
+ for (size_t i = 0; i < kMaxInstances; i++) {
+ if (!g_instance_used[i]) {
+ g_instance_used[i] = true;
+ g_instances[i].magic = HWVULKAN_DISPATCH_MAGIC;
+ *instance = reinterpret_cast<VkInstance>(&g_instances[i]);
+ return VK_SUCCESS;
+ }
+ }
+ ALOGE("no more instances available (max=%zu)", kMaxInstances);
+ return VK_ERROR_INITIALIZATION_FAILED;
+}
+
+void DestroyInstance(VkInstance instance,
+ const VkAllocationCallbacks* /*allocator*/) {
+ std::lock_guard<std::mutex> lock(g_instance_mutex);
+ ssize_t idx =
+ reinterpret_cast<hwvulkan_dispatch_t*>(instance) - &g_instances[0];
+ ALOG_ASSERT(idx >= 0 && static_cast<size_t>(idx) < g_instance_used.size(),
+ "DestroyInstance: invalid instance handle");
+ g_instance_used[static_cast<size_t>(idx)] = false;
+}
+
+VkResult EnumeratePhysicalDevices(VkInstance /*instance*/,
+ uint32_t* count,
+ VkPhysicalDevice* /*gpus*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+VkResult
+EnumeratePhysicalDeviceGroups(VkInstance /*instance*/,
+ uint32_t* count,
+ VkPhysicalDeviceGroupProperties* /*properties*/) {
+ *count = 0;
+ return VK_SUCCESS;
+}
+
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance,
+ const char* name) {
+ if (strcmp(name, "vkCreateInstance") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
+ if (strcmp(name, "vkDestroyInstance") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
+ if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(
+ EnumerateInstanceExtensionProperties);
+ if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
+ if (strcmp(name, "vkEnumeratePhysicalDeviceGroups") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(
+ EnumeratePhysicalDeviceGroups);
+ if (strcmp(name, "vkGetInstanceProcAddr") == 0)
+ return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
+ // Per the spec, return NULL if instance is NULL.
+ if (!instance)
+ return nullptr;
+ // None of the other Vulkan functions should ever be called, as they all
+ // take a VkPhysicalDevice or other object obtained from a physical device.
+ return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
+}
+
+} // namespace vkstubhal
+
namespace {
int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device);
@@ -49,23 +148,24 @@
return 0;
}
-#define VK_HOST_CONNECTION \
+#define VK_HOST_CONNECTION(ret) \
HostConnection *hostCon = HostConnection::get(); \
if (!hostCon) { \
ALOGE("vulkan: Failed to get host connection\n"); \
- return VK_ERROR_DEVICE_LOST; \
+ return ret; \
} \
ExtendedRCEncoderContext *rcEnc = hostCon->rcEncoder(); \
if (!rcEnc) { \
ALOGE("vulkan: Failed to get renderControl encoder context\n"); \
- return VK_ERROR_DEVICE_LOST; \
+ return ret; \
} \
goldfish_vk::VkEncoder *vkEnc = hostCon->vkEncoder(); \
if (!vkEnc) { \
ALOGE("vulkan: Failed to get Vulkan encoder\n"); \
- return VK_ERROR_DEVICE_LOST; \
+ return ret; \
} \
goldfish_vk::ResourceTracker::get()->setupFeatures(rcEnc->featureInfo_const()); \
+ auto hostSupportsVulkan = goldfish_vk::ResourceTracker::get()->hostSupportsVulkan(); \
VKAPI_ATTR
VkResult EnumerateInstanceExtensionProperties(
@@ -73,7 +173,11 @@
uint32_t* count,
VkExtensionProperties* properties) {
- VK_HOST_CONNECTION;
+ VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
+
+ if (!hostSupportsVulkan) {
+ return vkstubhal::EnumerateInstanceExtensionProperties(layer_name, count, properties);
+ }
if (layer_name) {
ALOGW(
@@ -92,8 +196,11 @@
VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
const VkAllocationCallbacks* allocator,
VkInstance* out_instance) {
- ALOGD("%s: goldfish vkCreateInstance\n", __func__);
- VK_HOST_CONNECTION;
+ VK_HOST_CONNECTION(VK_ERROR_DEVICE_LOST)
+
+ if (!hostSupportsVulkan) {
+ return vkstubhal::CreateInstance(create_info, allocator, out_instance);
+ }
VkResult res = vkEnc->vkCreateInstance(create_info, nullptr, out_instance);
@@ -101,6 +208,12 @@
}
static PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
+ VK_HOST_CONNECTION(nullptr)
+
+ if (!hostSupportsVulkan) {
+ return nullptr;
+ }
+
if (!strcmp(name, "vkGetDeviceProcAddr")) {
return (PFN_vkVoidFunction)(GetDeviceProcAddr);
}
@@ -109,6 +222,12 @@
VKAPI_ATTR
PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
+ VK_HOST_CONNECTION(nullptr)
+
+ if (!hostSupportsVulkan) {
+ return vkstubhal::GetInstanceProcAddr(instance, name);
+ }
+
if (!strcmp(name, "vkEnumerateInstanceExtensionProperties")) {
return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties;
}
@@ -144,4 +263,4 @@
return -ENOENT;
}
-} // namespace
\ No newline at end of file
+} // namespace
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index a693ebd..3cacf39 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -328,6 +328,12 @@
}
}
+ bool hostSupportsVulkan() const {
+ if (!mFeatureInfo) return false;
+
+ return mFeatureInfo->hasVulkan;
+ }
+
bool usingDirectMapping() const {
return mHostVisibleMemoryVirtInfo.virtualizationSupported;
}
@@ -1136,6 +1142,10 @@
mImpl->setupFeatures(features);
}
+bool ResourceTracker::hostSupportsVulkan() const {
+ return mImpl->hostSupportsVulkan();
+}
+
bool ResourceTracker::usingDirectMapping() const {
return mImpl->usingDirectMapping();
}
diff --git a/system/vulkan_enc/ResourceTracker.h b/system/vulkan_enc/ResourceTracker.h
index cdbb54d..c63dfc0 100644
--- a/system/vulkan_enc/ResourceTracker.h
+++ b/system/vulkan_enc/ResourceTracker.h
@@ -143,6 +143,7 @@
VkDeviceSize getNonCoherentExtendedSize(VkDevice device, VkDeviceSize basicSize) const;
bool isValidMemoryRange(const VkMappedMemoryRange& range) const;
void setupFeatures(const EmulatorFeatureInfo* features);
+ bool hostSupportsVulkan() const;
bool usingDirectMapping() const;
void deviceMemoryTransform_tohost(
VkDeviceMemory* memory, uint32_t memoryCount,
@@ -167,4 +168,4 @@
std::unique_ptr<Impl> mImpl;
};
-} // namespace goldfish_vk
\ No newline at end of file
+} // namespace goldfish_vk