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:
@@ -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,
|
||||
},
|
||||
},
|
||||
|
Reference in New Issue
Block a user