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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36227>
This commit is contained in:
Aaron Ruby 2025-07-18 13:25:33 -04:00 committed by Marge Bot
parent 4f227dc00c
commit ae904e11a8
3 changed files with 64 additions and 62 deletions

View file

@ -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()

View file

@ -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

View file

@ -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;
};