v3dv: fix branching to large secondaries with more than one BCL buffer.

Fixes:
dEQP-VK.api.command_buffers.record_many_draws_secondary_*

Tested-by: Juan A. Suarez <jasuarez@igalia.com>
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9333>
This commit is contained in:
Iago Toral Quiroga 2021-03-01 10:42:42 +01:00
parent 0360ecac73
commit 8a60bde0cf
2 changed files with 31 additions and 9 deletions

View file

@ -101,8 +101,26 @@ v3dv_cl_ensure_space(struct v3dv_cl *cl, uint32_t space, uint32_t alignment)
void
v3dv_cl_ensure_space_with_branch(struct v3dv_cl *cl, uint32_t space)
{
if (v3dv_cl_offset(cl) + space + cl_packet_length(BRANCH) <= cl->size)
/* We do not want to emit branches from secondary command lists, instead,
* we will branch to them when we execute them in a primary using
* 'branch to sub list' commands, expecting each linked secondary to
* end with a 'return from sub list' command.
*/
bool needs_return_from_sub_list = false;
if (cl->job->type == V3DV_JOB_TYPE_GPU_CL_SECONDARY) {
if (cl->size > 0) {
needs_return_from_sub_list = true;
space += cl_packet_length(RETURN_FROM_SUB_LIST);
}
} else {
space += cl_packet_length(BRANCH);
}
if (v3dv_cl_offset(cl) + space <= cl->size)
return;
cl_alloc_bo(cl, space, true);
if (needs_return_from_sub_list)
cl_emit(cl, RETURN_FROM_SUB_LIST, ret);
cl_alloc_bo(cl, space, !needs_return_from_sub_list);
}

View file

@ -2768,13 +2768,17 @@ cmd_buffer_execute_inside_pass(struct v3dv_cmd_buffer *primary,
v3dv_job_add_bo(primary_job, bo);
}
/* Emit the branch instruction */
v3dv_cl_ensure_space_with_branch(&primary_job->bcl,
cl_packet_length(BRANCH_TO_SUB_LIST));
v3dv_return_if_oom(primary, NULL);
cl_emit(&primary_job->bcl, BRANCH_TO_SUB_LIST, branch) {
branch.address = v3dv_cl_address(secondary_job->bcl.bo, 0);
/* Emit required branch instructions. We expect each of these
* to end with a corresponding 'return from sub list' item.
*/
list_for_each_entry(struct v3dv_bo, bcl_bo,
&secondary_job->bcl.bo_list, list_link) {
v3dv_cl_ensure_space_with_branch(&primary_job->bcl,
cl_packet_length(BRANCH_TO_SUB_LIST));
v3dv_return_if_oom(primary, NULL);
cl_emit(&primary_job->bcl, BRANCH_TO_SUB_LIST, branch) {
branch.address = v3dv_cl_address(bcl_bo, 0);
}
}
primary_job->tmu_dirty_rcl |= secondary_job->tmu_dirty_rcl;