From ae904e11a897c6b25ed65a6b6de8ae147336d774 Mon Sep 17 00:00:00 2001 From: Aaron Ruby Date: Fri, 18 Jul 2025 13:25:33 -0400 Subject: [PATCH] gfxstream: init vk_queues in CreateDevice() based on queueCreateInfo ... and defer getDeviceQueue impl to vk_common and trim down impls in gfxstream. gfxstream advertises, and selects queues/queueFamilies from what the real device on the host advertises. During createDevice(), it needs to allocate the queue objects to support this. Part-of: --- .../codegen/scripts/cereal/functable.py | 10 +- .../guest/vulkan/gfxstream_vk_device.cpp | 109 ++++++++---------- .../guest/vulkan_enc/gfxstream_vk_private.h | 7 ++ 3 files changed, 64 insertions(+), 62 deletions(-) diff --git a/src/gfxstream/codegen/scripts/cereal/functable.py b/src/gfxstream/codegen/scripts/cereal/functable.py index d47982f4eae..d652579444f 100644 --- a/src/gfxstream/codegen/scripts/cereal/functable.py +++ b/src/gfxstream/codegen/scripts/cereal/functable.py @@ -110,7 +110,9 @@ SUCCESS_VAL = { "VkResult" : ["VK_SUCCESS"], } -HANDWRITTEN_ENTRY_POINTS = [ +# These could be entrypoints that are custom-written for gfxstream, or ones that +# are meant fall back to the vk_common_* entrypoints +NON_AUTOGEN_ENTRYPOINTS = [ # Instance/device/physical-device special-handling, dispatch tables, etc.. "vkCreateInstance", "vkDestroyInstance", @@ -125,7 +127,6 @@ HANDWRITTEN_ENTRY_POINTS = [ "vkCreateDevice", "vkDestroyDevice", # Manual alloc/free + vk_*_init/free() call w/ special params - "vkGetDeviceQueue", "vkGetDeviceQueue2", # Command pool/buffer handling "vkCreateCommandPool", @@ -140,6 +141,9 @@ HANDWRITTEN_ENTRY_POINTS = [ # TODO: Make a codegen module (use deepcopy as reference) to make this more robust "vkAllocateMemory", "vkUpdateDescriptorSets", + + # Use vk_common_* entrypoints; usually just dispatches to the "vk*2()" API variant + "vkGetDeviceQueue", ] # Handles that need to be translated to/from their corresponding gfxstream object types @@ -562,7 +566,7 @@ class VulkanFuncTable(VulkanWrapperGenerator): genReturnExpression() api_entry = api.withModifiedName("gfxstream_vk_" + api.name[2:]) - if api.name not in HANDWRITTEN_ENTRY_POINTS: + if api.name not in NON_AUTOGEN_ENTRYPOINTS: cgen.line(self.cgen.makeFuncProto(api_entry)) cgen.beginBlock() genGfxstreamEntry() diff --git a/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp b/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp index 2a943c0ec29..4aecf805022 100644 --- a/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp +++ b/src/gfxstream/guest/vulkan/gfxstream_vk_device.cpp @@ -548,6 +548,37 @@ VkResult gfxstream_vk_CreateDevice(VkPhysicalDevice physicalDevice, vk_free(pMesaAllocator, gfxstream_device); } + // alloc/init all vk_queue objects + if (VK_SUCCESS == result) { + gfxstream_device->queue_family_count = pCreateInfo->queueCreateInfoCount; + gfxstream_device->queue_families = (struct gfxstream_vk_device::queue_family_info*)vk_zalloc( + pMesaAllocator, gfxstream_device->queue_family_count * sizeof(*gfxstream_device->queue_families), GFXSTREAM_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + result = gfxstream_device->queue_families ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY; + if (VK_SUCCESS == result) { + for (uint32_t qfi = 0; qfi < gfxstream_device->queue_family_count; qfi++) { + gfxstream_device->queue_families[qfi].queue_count = pCreateInfo->pQueueCreateInfos[qfi].queueCount; + gfxstream_device->queue_families[qfi].queues = (struct gfxstream_vk_queue*)vk_zalloc( + pMesaAllocator, gfxstream_device->queue_families[qfi].queue_count * sizeof(struct gfxstream_vk_queue), GFXSTREAM_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + result =gfxstream_device->queue_families[qfi].queues ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY; + if (VK_SUCCESS != result) { + break; + } + } + if (VK_SUCCESS == result) { + for (uint32_t qfi = 0; qfi < gfxstream_device->queue_family_count; qfi++) { + for (uint32_t queue_index = 0; queue_index < gfxstream_device->queue_families[qfi].queue_count; queue_index++) { + struct gfxstream_vk_queue *gfxstream_queue = &gfxstream_device->queue_families[qfi].queues[queue_index]; + result = vk_queue_init(&gfxstream_queue->vk, &gfxstream_device->vk, &pCreateInfo->pQueueCreateInfos[qfi], queue_index); + if (VK_SUCCESS != result) { + break; + } + gfxstream_queue->device = gfxstream_device; + } + } + } + } + } + return result; } @@ -559,77 +590,37 @@ void gfxstream_vk_DestroyDevice(VkDevice device, const VkAllocationCallbacks* pA auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder(); vkEnc->vkDestroyDevice(gfxstream_device->internal_object, pAllocator, true /* do lock */); - /* Must destroy device queues manually */ + /* Must finish the queues, and destroy the queue-list objects manually */ vk_foreach_queue_safe(queue, &gfxstream_device->vk) { vk_queue_finish(queue); vk_free(&gfxstream_device->vk.alloc, queue); } + /* Now destroy the queue allocations from the device object */ + for (uint32_t qfi = 0; qfi < gfxstream_device->queue_family_count; qfi++) { + vk_free(&gfxstream_device->vk.alloc, gfxstream_device->queue_families[qfi].queues); + gfxstream_device->queue_families[qfi].queues = NULL; + gfxstream_device->queue_families[qfi].queue_count = 0; + } + vk_free(&gfxstream_device->vk.alloc, gfxstream_device->queue_families); + gfxstream_device->queue_families = NULL; + gfxstream_device->queue_family_count = 0; + vk_device_finish(&gfxstream_device->vk); vk_free(&gfxstream_device->vk.alloc, gfxstream_device); } -void gfxstream_vk_GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, - VkQueue* pQueue) { - MESA_TRACE_SCOPE("vkGetDeviceQueue"); - VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device); - struct gfxstream_vk_queue* gfxstream_queue = (struct gfxstream_vk_queue*)vk_zalloc( - &gfxstream_device->vk.alloc, sizeof(struct gfxstream_vk_queue), GFXSTREAM_DEFAULT_ALIGN, - VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); - VkResult result = gfxstream_queue ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY; - if (VK_SUCCESS == result) { - VkDeviceQueueCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .pNext = NULL, - .flags = 0, - .queueFamilyIndex = queueFamilyIndex, - .queueCount = 1, - .pQueuePriorities = NULL, - }; - result = - vk_queue_init(&gfxstream_queue->vk, &gfxstream_device->vk, &createInfo, queueIndex); - } - if (VK_SUCCESS == result) { - auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder(); - vkEnc->vkGetDeviceQueue(gfxstream_device->internal_object, queueFamilyIndex, queueIndex, - &gfxstream_queue->internal_object, true /* do lock */); - - gfxstream_queue->device = gfxstream_device; - *pQueue = gfxstream_vk_queue_to_handle(gfxstream_queue); - } else { - *pQueue = VK_NULL_HANDLE; - } -} - void gfxstream_vk_GetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2* pQueueInfo, VkQueue* pQueue) { MESA_TRACE_SCOPE("vkGetDeviceQueue2"); VK_FROM_HANDLE(gfxstream_vk_device, gfxstream_device, device); - struct gfxstream_vk_queue* gfxstream_queue = (struct gfxstream_vk_queue*)vk_zalloc( - &gfxstream_device->vk.alloc, sizeof(struct gfxstream_vk_queue), GFXSTREAM_DEFAULT_ALIGN, - VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); - VkResult result = gfxstream_queue ? VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY; - if (VK_SUCCESS == result) { - VkDeviceQueueCreateInfo createInfo = { - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .pNext = NULL, - .flags = pQueueInfo->flags, - .queueFamilyIndex = pQueueInfo->queueFamilyIndex, - .queueCount = 1, - .pQueuePriorities = NULL, - }; - result = vk_queue_init(&gfxstream_queue->vk, &gfxstream_device->vk, &createInfo, - pQueueInfo->queueIndex); - } - if (VK_SUCCESS == result) { - auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder(); - vkEnc->vkGetDeviceQueue2(gfxstream_device->internal_object, pQueueInfo, - &gfxstream_queue->internal_object, true /* do lock */); - - gfxstream_queue->device = gfxstream_device; - *pQueue = gfxstream_vk_queue_to_handle(gfxstream_queue); - } else { - *pQueue = VK_NULL_HANDLE; - } + assert(pQueueInfo->queueFamilyIndex < gfxstream_device->queue_family_count); + assert(pQueueInfo->queueIndex < gfxstream_device->queue_families[pQueueInfo->queueFamilyIndex].queue_count); + /* Queue objects must have been allocated during CreateDevice() */ + struct gfxstream_vk_queue *gfxstream_queue = &gfxstream_device->queue_families[pQueueInfo->queueFamilyIndex].queues[pQueueInfo->queueIndex]; + auto vkEnc = gfxstream::vk::ResourceTracker::getThreadLocalEncoder(); + vkEnc->vkGetDeviceQueue2(gfxstream_device->internal_object, pQueueInfo, + &gfxstream_queue->internal_object, true /* do lock */); + *pQueue = gfxstream_vk_queue_to_handle(gfxstream_queue); } /* The loader wants us to expose a second GetInstanceProcAddr function diff --git a/src/gfxstream/guest/vulkan_enc/gfxstream_vk_private.h b/src/gfxstream/guest/vulkan_enc/gfxstream_vk_private.h index ec9d886334f..e75934dd95e 100644 --- a/src/gfxstream/guest/vulkan_enc/gfxstream_vk_private.h +++ b/src/gfxstream/guest/vulkan_enc/gfxstream_vk_private.h @@ -81,6 +81,13 @@ struct gfxstream_vk_device { struct vk_device_dispatch_table cmd_dispatch; struct gfxstream_vk_physical_device* physical_device; + + uint32_t queue_family_count; + struct queue_family_info { + uint32_t queue_count; + struct gfxstream_vk_queue* queues; + } *queue_families; + VkDevice internal_object; };