v3dv: improve handling of trailing barriers
When a command buffer ends with pending barriers we were emitting a serialized noop job, but this only works to ensure serialization of follow-up CL jobs, it won't do what we want if the barrier was intended for compute or TFU transfers for example. Fix this by merging the barrier state into follow-up jobs in the same queue submission. Reviewed-by: Juan A. Suarez <jasuarez@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33507>
This commit is contained in:
committed by
Marge Bot
parent
c6264c641d
commit
45f9208cca
@@ -1171,13 +1171,34 @@ handle_csd_job(struct v3dv_queue *queue,
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
queue_apply_barrier_state(struct v3dv_job *job,
|
||||
struct v3dv_barrier_state *barrier)
|
||||
{
|
||||
if (!v3dv_job_apply_barrier_state(job, barrier))
|
||||
return;
|
||||
|
||||
if (job->type != V3DV_JOB_TYPE_GPU_CL)
|
||||
return;
|
||||
|
||||
if (job->serialize &&
|
||||
(barrier->bcl_buffer_access || barrier->bcl_image_access)) {
|
||||
job->needs_bcl_sync = true;
|
||||
barrier->bcl_buffer_access = barrier->bcl_image_access = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static VkResult
|
||||
queue_handle_job(struct v3dv_queue *queue,
|
||||
struct v3dv_job *job,
|
||||
uint32_t counter_pass_idx,
|
||||
struct v3dv_barrier_state *barrier,
|
||||
struct v3dv_submit_sync_info *sync_info,
|
||||
bool signal_syncs)
|
||||
{
|
||||
if (barrier)
|
||||
queue_apply_barrier_state(job, barrier);
|
||||
|
||||
if (unlikely(V3D_DBG(SYNC))) {
|
||||
job->serialize = V3DV_BARRIER_ALL;
|
||||
job->needs_bcl_sync = job->type == V3DV_JOB_TYPE_GPU_CL;
|
||||
@@ -1240,7 +1261,7 @@ queue_submit_noop_job(struct v3dv_queue *queue,
|
||||
}
|
||||
|
||||
assert(queue->noop_job);
|
||||
return queue_handle_job(queue, queue->noop_job, counter_pass_idx,
|
||||
return queue_handle_job(queue, queue->noop_job, counter_pass_idx, NULL,
|
||||
sync_info, signal_syncs);
|
||||
}
|
||||
|
||||
@@ -1262,6 +1283,7 @@ v3dv_queue_driver_submit(struct vk_queue *vk_queue,
|
||||
for (int i = 0; i < V3DV_QUEUE_COUNT; i++)
|
||||
queue->last_job_syncs.first[i] = true;
|
||||
|
||||
struct v3dv_barrier_state pending_barrier = { 0 };
|
||||
struct v3dv_job *first_suspend_job = NULL;
|
||||
struct v3dv_job *current_suspend_job = NULL;
|
||||
for (uint32_t i = 0; i < submit->command_buffer_count; i++) {
|
||||
@@ -1299,7 +1321,7 @@ v3dv_queue_driver_submit(struct vk_queue *vk_queue,
|
||||
first_suspend_job : job;
|
||||
result =
|
||||
queue_handle_job(queue, submit_job, submit->perf_pass_index,
|
||||
&sync_info, false);
|
||||
&pending_barrier, &sync_info, false);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
@@ -1308,17 +1330,10 @@ v3dv_queue_driver_submit(struct vk_queue *vk_queue,
|
||||
}
|
||||
}
|
||||
|
||||
/* If the command buffer ends with a barrier we need to consume it now.
|
||||
*
|
||||
* FIXME: this will drain all hw queues. Instead, we could use the pending
|
||||
* barrier state to limit the queues we serialize against.
|
||||
/* If the command buffer ends with a barrier, save the pending barrier
|
||||
* state so we can apply it on the next command buffer.
|
||||
*/
|
||||
if (cmd_buffer->state.barrier.dst_mask) {
|
||||
result = queue_submit_noop_job(queue, submit->perf_pass_index,
|
||||
&sync_info, false);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
v3dv_merge_barrier_state(&pending_barrier, &cmd_buffer->state.barrier);
|
||||
}
|
||||
|
||||
assert(!first_suspend_job);
|
||||
|
||||
Reference in New Issue
Block a user