venus: append fence feedback batch

Instead of calling an additional QueueSubmit for fence feedback, append
a SubmitInfo batch for fence feedback. This does require copying the
submitted batches to a larger buffer with an additional slot for the
fence feedback batch.

Signed-off-by: Juston Li <justonli@google.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20088>
This commit is contained in:
Juston Li
2022-12-20 16:53:47 -08:00
committed by Marge Bot
parent 2889a0478b
commit 6863092d95

View File

@@ -53,12 +53,23 @@ struct vn_queue_submission {
union {
const void *batches;
const VkSubmitInfo *submit_batches;
const VkSubmitInfo2 *submit_batches2;
};
VkFence fence;
bool synchronous;
bool has_feedback_fence;
const struct vn_device_memory *wsi_mem;
struct {
union {
void *batches;
VkSubmitInfo *submit_batches;
VkSubmitInfo2 *submit_batches2;
};
VkCommandBufferSubmitInfo fence_feedback_cmd_info;
} temp;
};
static VkResult
@@ -162,6 +173,109 @@ vn_queue_submission_prepare(struct vn_queue_submission *submit)
return VK_SUCCESS;
}
static const VkCommandBuffer *
vn_get_fence_feedback_cmd(struct vn_queue *queue, struct vn_fence *fence)
{
assert(fence->feedback.slot);
for (uint32_t i = 0; i < queue->device->queue_family_count; i++) {
if (queue->device->queue_families[i] == queue->family)
return &fence->feedback.commands[i];
}
unreachable("bad feedback fence");
}
static VkResult
vn_queue_submission_add_fence_feedback(struct vn_queue_submission *submit)
{
struct vn_fence *fence = vn_fence_from_handle(submit->fence);
struct vn_queue *queue = vn_queue_from_handle(submit->queue);
const VkAllocationCallbacks *alloc = &queue->device->base.base.alloc;
size_t batch_size = 0;
assert(fence->feedback.slot);
switch (submit->batch_type) {
case VK_STRUCTURE_TYPE_SUBMIT_INFO:
batch_size = sizeof(VkSubmitInfo);
break;
case VK_STRUCTURE_TYPE_SUBMIT_INFO_2:
batch_size = sizeof(VkSubmitInfo2);
break;
default:
unreachable("unexpected batch type");
break;
}
size_t submit_batches_size = batch_size * submit->batch_count;
/* add space for an additional batch for fence feedback */
size_t new_submit_batches_size = submit_batches_size + batch_size;
submit->temp.batches =
vk_zalloc(alloc, new_submit_batches_size, VN_DEFAULT_ALIGN,
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (!submit->temp.batches)
return VK_ERROR_OUT_OF_HOST_MEMORY;
/* copy only needed for non-empty submissions */
if (submit_batches_size)
memcpy(submit->temp.batches, submit->batches, submit_batches_size);
const VkCommandBuffer *cmd_handle =
vn_get_fence_feedback_cmd(queue, fence);
switch (submit->batch_type) {
case VK_STRUCTURE_TYPE_SUBMIT_INFO: {
VkSubmitInfo *submit_info =
&submit->temp.submit_batches[submit->batch_count];
submit_info->sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info->commandBufferCount = 1;
submit_info->pCommandBuffers = cmd_handle;
submit->submit_batches = submit->temp.submit_batches;
break;
}
case VK_STRUCTURE_TYPE_SUBMIT_INFO_2: {
VkSubmitInfo2 *submit_info2 =
&submit->temp.submit_batches2[submit->batch_count];
submit_info2->sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2;
submit_info2->commandBufferInfoCount = 1;
submit->temp.fence_feedback_cmd_info.sType =
VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO;
submit->temp.fence_feedback_cmd_info.pNext = NULL;
submit->temp.fence_feedback_cmd_info.commandBuffer = *cmd_handle;
submit_info2->pCommandBufferInfos =
&submit->temp.fence_feedback_cmd_info;
submit->submit_batches2 = submit->temp.submit_batches2;
break;
}
default:
unreachable("unexpected batch type");
break;
}
submit->batch_count++;
return VK_SUCCESS;
}
static void
vn_queue_submission_cleanup(struct vn_queue_submission *submit)
{
struct vn_queue *queue = vn_queue_from_handle(submit->queue);
const VkAllocationCallbacks *alloc = &queue->device->base.base.alloc;
if (submit->has_feedback_fence)
vk_free(alloc, submit->temp.batches);
}
static VkResult
vn_queue_submission_prepare_submit(struct vn_queue_submission *submit,
VkQueue queue,
@@ -179,20 +293,13 @@ vn_queue_submission_prepare_submit(struct vn_queue_submission *submit,
if (result != VK_SUCCESS)
return result;
return result;
}
static const VkCommandBuffer
vn_get_fence_feedback_cmd(struct vn_queue *queue, struct vn_fence *fence)
{
assert(fence->feedback.slot);
for (uint32_t i = 0; i < queue->device->queue_family_count; i++) {
if (queue->device->queue_families[i] == queue->family)
return fence->feedback.commands[i];
if (submit->has_feedback_fence) {
result = vn_queue_submission_add_fence_feedback(submit);
if (result != VK_SUCCESS)
return result;
}
unreachable("bad feedback fence");
return VK_SUCCESS;
}
static VkResult
@@ -249,15 +356,11 @@ vn_QueueSubmit(VkQueue queue_h,
if (result != VK_SUCCESS)
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
/* if the original submission involves a feedback fence:
* - defer the feedback fence to another submit to avoid deep copy
* - defer the potential sync_submit to the feedback fence submission
*/
result = vn_queue_submit(
dev->instance, submit.queue, submit.batch_count, submit.submit_batches,
submit.has_feedback_fence ? VK_NULL_HANDLE : submit.fence,
!submit.has_feedback_fence && submit.synchronous);
result = vn_queue_submit(dev->instance, submit.queue, submit.batch_count,
submit.submit_batches, submit.fence,
submit.synchronous);
if (result != VK_SUCCESS) {
vn_queue_submission_cleanup(&submit);
return vn_error(dev->instance, result);
}
@@ -283,27 +386,6 @@ vn_QueueSubmit(VkQueue queue_h,
}
}
/* TODO intercept original submit batches to append the fence feedback cmd
* with a per-queue cached submission builder to avoid transient allocs.
*
* vn_queue_submission bits must be fixed for VkTimelineSemaphoreSubmitInfo
* before adding timeline semaphore feedback.
*/
if (submit.has_feedback_fence) {
const VkCommandBuffer cmd_handle =
vn_get_fence_feedback_cmd(queue, fence);
const VkSubmitInfo info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.commandBufferCount = 1,
.pCommandBuffers = &cmd_handle,
};
result = vn_queue_submit(dev->instance, submit.queue, 1, &info,
submit.fence, submit.synchronous);
if (result != VK_SUCCESS) {
return vn_error(dev->instance, result);
}
}
if (submit.wsi_mem) {
/* XXX this is always false and kills the performance */
if (dev->instance->renderer->info.has_implicit_fencing) {
@@ -322,6 +404,8 @@ vn_QueueSubmit(VkQueue queue_h,
}
}
vn_queue_submission_cleanup(&submit);
return VK_SUCCESS;
}
@@ -414,6 +498,9 @@ vn_queue_submit2_feedback_fence(struct vn_queue *queue,
assert(fence->feedback.slot);
const VkCommandBuffer *cmd_handle =
vn_get_fence_feedback_cmd(queue, fence);
const VkSubmitInfo2 submit = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
.commandBufferInfoCount = 1,
@@ -421,7 +508,7 @@ vn_queue_submit2_feedback_fence(struct vn_queue *queue,
(VkCommandBufferSubmitInfo[]){
{
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
.commandBuffer = vn_get_fence_feedback_cmd(queue, fence),
.commandBuffer = *cmd_handle,
.deviceMask = 0,
},
},