From 43c53e3225215d387f9bd332a56236749eb5bfc3 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 7 Sep 2022 16:26:25 -0700 Subject: [PATCH] turnip: add support for VK_KHR_global_priority Part-of: --- docs/features.txt | 6 +- src/freedreno/vulkan/tu_device.c | 120 +++++++++++++++++++++++++++++++++------ src/freedreno/vulkan/tu_drm.c | 4 +- 3 files changed, 110 insertions(+), 20 deletions(-) diff --git a/docs/features.txt b/docs/features.txt index f34df84..aebca53 100644 --- a/docs/features.txt +++ b/docs/features.txt @@ -513,7 +513,7 @@ Khronos extensions that are not part of any Vulkan version: VK_KHR_fragment_shading_rate DONE (anv/gen11+, radv/gfx10.3+) VK_KHR_get_display_properties2 DONE (anv, radv, tu, v3dv) VK_KHR_get_surface_capabilities2 DONE (anv, lvp, radv, tu, v3dv, vn) - VK_KHR_global_priority DONE (radv) + VK_KHR_global_priority DONE (radv, tu) VK_KHR_incremental_present DONE (anv, lvp, radv, tu, v3dv, vn) VK_KHR_performance_query DONE (anv/gen8+, radv/gfx10.3+, tu, v3dv) VK_KHR_pipeline_executable_properties DONE (anv, radv, tu, v3dv) @@ -553,8 +553,8 @@ Khronos extensions that are not part of any Vulkan version: VK_EXT_external_memory_host DONE (anv, lvp, radv) VK_EXT_filter_cubic DONE (tu/a650) VK_EXT_fragment_shader_interlock DONE (anv/gen9+) - VK_EXT_global_priority DONE (anv, radv) - VK_EXT_global_priority_query DONE (anv, radv) + VK_EXT_global_priority DONE (anv, radv, tu) + VK_EXT_global_priority_query DONE (anv, radv, tu) VK_EXT_graphics_pipeline_library DONE (lvp) VK_EXT_image_2d_view_of_3d DONE (anv, radv, tu, lvp) VK_EXT_image_drm_format_modifier DONE (anv, radv/gfx9+, tu, v3dv, vn) diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index 2f76ae2..f58a576 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -134,6 +134,7 @@ get_device_extensions(const struct tu_physical_device *device, .KHR_external_semaphore_fd = true, .KHR_format_feature_flags2 = true, .KHR_get_memory_requirements2 = true, + .KHR_global_priority = true, .KHR_imageless_framebuffer = true, .KHR_incremental_present = TU_HAS_SURFACE, .KHR_image_format_list = true, @@ -189,6 +190,8 @@ get_device_extensions(const struct tu_physical_device *device, .EXT_extended_dynamic_state = true, .EXT_extended_dynamic_state2 = true, .EXT_filter_cubic = device->info->a6xx.has_tex_filter_cubic, + .EXT_global_priority = true, + .EXT_global_priority_query = true, .EXT_host_query_reset = true, .EXT_index_type_uint8 = true, .EXT_memory_budget = true, @@ -886,6 +889,12 @@ tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, features->attachmentFeedbackLoopLayout = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR: { + VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR *features = + (VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR*)ext; + features->globalPriorityQuery = true; + break; + } default: break; @@ -1359,18 +1368,91 @@ static const VkQueueFamilyProperties tu_queue_family_properties = { .minImageTransferGranularity = { 1, 1, 1 }, }; +static void +tu_physical_device_get_global_priority_properties(const struct tu_physical_device *pdevice, + VkQueueFamilyGlobalPriorityPropertiesKHR *props) +{ + props->priorityCount = MIN2(pdevice->submitqueue_priority_count, 3); + switch (props->priorityCount) { + case 1: + props->priorities[0] = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR; + break; + case 2: + props->priorities[0] = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR; + props->priorities[1] = VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR; + break; + case 3: + props->priorities[0] = VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR; + props->priorities[1] = VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR; + props->priorities[2] = VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR; + break; + default: + unreachable("unexpected priority count"); + break; + } +} + +static int +tu_physical_device_get_submitqueue_priority(const struct tu_physical_device *pdevice, + VkQueueGlobalPriorityKHR global_priority, + bool global_priority_query) +{ + if (global_priority_query) { + VkQueueFamilyGlobalPriorityPropertiesKHR props; + tu_physical_device_get_global_priority_properties(pdevice, &props); + + bool valid = false; + for (uint32_t i = 0; i < props.priorityCount; i++) { + if (props.priorities[i] == global_priority) { + valid = true; + break; + } + } + + if (!valid) + return -1; + } + + /* Valid values are from 0 to (pdevice->submitqueue_priority_count - 1), + * with 0 being the highest priority. This matches what freedreno does. + */ + int priority; + if (global_priority == VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR) + priority = pdevice->submitqueue_priority_count / 2; + else if (global_priority < VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR) + priority = pdevice->submitqueue_priority_count - 1; + else + priority = 0; + + return priority; +} + VKAPI_ATTR void VKAPI_CALL tu_GetPhysicalDeviceQueueFamilyProperties2( VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties2 *pQueueFamilyProperties) { + TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice); + VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, out, pQueueFamilyProperties, pQueueFamilyPropertyCount); vk_outarray_append_typed(VkQueueFamilyProperties2, &out, p) { p->queueFamilyProperties = tu_queue_family_properties; + + vk_foreach_struct(ext, p->pNext) { + switch (ext->sType) { + case VK_STRUCTURE_TYPE_QUEUE_FAMILY_GLOBAL_PRIORITY_PROPERTIES_KHR: { + VkQueueFamilyGlobalPriorityPropertiesKHR *props = (void *)ext; + tu_physical_device_get_global_priority_properties(pdevice, props); + break; + } + default: + break; + } + } } } @@ -1458,21 +1540,21 @@ static VkResult tu_queue_init(struct tu_device *device, struct tu_queue *queue, int idx, - const VkDeviceQueueCreateInfo *create_info) -{ - - /* Match the default priority of fd_context_init. We ignore - * pQueuePriorities because the spec says - * - * An implementation may allow a higher-priority queue to starve a - * lower-priority queue on the same VkDevice until the higher-priority - * queue has no further commands to execute. The relationship of queue - * priorities must not cause queues on one VkDevice to starve queues on - * another VkDevice. - * - * We cannot let one VkDevice starve another. - */ - const int priority = 1; + const VkDeviceQueueCreateInfo *create_info, + bool global_priority_query) +{ + const VkDeviceQueueGlobalPriorityCreateInfoKHR *priority_info = + vk_find_struct_const(create_info->pNext, + DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR); + const enum VkQueueGlobalPriorityKHR global_priority = priority_info ? + priority_info->globalPriority : VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR; + + const int priority = tu_physical_device_get_submitqueue_priority( + device->physical_device, global_priority, global_priority_query); + if (priority < 0) { + return vk_startup_errorf(device->instance, VK_ERROR_INITIALIZATION_FAILED, + "invalid global priority"); + } VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info, idx); if (result != VK_SUCCESS) @@ -1773,6 +1855,7 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice, bool perf_query_pools = false; bool robust_buffer_access2 = false; bool border_color_without_format = false; + bool global_priority_query = false; vk_foreach_struct_const(ext, pCreateInfo->pNext) { switch (ext->sType) { @@ -1794,6 +1877,11 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice, robust_buffer_access2 = features->robustBufferAccess2; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR: { + VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR *features = (void *)ext; + global_priority_query = features->globalPriorityQuery; + break; + } default: break; } @@ -1855,7 +1943,7 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice, for (unsigned q = 0; q < queue_create->queueCount; q++) { result = tu_queue_init(device, &device->queues[qfi][q], q, - queue_create); + queue_create, global_priority_query); if (result != VK_SUCCESS) { device->queue_count[qfi] = q; goto fail_queues; diff --git a/src/freedreno/vulkan/tu_drm.c b/src/freedreno/vulkan/tu_drm.c index f209ef4..6eb2f21 100644 --- a/src/freedreno/vulkan/tu_drm.c +++ b/src/freedreno/vulkan/tu_drm.c @@ -174,9 +174,11 @@ tu_drm_submitqueue_new(const struct tu_device *dev, int priority, uint32_t *queue_id) { + assert(priority >= 0 && + priority < dev->physical_device->submitqueue_priority_count); struct drm_msm_submitqueue req = { .flags = 0, - .prio = MIN2(priority, dev->physical_device->submitqueue_priority_count - 1), + .prio = priority, }; int ret = drmCommandWriteRead(dev->fd, -- 2.7.4