diff options
author | 2024-08-13 20:45:14 +0000 | |
---|---|---|
committer | 2024-09-19 19:04:31 +0000 | |
commit | 9a9e06c425ea0a93f1553407d65fef2ab2d4f12b (patch) | |
tree | 71d0fff9f5784a3daa1971873e43e41b96b9d125 | |
parent | 7a9c9eecd8055336fc46bfa6edab039092a0fe04 (diff) |
[Vulkan] Query global priority support for queue creation
Setting up a device queue with a global queue priority above the system
default requires sufficient privileges (SYS_NICE) otherwise queue
creation will fail.
SurfaceFlinger and system_server have SYS_NICE and will set priority to
REALTIME. SysUI and Launcher take that as an indication they should
request HIGH for better preemption strategy. However for upstream DRM
drivers, we currently lack a way to grant them granular access to HIGH
but not RT. For long term, the right way to do this is via drm specific
cgroup for scheduling controls however this is currently being worked
on upstream.
In the meantime, instead of fatally crashing, we can query the global
priorities supported before queue creation and if its not supported,
drop the priority request and log a warning.
Note this requires vkGetPhysicalDeviceQueueFamilyProperties2 which is
provided by Vulkan 1.1 while the global priority query can be safely
added to the pNext chain and will be ignored if
VK_EXT_global_priority_query isn't supported.
Bug: 343986434
Flag: com.android.graphics.hwui.flags.query_global_priority
Test: UI comes up debug.renderengine.backend=skiavkthreaded
Change-Id: I662c9ce3f3724e87690e25d260ee010340451c53
-rw-r--r-- | libs/hwui/Properties.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/Properties.h | 1 | ||||
-rw-r--r-- | libs/hwui/aconfig/hwui_flags.aconfig | 10 | ||||
-rw-r--r-- | libs/hwui/renderthread/VulkanManager.cpp | 85 | ||||
-rw-r--r-- | libs/hwui/renderthread/VulkanManager.h | 2 |
5 files changed, 88 insertions, 16 deletions
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index b6476c9d466f..ae46a99f09c8 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -50,6 +50,10 @@ constexpr bool skip_eglmanager_telemetry() { constexpr bool resample_gainmap_regions() { return false; } + +constexpr bool query_global_priority() { + return false; +} } // namespace hwui_flags #endif @@ -110,6 +114,7 @@ bool Properties::clipSurfaceViews = false; bool Properties::hdr10bitPlus = false; bool Properties::skipTelemetry = false; bool Properties::resampleGainmapRegions = false; +bool Properties::queryGlobalPriority = false; int Properties::timeoutMultiplier = 1; @@ -187,6 +192,7 @@ bool Properties::load() { hdr10bitPlus = hwui_flags::hdr_10bit_plus(); resampleGainmapRegions = base::GetBoolProperty("debug.hwui.resample_gainmap_regions", hwui_flags::resample_gainmap_regions()); + queryGlobalPriority = hwui_flags::query_global_priority(); timeoutMultiplier = android::base::GetIntProperty("ro.hw_timeout_multiplier", 1); skipTelemetry = base::GetBoolProperty(PROPERTY_SKIP_EGLMANAGER_TELEMETRY, diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index db471527b861..6f84796fb11e 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -346,6 +346,7 @@ public: static bool hdr10bitPlus; static bool skipTelemetry; static bool resampleGainmapRegions; + static bool queryGlobalPriority; static int timeoutMultiplier; diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig index ab052b902e02..93df47853769 100644 --- a/libs/hwui/aconfig/hwui_flags.aconfig +++ b/libs/hwui/aconfig/hwui_flags.aconfig @@ -129,3 +129,13 @@ flag { description: "APIs that expose gainmap metadata corresponding to those defined in ISO 21496-1" bug: "349357636" } + +flag { + name: "query_global_priority" + namespace: "core_graphics" + description: "Attempt to query whether the vulkan driver supports the requested global priority before queue creation." + bug: "343986434" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index e3023937964e..6571d92aeafa 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -44,7 +44,7 @@ namespace uirenderer { namespace renderthread { // Not all of these are strictly required, but are all enabled if present. -static std::array<std::string_view, 21> sEnableExtensions{ +static std::array<std::string_view, 23> sEnableExtensions{ VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME, @@ -65,6 +65,8 @@ static std::array<std::string_view, 21> sEnableExtensions{ VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, + VK_EXT_GLOBAL_PRIORITY_QUERY_EXTENSION_NAME, + VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME, VK_EXT_DEVICE_FAULT_EXTENSION_NAME, }; @@ -206,7 +208,7 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions, GET_INST_PROC(GetPhysicalDeviceFeatures2); GET_INST_PROC(GetPhysicalDeviceImageFormatProperties2); GET_INST_PROC(GetPhysicalDeviceProperties); - GET_INST_PROC(GetPhysicalDeviceQueueFamilyProperties); + GET_INST_PROC(GetPhysicalDeviceQueueFamilyProperties2); uint32_t gpuCount; LOG_ALWAYS_FATAL_IF(mEnumeratePhysicalDevices(mInstance, &gpuCount, nullptr)); @@ -225,21 +227,30 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions, // query to get the initial queue props size uint32_t queueCount = 0; - mGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr); + mGetPhysicalDeviceQueueFamilyProperties2(mPhysicalDevice, &queueCount, nullptr); LOG_ALWAYS_FATAL_IF(!queueCount); // now get the actual queue props - std::unique_ptr<VkQueueFamilyProperties[]> queueProps(new VkQueueFamilyProperties[queueCount]); - mGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, queueProps.get()); + std::unique_ptr<VkQueueFamilyProperties2[]> + queueProps(new VkQueueFamilyProperties2[queueCount]); + // query the global priority, this ignored if VK_EXT_global_priority isn't supported + std::vector<VkQueueFamilyGlobalPriorityPropertiesEXT> queuePriorityProps(queueCount); + for (uint32_t i = 0; i < queueCount; i++) { + queuePriorityProps[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_EXT; + queuePriorityProps[i].pNext = nullptr; + queueProps[i].pNext = &queuePriorityProps[i]; + } + mGetPhysicalDeviceQueueFamilyProperties2(mPhysicalDevice, &queueCount, queueProps.get()); constexpr auto kRequestedQueueCount = 2; // iterate to find the graphics queue mGraphicsQueueIndex = queueCount; for (uint32_t i = 0; i < queueCount; i++) { - if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { + if (queueProps[i].queueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT) { mGraphicsQueueIndex = i; - LOG_ALWAYS_FATAL_IF(queueProps[i].queueCount < kRequestedQueueCount); + LOG_ALWAYS_FATAL_IF( + queueProps[i].queueFamilyProperties.queueCount < kRequestedQueueCount); break; } } @@ -327,6 +338,15 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions, tailPNext = &formatFeatures->pNext; } + VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT* globalPriorityQueryFeatures = + new VkPhysicalDeviceGlobalPriorityQueryFeaturesEXT; + globalPriorityQueryFeatures->sType = + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_EXT; + globalPriorityQueryFeatures->pNext = nullptr; + globalPriorityQueryFeatures->globalPriorityQuery = false; + *tailPNext = globalPriorityQueryFeatures; + tailPNext = &globalPriorityQueryFeatures->pNext; + // query to get the physical device features mGetPhysicalDeviceFeatures2(mPhysicalDevice, &features); // this looks like it would slow things down, @@ -341,24 +361,59 @@ void VulkanManager::setupDevice(skgpu::VulkanExtensions& grExtensions, if (Properties::contextPriority != 0 && grExtensions.hasExtension(VK_EXT_GLOBAL_PRIORITY_EXTENSION_NAME, 2)) { - memset(&queuePriorityCreateInfo, 0, sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT)); - queuePriorityCreateInfo.sType = - VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT; - queuePriorityCreateInfo.pNext = nullptr; + VkQueueGlobalPriorityEXT globalPriority; switch (Properties::contextPriority) { case EGL_CONTEXT_PRIORITY_LOW_IMG: - queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT; + globalPriority = VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT; break; case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: - queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT; + globalPriority = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT; break; case EGL_CONTEXT_PRIORITY_HIGH_IMG: - queuePriorityCreateInfo.globalPriority = VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT; + globalPriority = VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT; break; default: LOG_ALWAYS_FATAL("Unsupported context priority"); } - queueNextPtr = &queuePriorityCreateInfo; + + // check if the requested priority is reported by the query + bool attachGlobalPriority = false; + if (uirenderer::Properties::queryGlobalPriority && + globalPriorityQueryFeatures->globalPriorityQuery) { + for (uint32_t i = 0; i < queuePriorityProps[mGraphicsQueueIndex].priorityCount; i++) { + if (queuePriorityProps[mGraphicsQueueIndex].priorities[i] == globalPriority) { + attachGlobalPriority = true; + break; + } + } + } else { + // Querying is not supported so attempt queue creation with requested priority anyways + // If the priority turns out not to be supported, the driver *may* fail with + // VK_ERROR_NOT_PERMITTED_KHR + attachGlobalPriority = true; + } + + if (attachGlobalPriority) { + memset(&queuePriorityCreateInfo, 0, sizeof(VkDeviceQueueGlobalPriorityCreateInfoEXT)); + queuePriorityCreateInfo.sType = + VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT; + queuePriorityCreateInfo.pNext = nullptr; + queuePriorityCreateInfo.globalPriority = globalPriority; + queueNextPtr = &queuePriorityCreateInfo; + } else { + // If globalPriorityQuery is enabled, attempting queue creation with an unsupported + // priority will return VK_ERROR_INITIALIZATION_FAILED. + // + // SysUI and Launcher will request HIGH when SF has RT but it is a known issue that + // upstream drm drivers currently lack a way to grant them the granular privileges + // they need for HIGH (but not RT) so they will fail queue creation. + // For now, drop the unsupported global priority request so that queue creation + // succeeds. + // + // Once that is fixed, this should probably be a fatal error indicating an improper + // request or an app needs to get the correct privileges. + ALOGW("Requested context priority is not supported by the queue"); + } } const VkDeviceQueueCreateInfo queueInfo = { diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index f0425719ea89..a593ec6f8351 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -152,7 +152,7 @@ private: VkPtr<PFN_vkDestroyInstance> mDestroyInstance; VkPtr<PFN_vkEnumeratePhysicalDevices> mEnumeratePhysicalDevices; VkPtr<PFN_vkGetPhysicalDeviceProperties> mGetPhysicalDeviceProperties; - VkPtr<PFN_vkGetPhysicalDeviceQueueFamilyProperties> mGetPhysicalDeviceQueueFamilyProperties; + VkPtr<PFN_vkGetPhysicalDeviceQueueFamilyProperties2> mGetPhysicalDeviceQueueFamilyProperties2; VkPtr<PFN_vkGetPhysicalDeviceFeatures2> mGetPhysicalDeviceFeatures2; VkPtr<PFN_vkGetPhysicalDeviceImageFormatProperties2> mGetPhysicalDeviceImageFormatProperties2; VkPtr<PFN_vkCreateDevice> mCreateDevice; |