venus: bind VkQueue to available ring_idx at creation
Signed-off-by: Ryan Neph <ryanneph@google.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19691>
This commit is contained in:
@@ -41,16 +41,36 @@ vn_queue_init(struct vn_device *dev,
|
||||
{
|
||||
vn_object_base_init(&queue->base, VK_OBJECT_TYPE_QUEUE, &dev->base);
|
||||
|
||||
VkDeviceQueueTimelineInfoMESA timeline_info;
|
||||
const struct vn_renderer_info *renderer_info =
|
||||
&dev->instance->renderer->info;
|
||||
if (renderer_info->supports_multiple_timelines) {
|
||||
int ring_idx = vn_instance_acquire_ring_idx(dev->instance);
|
||||
if (ring_idx < 0) {
|
||||
vn_log(dev->instance,
|
||||
"failed binding VkQueue to renderer sync queue");
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
queue->ring_idx = (uint32_t)ring_idx;
|
||||
|
||||
timeline_info = (VkDeviceQueueTimelineInfoMESA){
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_TIMELINE_INFO_MESA,
|
||||
.ringIdx = queue->ring_idx,
|
||||
};
|
||||
}
|
||||
|
||||
const VkDeviceQueueInfo2 device_queue_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
|
||||
.pNext =
|
||||
renderer_info->supports_multiple_timelines ? &timeline_info : NULL,
|
||||
.flags = queue_info->flags,
|
||||
.queueFamilyIndex = queue_info->queueFamilyIndex,
|
||||
.queueIndex = queue_index,
|
||||
};
|
||||
|
||||
VkQueue queue_handle = vn_queue_to_handle(queue);
|
||||
vn_async_vkGetDeviceQueue2(
|
||||
dev->instance, vn_device_to_handle(dev),
|
||||
&(VkDeviceQueueInfo2){
|
||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
|
||||
.flags = queue_info->flags,
|
||||
.queueFamilyIndex = queue_info->queueFamilyIndex,
|
||||
.queueIndex = queue_index,
|
||||
},
|
||||
&queue_handle);
|
||||
vn_async_vkGetDeviceQueue2(dev->instance, vn_device_to_handle(dev),
|
||||
&device_queue_info, &queue_handle);
|
||||
|
||||
queue->device = dev;
|
||||
queue->family = queue_info->queueFamilyIndex;
|
||||
@@ -493,6 +513,16 @@ vn_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator)
|
||||
*/
|
||||
vn_async_vkDestroyDevice(dev->instance, device, NULL);
|
||||
|
||||
/* We must emit vn_call_vkDestroyDevice before releasing bound ring_idx.
|
||||
* Otherwise, another thread might reuse their ring_idx while they
|
||||
* are still bound to the queues in the renderer.
|
||||
*/
|
||||
if (dev->instance->renderer->info.supports_multiple_timelines) {
|
||||
for (uint32_t i = 0; i < dev->queue_count; i++) {
|
||||
vn_instance_release_ring_idx(dev->instance, dev->queues[i].ring_idx);
|
||||
}
|
||||
}
|
||||
|
||||
vk_free(alloc, dev->queues);
|
||||
|
||||
vn_device_base_fini(&dev->base);
|
||||
|
||||
@@ -720,8 +720,12 @@ vn_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
|
||||
return vn_error(NULL, result);
|
||||
}
|
||||
|
||||
/* ring_idx = 0 reserved for CPU timeline */
|
||||
instance->ring_idx_used_mask = 0x1;
|
||||
|
||||
mtx_init(&instance->physical_device.mutex, mtx_plain);
|
||||
mtx_init(&instance->cs_shmem.mutex, mtx_plain);
|
||||
mtx_init(&instance->ring_idx_mutex, mtx_plain);
|
||||
|
||||
if (!vn_icd_supports_api_version(
|
||||
instance->base.base.app_info.api_version)) {
|
||||
@@ -823,6 +827,7 @@ fail:
|
||||
vn_renderer_destroy(instance->renderer, alloc);
|
||||
|
||||
mtx_destroy(&instance->physical_device.mutex);
|
||||
mtx_destroy(&instance->ring_idx_mutex);
|
||||
mtx_destroy(&instance->cs_shmem.mutex);
|
||||
|
||||
vn_instance_base_fini(&instance->base);
|
||||
@@ -850,6 +855,7 @@ vn_DestroyInstance(VkInstance _instance,
|
||||
vk_free(alloc, instance->physical_device.groups);
|
||||
}
|
||||
mtx_destroy(&instance->physical_device.mutex);
|
||||
mtx_destroy(&instance->ring_idx_mutex);
|
||||
|
||||
vn_call_vkDestroyInstance(instance, _instance, NULL);
|
||||
|
||||
|
||||
@@ -41,6 +41,9 @@ struct vn_instance {
|
||||
|
||||
struct vn_renderer_shmem_pool reply_shmem_pool;
|
||||
|
||||
mtx_t ring_idx_mutex;
|
||||
uint64_t ring_idx_used_mask;
|
||||
|
||||
/* XXX staged features to be merged to core venus protocol */
|
||||
VkVenusExperimentalFeatures100000MESA experimental;
|
||||
|
||||
@@ -172,4 +175,32 @@ vn_instance_cs_shmem_alloc(struct vn_instance *instance,
|
||||
return shmem;
|
||||
}
|
||||
|
||||
static inline int
|
||||
vn_instance_acquire_ring_idx(struct vn_instance *instance)
|
||||
{
|
||||
mtx_lock(&instance->ring_idx_mutex);
|
||||
int ring_idx = ffsll(~instance->ring_idx_used_mask) - 1;
|
||||
if (ring_idx >= instance->renderer->info.max_sync_queue_count)
|
||||
ring_idx = -1;
|
||||
if (ring_idx > 0)
|
||||
instance->ring_idx_used_mask |= (1ULL << (uint32_t)ring_idx);
|
||||
mtx_unlock(&instance->ring_idx_mutex);
|
||||
|
||||
assert(ring_idx); /* never acquire the dedicated CPU ring */
|
||||
|
||||
/* returns -1 when no vacant rings */
|
||||
return ring_idx;
|
||||
}
|
||||
|
||||
static inline void
|
||||
vn_instance_release_ring_idx(struct vn_instance *instance, uint32_t ring_idx)
|
||||
{
|
||||
assert(ring_idx > 0);
|
||||
|
||||
mtx_lock(&instance->ring_idx_mutex);
|
||||
assert(instance->ring_idx_used_mask & (1ULL << ring_idx));
|
||||
instance->ring_idx_used_mask &= ~(1ULL << ring_idx);
|
||||
mtx_unlock(&instance->ring_idx_mutex);
|
||||
}
|
||||
|
||||
#endif /* VN_INSTANCE_H */
|
||||
|
||||
@@ -23,6 +23,9 @@ struct vn_queue {
|
||||
uint32_t index;
|
||||
uint32_t flags;
|
||||
|
||||
/* only used if renderer supports multiple timelines */
|
||||
uint32_t ring_idx;
|
||||
|
||||
/* wait fence used for vn_QueueWaitIdle */
|
||||
VkFence wait_fence;
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ struct vn_renderer_info {
|
||||
/* combined mask for vk_extension_mask1, 2,..., N */
|
||||
uint32_t vk_extension_mask[32];
|
||||
uint32_t allow_vk_wait_syncs;
|
||||
uint32_t supports_multiple_timelines;
|
||||
};
|
||||
|
||||
struct vn_renderer_submit_batch {
|
||||
|
||||
Reference in New Issue
Block a user