Module: Mesa Branch: main Commit: 134c49072a1f1132adf6bff5d31cd373822f78f3 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=134c49072a1f1132adf6bff5d31cd373822f78f3
Author: Karmjit Mahil <[email protected]> Date: Tue Nov 1 09:33:35 2022 +0000 pvr: Process wait event sub command. Signed-off-by: Karmjit Mahil <[email protected]> Reviewed-by: Frank Binns <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20862> --- src/imagination/vulkan/pvr_queue.c | 128 ++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 2 deletions(-) diff --git a/src/imagination/vulkan/pvr_queue.c b/src/imagination/vulkan/pvr_queue.c index 9aeb327c0b1..e6d69d2cb55 100644 --- a/src/imagination/vulkan/pvr_queue.c +++ b/src/imagination/vulkan/pvr_queue.c @@ -755,6 +755,128 @@ static VkResult pvr_process_event_cmd_set_or_reset( return VK_SUCCESS; } +/** + * \brief Process an event sub command of wait type. + * + * This sets up barrier syncobjs to create a dependency from the event syncobjs + * onto the next job submissions. + * + * The barriers are setup by taking into consideration each event's dst stage + * mask so this is in line with vkCmdWaitEvents2(). + * + * \param[in] device Device to create the syncobjs on. + * \param[in] sub_cmd Sub command to process. + * \param[in,out] barriers Current barriers as input. Barriers + * for the next jobs as output. + * \parma[in,out] per_cmd_buffer_syncobjs Completion syncobjs for the command + * buffer being processed. + */ +static VkResult pvr_process_event_cmd_wait( + struct pvr_device *device, + struct pvr_sub_cmd_event *sub_cmd, + struct vk_sync *barriers[static PVR_JOB_TYPE_MAX], + struct vk_sync *per_cmd_buffer_syncobjs[static PVR_JOB_TYPE_MAX]) +{ + /* +1 if there's a previous barrier which we need to merge. */ + struct vk_sync *new_barriers[PVR_JOB_TYPE_MAX]; + struct vk_sync *completions[PVR_JOB_TYPE_MAX]; + uint32_t dst_mask = 0; + + STACK_ARRAY(struct vk_sync *, src_syncobjs, sub_cmd->wait.count + 1); + if (!src_syncobjs) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + for (uint32_t i = 0; i < sub_cmd->wait.count; i++) + dst_mask |= sub_cmd->wait.wait_at_stage_masks[i]; + + u_foreach_bit (stage, dst_mask) { + uint32_t src_syncobj_count = 0; + struct vk_sync *completion; + struct vk_sync *barrier; + VkResult result; + + if (barriers[stage]) + src_syncobjs[src_syncobj_count++] = barriers[stage]; + + for (uint32_t i = 0; i < sub_cmd->wait.count; i++) { + if (sub_cmd->wait.wait_at_stage_masks[i] & stage) + src_syncobjs[src_syncobj_count++] = sub_cmd->wait.events[i]->sync; + } + + /* Create completion. */ + + result = vk_sync_create(&device->vk, + &device->pdevice->ws->syncobj_type, + 0U, + 0UL, + &completion); + if (result != VK_SUCCESS) { + STACK_ARRAY_FINISH(src_syncobjs); + return result; + } + + result = device->ws->ops->null_job_submit(device->ws, + src_syncobjs, + src_syncobj_count, + completion); + if (result != VK_SUCCESS) { + vk_sync_destroy(&device->vk, completion); + STACK_ARRAY_FINISH(src_syncobjs); + return result; + } + + completions[stage] = completion; + + /* Create barrier. */ + + /* We can't reuse the completion as a barrier since a barrier can be + * passed into multiple job submissions based on the dst mask while the + * completion gets replaced on each job submission so we'd end up in a + * case where the completion is replaced but other job submissions (of + * different type, i.e. different stages in the dst mask) get fed the + * freed barrier resulting in a use after free. + */ + + result = vk_sync_create(&device->vk, + &device->pdevice->ws->syncobj_type, + 0U, + 0UL, + &barrier); + if (result != VK_SUCCESS) { + vk_sync_destroy(&device->vk, completion); + STACK_ARRAY_FINISH(src_syncobjs); + return result; + } + + result = + device->ws->ops->null_job_submit(device->ws, &completion, 1, barrier); + if (result != VK_SUCCESS) { + vk_sync_destroy(&device->vk, barrier); + vk_sync_destroy(&device->vk, completion); + STACK_ARRAY_FINISH(src_syncobjs); + return result; + } + + new_barriers[stage] = barrier; + } + + u_foreach_bit (stage, dst_mask) { + if (per_cmd_buffer_syncobjs[stage]) + vk_sync_destroy(&device->vk, per_cmd_buffer_syncobjs[stage]); + + per_cmd_buffer_syncobjs[stage] = completions[stage]; + + if (barriers[stage]) + vk_sync_destroy(&device->vk, barriers[stage]); + + barriers[stage] = new_barriers[stage]; + } + + STACK_ARRAY_FINISH(src_syncobjs); + + return VK_SUCCESS; +} + static VkResult pvr_process_event_cmd( struct pvr_device *device, struct pvr_sub_cmd_event *sub_cmd, @@ -772,8 +894,10 @@ static VkResult pvr_process_event_cmd( per_cmd_buffer_syncobjs); case PVR_EVENT_TYPE_WAIT: - pvr_finishme("Add support for event sub command type: %d", sub_cmd->type); - return VK_SUCCESS; + return pvr_process_event_cmd_wait(device, + sub_cmd, + barriers, + per_cmd_buffer_syncobjs); case PVR_EVENT_TYPE_BARRIER: return pvr_process_event_cmd_barrier(device,
