summaryrefslogtreecommitdiff
path: root/src/broadcom
diff options
context:
space:
mode:
Diffstat (limited to 'src/broadcom')
-rw-r--r--src/broadcom/vulkan/v3dv_cmd_buffer.c95
-rw-r--r--src/broadcom/vulkan/v3dv_private.h6
2 files changed, 70 insertions, 31 deletions
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index 3504813f8d2..8c487269686 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -122,6 +122,7 @@ cmd_buffer_init(struct v3dv_cmd_buffer *cmd_buffer,
list_inithead(&cmd_buffer->private_objs);
list_inithead(&cmd_buffer->jobs);
+ list_inithead(&cmd_buffer->pre_jobs);
list_inithead(&cmd_buffer->list_link);
assert(pool);
@@ -249,6 +250,13 @@ cmd_buffer_free_resources(struct v3dv_cmd_buffer *cmd_buffer)
if (cmd_buffer->state.job)
v3dv_job_destroy(cmd_buffer->state.job);
+
+ list_for_each_entry_safe(struct v3dv_job, job,
+ &cmd_buffer->pre_jobs, list_link) {
+ assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY);
+ v3dv_job_destroy(job);
+ }
+
if (cmd_buffer->state.attachments) {
assert(cmd_buffer->state.attachment_count > 0);
vk_free(&cmd_buffer->pool->alloc, cmd_buffer->state.attachments);
@@ -2131,6 +2139,27 @@ cmd_buffer_copy_secondary_end_query_state(struct v3dv_cmd_buffer *primary,
}
}
+/* Clones a job for inclusion in the given command buffer. Note that this
+ * doesn't make a deep copy so the cloned job it doesn't own any resources.
+ * Useful when we need to have a job in more than one list, which happens
+ * for jobs recorded in secondary command buffers when we want to execute
+ * them in primaries.
+ */
+static struct v3dv_job *
+job_clone(struct v3dv_job *job, struct v3dv_cmd_buffer *cmd_buffer)
+{
+ struct v3dv_job *clone_job = vk_alloc(&job->device->alloc,
+ sizeof(struct v3dv_job), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+ if (!clone_job)
+ return NULL;
+
+ *clone_job = *job;
+ clone_job->is_clone = true;
+ clone_job->cmd_buffer = cmd_buffer;
+ return clone_job;
+}
+
static void
cmd_buffer_execute_inside_pass(struct v3dv_cmd_buffer *primary,
uint32_t cmd_buffer_count,
@@ -2148,6 +2177,18 @@ cmd_buffer_execute_inside_pass(struct v3dv_cmd_buffer *primary,
assert(secondary->usage_flags &
VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT);
+ /* Insert any jobs that should run before the secondary's commands */
+ list_for_each_entry(struct v3dv_job, pre_job,
+ &secondary->pre_jobs, list_link) {
+ struct v3dv_job *clone_job = job_clone(pre_job, primary);
+ if (!clone_job) {
+ v3dv_flag_oom(primary, NULL);
+ return;
+ }
+
+ list_addtail(&clone_job->list_link, &primary->jobs);
+ }
+
/* Secondaries that run inside a render pass only record commands inside
* a subpass, so they don't crate complete jobs (they don't have an RCL
* and their BCL doesn't include tiling setup). These are provided by
@@ -2189,27 +2230,6 @@ cmd_buffer_execute_inside_pass(struct v3dv_cmd_buffer *primary,
}
}
-/* Clones a job for inclusion in the given command buffer. Note that this
- * doesn't make a deep copy so the cloned job it doesn't own any resources.
- * Useful when we need to have a job in more than one list, which happens
- * for jobs recorded in secondary command buffers when we want to execute
- * them in primaries.
- */
-static struct v3dv_job *
-job_clone(struct v3dv_job *job, struct v3dv_cmd_buffer *cmd_buffer)
-{
- struct v3dv_job *clone_job = vk_alloc(&job->device->alloc,
- sizeof(struct v3dv_job), 8,
- VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
- if (!clone_job)
- return NULL;
-
- *clone_job = *job;
- clone_job->is_clone = true;
- clone_job->cmd_buffer = cmd_buffer;
- return clone_job;
-}
-
static void
cmd_buffer_execute_outside_pass(struct v3dv_cmd_buffer *primary,
uint32_t cmd_buffer_count,
@@ -4190,15 +4210,6 @@ v3dv_CmdWaitEvents(VkCommandBuffer commandBuffer,
{
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
- /* vkCmdWaitEvents can be recorded inside a render pass, so we might have
- * an active job.
- *
- * FIXME: Since we can't signal/reset events inside a render pass, we could,
- * in theory, move this wait to an earlier point, such as before the
- * current job if it is inside a render pass, to avoid the split.
- */
- v3dv_cmd_buffer_finish_job(cmd_buffer);
-
assert(eventCount > 0);
struct v3dv_job *job =
@@ -4221,5 +4232,27 @@ v3dv_CmdWaitEvents(VkCommandBuffer commandBuffer,
for (uint32_t i = 0; i < eventCount; i++)
job->cpu.event_wait.events[i] = v3dv_event_from_handle(pEvents[i]);
- list_addtail(&job->list_link, &cmd_buffer->jobs);
+ /* vkCmdWaitEvents can be recorded inside a render pass, so we might have
+ * an active job.
+ *
+ * If we are inside a render pass, because we vkCmd(Re)SetEvent can't happen
+ * inside a render pass, it is safe to move the wait job so it happens right
+ * before the current job we are currently recording for the subpass, if any
+ * (it would actually be safe to move it all the way back to right before
+ * the start of the render pass). If we are a secondary command buffer
+ * inside a render pass though, we only have access to the currently
+ * recording job, so we put it in a "execute first" list that we will execute
+ * right before the secondary in vkCmdExecuteCommands.
+ *
+ * If we are outside a render pass then we should not have any on-going job
+ * and we are free to just add the wait job without restrictions.
+ */
+ assert(cmd_buffer->state.pass || !cmd_buffer->state.job);
+ if (!cmd_buffer->state.pass ||
+ cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY) {
+ list_addtail(&job->list_link, &cmd_buffer->jobs);
+ } else {
+ assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY);
+ list_addtail(&job->list_link, &cmd_buffer->pre_jobs);
+ }
}
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index b8ed1ae74e4..3a21fd28a81 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -967,6 +967,12 @@ struct v3dv_cmd_buffer {
* buffer via vkCmdExecuteCommands.
*/
struct list_head jobs;
+
+ /* For secondary command buffers inside a render pass, a list of jobs
+ * that should be executed right before the secondary job is executed
+ * inside a primary.
+ */
+ struct list_head pre_jobs;
};
struct v3dv_job *v3dv_cmd_buffer_start_job(struct v3dv_cmd_buffer *cmd_buffer,