vulkan/queue: Merge submits when possible

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25576>
This commit is contained in:
Faith Ekstrand
2023-10-05 19:04:10 -05:00
committed by Marge Bot
parent c3bf1a67a1
commit bba6bf33a8

View File

@@ -463,6 +463,135 @@ vk_queue_submit_add_image_bind(
submit->image_binds[submit->image_bind_count++] = info_tmp;
}
/* Attempts to merge two submits into one. If the merge succeeds, the merged
* submit is return and the two submits passed in are destroyed.
*/
static struct vk_queue_submit *
vk_queue_submits_merge(struct vk_queue *queue,
struct vk_queue_submit *first,
struct vk_queue_submit *second)
{
/* Don't merge if there are signals in between: see 'Signal operation order' */
if (first->signal_count > 0 &&
(second->command_buffer_count ||
second->buffer_bind_count ||
second->image_opaque_bind_count ||
second->image_bind_count ||
second->wait_count))
return NULL;
if (vk_queue_submit_has_bind(first) != vk_queue_submit_has_bind(second))
return NULL;
if (first->_mem_signal_temp)
return NULL;
if (first->perf_pass_index != second->perf_pass_index)
return NULL;
/* noop submits can always do a no-op merge */
if (!second->command_buffer_count &&
!second->buffer_bind_count &&
!second->image_opaque_bind_count &&
!second->image_bind_count &&
!second->wait_count &&
!second->signal_count) {
vk_queue_submit_destroy(queue, second);
return first;
}
if (!first->command_buffer_count &&
!first->buffer_bind_count &&
!first->image_opaque_bind_count &&
!first->image_bind_count &&
!first->wait_count &&
!first->signal_count) {
vk_queue_submit_destroy(queue, first);
return second;
}
struct vk_queue_submit *merged = vk_queue_submit_alloc(queue,
first->wait_count + second->wait_count,
first->command_buffer_count + second->command_buffer_count,
first->buffer_bind_count + second->buffer_bind_count,
first->image_opaque_bind_count + second->image_opaque_bind_count,
first->image_bind_count + second->image_bind_count,
first->_bind_entry_count + second->_bind_entry_count,
first->_image_bind_entry_count + second->_image_bind_entry_count,
first->signal_count + second->signal_count);
if (merged == NULL)
return NULL;
merged->wait_count = first->wait_count + second->wait_count;
typed_memcpy(merged->waits, first->waits, first->wait_count);
typed_memcpy(&merged->waits[first->wait_count], second->waits, second->wait_count);
merged->command_buffer_count = first->command_buffer_count +
second->command_buffer_count;
typed_memcpy(merged->command_buffers,
first->command_buffers, first->command_buffer_count);
typed_memcpy(&merged->command_buffers[first->command_buffer_count],
second->command_buffers, second->command_buffer_count);
merged->signal_count = first->signal_count + second->signal_count;
typed_memcpy(merged->signals, first->signals, first->signal_count);
typed_memcpy(&merged->signals[first->signal_count], second->signals, second->signal_count);
for (uint32_t i = 0; i < first->buffer_bind_count; i++)
vk_queue_submit_add_buffer_bind(queue, first, &first->buffer_binds[i]);
for (uint32_t i = 0; i < second->buffer_bind_count; i++)
vk_queue_submit_add_buffer_bind(queue, second, &first->buffer_binds[i]);
for (uint32_t i = 0; i < first->image_opaque_bind_count; i++) {
vk_queue_submit_add_image_opaque_bind(queue, first,
&first->image_opaque_binds[i]);
}
for (uint32_t i = 0; i < second->image_opaque_bind_count; i++) {
vk_queue_submit_add_image_opaque_bind(queue, second,
&first->image_opaque_binds[i]);
}
for (uint32_t i = 0; i < first->image_bind_count; i++)
vk_queue_submit_add_image_bind(queue, first, &first->image_binds[i]);
for (uint32_t i = 0; i < second->image_bind_count; i++)
vk_queue_submit_add_image_bind(queue, second, &first->image_binds[i]);
merged->perf_pass_index = first->perf_pass_index;
assert(second->perf_pass_index == merged->perf_pass_index);
assert(merged->_bind_entry_count ==
first->_bind_entry_count + second->_bind_entry_count);
assert(merged->_image_bind_entry_count ==
first->_image_bind_entry_count + second->_image_bind_entry_count);
merged->_has_binary_permanent_semaphore_wait =
first->_has_binary_permanent_semaphore_wait;
typed_memcpy(merged->_wait_temps, first->_wait_temps, first->wait_count);
typed_memcpy(&merged->_wait_temps[first->wait_count], second->_wait_temps, second->wait_count);
assert(first->_mem_signal_temp == NULL);
merged->_mem_signal_temp = second->_mem_signal_temp;
if (queue->base.device->timeline_mode == VK_DEVICE_TIMELINE_MODE_EMULATED) {
typed_memcpy(merged->_wait_points,
first->_wait_points, first->wait_count);
typed_memcpy(&merged->_wait_points[first->wait_count],
second->_wait_points, second->wait_count);
typed_memcpy(merged->_signal_points,
first->_signal_points, first->signal_count);
typed_memcpy(&merged->_signal_points[first->signal_count],
second->_signal_points, second->signal_count);
} else {
assert(first->_wait_points == NULL && second->_wait_points == NULL);
assert(first->_signal_points == NULL && second->_signal_points == NULL);
}
vk_queue_submit_free(queue, first);
vk_queue_submit_free(queue, second);
return merged;
}
static void
vk_queue_push_submit(struct vk_queue *queue,
struct vk_queue_submit *submit)
@@ -1084,6 +1213,35 @@ fail:
return result;
}
static VkResult
vk_queue_merge_submit(struct vk_queue *queue,
struct vk_queue_submit **last_submit,
struct vk_queue_submit *submit)
{
if (*last_submit == NULL) {
*last_submit = submit;
return VK_SUCCESS;
}
struct vk_queue_submit *merged =
vk_queue_submits_merge(queue, *last_submit, submit);
if (merged != NULL) {
*last_submit = merged;
return VK_SUCCESS;
}
VkResult result = vk_queue_submit(queue, *last_submit);
*last_submit = NULL;
if (likely(result == VK_SUCCESS)) {
*last_submit = submit;
} else {
vk_queue_submit_destroy(queue, submit);
}
return result;
}
VkResult
vk_queue_wait_before_present(struct vk_queue *queue,
const VkPresentInfoKHR *pPresentInfo)
@@ -1224,6 +1382,7 @@ vk_common_QueueSubmit2(VkQueue _queue,
{
VK_FROM_HANDLE(vk_queue, queue, _queue);
VK_FROM_HANDLE(vk_fence, fence, _fence);
VkResult result;
if (vk_device_is_lost(queue->base.device))
return VK_ERROR_DEVICE_LOST;
@@ -1236,6 +1395,7 @@ vk_common_QueueSubmit2(VkQueue _queue,
}
}
struct vk_queue_submit *last_submit = NULL;
for (uint32_t i = 0; i < submitCount; i++) {
struct vulkan_submit_info info = {
.pNext = pSubmits[i].pNext,
@@ -1248,11 +1408,17 @@ vk_common_QueueSubmit2(VkQueue _queue,
.fence = i == submitCount - 1 ? fence : NULL
};
struct vk_queue_submit *submit;
VkResult result = vk_queue_submit_create(queue, &info, &submit);
result = vk_queue_submit_create(queue, &info, &submit);
if (unlikely(result != VK_SUCCESS))
return result;
result = vk_queue_submit(queue, submit);
result = vk_queue_merge_submit(queue, &last_submit, submit);
if (unlikely(result != VK_SUCCESS))
return result;
}
if (last_submit != NULL) {
result = vk_queue_submit(queue, last_submit);
if (unlikely(result != VK_SUCCESS))
return result;
}
@@ -1268,6 +1434,7 @@ vk_common_QueueBindSparse(VkQueue _queue,
{
VK_FROM_HANDLE(vk_queue, queue, _queue);
VK_FROM_HANDLE(vk_fence, fence, _fence);
VkResult result;
if (vk_device_is_lost(queue->base.device))
return VK_ERROR_DEVICE_LOST;
@@ -1280,6 +1447,7 @@ vk_common_QueueBindSparse(VkQueue _queue,
}
}
struct vk_queue_submit *last_submit = NULL;
for (uint32_t i = 0; i < bindInfoCount; i++) {
const VkTimelineSemaphoreSubmitInfo *timeline_info =
vk_find_struct_const(pBindInfo[i].pNext, TIMELINE_SEMAPHORE_SUBMIT_INFO);
@@ -1355,9 +1523,9 @@ vk_common_QueueBindSparse(VkQueue _queue,
.fence = i == bindInfoCount - 1 ? fence : NULL
};
struct vk_queue_submit *submit;
VkResult result = vk_queue_submit_create(queue, &info, &submit);
result = vk_queue_submit_create(queue, &info, &submit);
if (likely(result == VK_SUCCESS))
result = vk_queue_submit(queue, submit);
result = vk_queue_merge_submit(queue, &last_submit, submit);
STACK_ARRAY_FINISH(wait_semaphore_infos);
STACK_ARRAY_FINISH(signal_semaphore_infos);
@@ -1366,6 +1534,12 @@ vk_common_QueueBindSparse(VkQueue _queue,
return result;
}
if (last_submit != NULL) {
result = vk_queue_submit(queue, last_submit);
if (unlikely(result != VK_SUCCESS))
return result;
}
return VK_SUCCESS;
}