From c889d3c5763d34ecfff99cff8df1c6e85aac00d0 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 16 Jul 2020 13:51:12 -0700 Subject: libvulkan: make vkEnumerateInstanceVersion trigger driver loading This is a globally dispatched api, and it's the best option to preload the driver in Zygote with minimum overhead. This change also updates some return codes according to the spec. Bug: 135536511 Test: take a trace and verify driver is loaded Change-Id: I6fe425ec568b13577d3d9471aa5f181cff44c61c --- vulkan/libvulkan/api.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'vulkan/libvulkan/api.cpp') diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp index 5b9affd03a..80166c8434 100644 --- a/vulkan/libvulkan/api.cpp +++ b/vulkan/libvulkan/api.cpp @@ -1256,7 +1256,7 @@ VkResult EnumerateInstanceLayerProperties(uint32_t* pPropertyCount, ATRACE_CALL(); if (!EnsureInitialized()) - return VK_ERROR_INITIALIZATION_FAILED; + return VK_ERROR_OUT_OF_HOST_MEMORY; uint32_t count = GetLayerCount(); @@ -1280,7 +1280,7 @@ VkResult EnumerateInstanceExtensionProperties( ATRACE_CALL(); if (!EnsureInitialized()) - return VK_ERROR_INITIALIZATION_FAILED; + return VK_ERROR_OUT_OF_HOST_MEMORY; if (pLayerName) { const Layer* layer = FindLayer(pLayerName); @@ -1456,6 +1456,11 @@ VkResult EnumerateDeviceExtensionProperties( VkResult EnumerateInstanceVersion(uint32_t* pApiVersion) { ATRACE_CALL(); + // Load the driver here if not done yet. This api will be used in Zygote + // for Vulkan driver pre-loading because of the minimum overhead. + if (!EnsureInitialized()) + return VK_ERROR_OUT_OF_HOST_MEMORY; + *pApiVersion = VK_API_VERSION_1_1; return VK_SUCCESS; } -- cgit v1.2.3-59-g8ed1b From 901f8ee258dbfff2090dc45badf3446266f0ae16 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Fri, 31 Jul 2020 13:18:49 -0700 Subject: Vulkan: unload builtin driver to reload updated driver if needed Android historically preloads GL driver in Zygote to speed up app launch time and avoid the duplicate extra memory for each process loading the graphics driver. In Android 10, we landed GL driver unloading mechanism to ship updatable driver and ANGLE without perf overhead on the rest of the system. To get prepared for the HWUI Vulkan backend being turned on as the default renderer for UI componments, this CL will do the same to the Vulkan driver to preload it in Zygote and unload so to reload updated driver if needed. Bug: 135536511 Test: atest CtsUiRenderingTestCases no regression on VK backend Change-Id: I2909f6ecc4f011b1f3670aacdf817ed3b6e9a487 --- vulkan/include/hardware/hwvulkan.h | 5 +++-- vulkan/libvulkan/api.cpp | 29 +++++++++++---------------- vulkan/libvulkan/driver.cpp | 41 +++++++++++++++++++++++++++++++++++++- 3 files changed, 55 insertions(+), 20 deletions(-) (limited to 'vulkan/libvulkan/api.cpp') diff --git a/vulkan/include/hardware/hwvulkan.h b/vulkan/include/hardware/hwvulkan.h index 9e9a14d489..98bc8e3c46 100644 --- a/vulkan/include/hardware/hwvulkan.h +++ b/vulkan/include/hardware/hwvulkan.h @@ -54,8 +54,9 @@ typedef union { /* A hwvulkan_device_t corresponds to an ICD on other systems. Currently there * can only be one on a system (HWVULKAN_DEVICE_0). It is opened once per * process when the Vulkan API is first used; the hw_device_t::close() function - * is never called. Any non-trivial resource allocation should be done when - * the VkInstance is created rather than when the hwvulkan_device_t is opened. + * is called upon driver unloading. Any non-trivial resource allocation should + * be done when the VkInstance is created rather than when the hwvulkan_device_t + * is opened. */ typedef struct hwvulkan_device_t { struct hw_device_t common; diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp index 80166c8434..2d4690a2af 100644 --- a/vulkan/libvulkan/api.cpp +++ b/vulkan/libvulkan/api.cpp @@ -1174,23 +1174,18 @@ const LayerChain::ActiveLayer* LayerChain::GetActiveLayers( // ---------------------------------------------------------------------------- bool EnsureInitialized() { - static std::once_flag once_flag; - static bool initialized; - - std::call_once(once_flag, []() { - if (driver::OpenHAL()) { - initialized = true; - } - }); - - { - static pid_t pid = getpid() + 1; - static std::mutex layer_lock; - std::lock_guard lock(layer_lock); - if (pid != getpid()) { - pid = getpid(); - DiscoverLayers(); - } + static bool initialized = false; + static pid_t init_attempted_for_pid = 0; + static std::mutex init_lock; + + std::lock_guard lock(init_lock); + if (init_attempted_for_pid == getpid()) + return initialized; + + init_attempted_for_pid = getpid(); + if (driver::OpenHAL()) { + DiscoverLayers(); + initialized = true; } return initialized; diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index e3fc67e35f..8deca47c66 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -84,6 +84,8 @@ class Hal { Hal(const Hal&) = delete; Hal& operator=(const Hal&) = delete; + bool ShouldUnloadBuiltinDriver(); + void UnloadBuiltinDriver(); bool InitDebugReportIndex(); static Hal hal_; @@ -243,7 +245,12 @@ bool Hal::Open() { const nsecs_t openTime = systemTime(); - ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once"); + if (hal_.ShouldUnloadBuiltinDriver()) { + hal_.UnloadBuiltinDriver(); + } + + if (hal_.dev_) + return true; // Use a stub device unless we successfully open a real HAL device. hal_.dev_ = &stubhal::kDevice; @@ -288,6 +295,38 @@ bool Hal::Open() { return true; } +bool Hal::ShouldUnloadBuiltinDriver() { + // Should not unload since the driver was not loaded + if (!hal_.dev_) + return false; + + // Should not unload if stubhal is used on the device + if (hal_.dev_ == &stubhal::kDevice) + return false; + + // Unload the driver if updated driver is chosen + if (android::GraphicsEnv::getInstance().getDriverNamespace()) + return true; + + return false; +} + +void Hal::UnloadBuiltinDriver() { + ATRACE_CALL(); + + ALOGD("Unload builtin Vulkan driver."); + + // Close the opened device + ALOG_ASSERT(!hal_.dev_->common.close(hal_.dev_->common), + "hw_device_t::close() failed."); + + // Close the opened shared library in the hw_module_t + dlclose(hal_.dev_->common.module->dso); + + hal_.dev_ = nullptr; + hal_.debug_report_index_ = -1; +} + bool Hal::InitDebugReportIndex() { ATRACE_CALL(); -- cgit v1.2.3-59-g8ed1b