diff --git a/src/imagination/.clang-format b/src/imagination/.clang-format index b3fc44e702e..e6c6e45542b 100644 --- a/src/imagination/.clang-format +++ b/src/imagination/.clang-format @@ -226,6 +226,7 @@ ForEachMacros: [ 'nir_foreach_use', 'nir_foreach_use_safe', 'nir_foreach_variable_with_modes', + 'u_foreach_bit', 'u_vector_foreach', 'util_dynarray_foreach', 'vk_foreach_struct', diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index 8c2ea2fb81e..6dfbda453f2 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -1667,6 +1667,7 @@ static VkResult pvr_cmd_buffer_start_sub_cmd(struct pvr_cmd_buffer *cmd_buffer, pvr_cmd_buffer_update_barriers(cmd_buffer, type); + /* TODO: Add proper support for joining consecutive event sub_cmd? */ if (state->current_sub_cmd) { if (state->current_sub_cmd->type == type) { /* Continue adding to the current sub command. */ @@ -1729,7 +1730,6 @@ static VkResult pvr_cmd_buffer_start_sub_cmd(struct pvr_cmd_buffer *cmd_buffer, break; case PVR_SUB_CMD_TYPE_EVENT: - /* TODO: Add support for joining consecutive event sub_cmd? */ break; default: @@ -6196,18 +6196,59 @@ static bool pvr_is_stencil_store_load_needed( return false; } -static void pvr_insert_mid_frag_barrier(struct pvr_cmd_buffer *cmd_buffer) +static VkResult +pvr_cmd_buffer_insert_mid_frag_barrier_event(struct pvr_cmd_buffer *cmd_buffer, + uint32_t src_stage_mask, + uint32_t dst_stage_mask) { - struct pvr_sub_cmd *const curr_sub_cmd = cmd_buffer->state.current_sub_cmd; + struct pvr_sub_cmd_event *sub_cmd; + VkResult result; - assert(curr_sub_cmd->type == PVR_SUB_CMD_TYPE_GRAPHICS); + assert(cmd_buffer->state.current_sub_cmd->type == PVR_SUB_CMD_TYPE_GRAPHICS); + + cmd_buffer->state.current_sub_cmd->gfx.empty_cmd = false; pvr_finishme("Handle mid frag barrier stencil store."); + pvr_cmd_buffer_end_sub_cmd(cmd_buffer); + result = pvr_cmd_buffer_start_sub_cmd(cmd_buffer, PVR_SUB_CMD_TYPE_EVENT); + if (result != VK_SUCCESS) + return result; + + sub_cmd = &cmd_buffer->state.current_sub_cmd->event; + + sub_cmd->type = PVR_EVENT_TYPE_BARRIER; + sub_cmd->barrier.in_render_pass = true; + sub_cmd->barrier.wait_for_stage_mask = src_stage_mask; + sub_cmd->barrier.wait_at_stage_mask = dst_stage_mask; + pvr_cmd_buffer_end_sub_cmd(cmd_buffer); pvr_cmd_buffer_start_sub_cmd(cmd_buffer, PVR_SUB_CMD_TYPE_GRAPHICS); pvr_finishme("Handle mid frag barrier color attachment load."); + + return VK_SUCCESS; +} + +static VkResult +pvr_cmd_buffer_insert_barrier_event(struct pvr_cmd_buffer *cmd_buffer, + uint32_t src_stage_mask, + uint32_t dst_stage_mask) +{ + struct pvr_sub_cmd_event *sub_cmd; + VkResult result; + + result = pvr_cmd_buffer_start_sub_cmd(cmd_buffer, PVR_SUB_CMD_TYPE_EVENT); + if (result != VK_SUCCESS) + return result; + + sub_cmd = &cmd_buffer->state.current_sub_cmd->event; + + sub_cmd->type = PVR_EVENT_TYPE_BARRIER; + sub_cmd->barrier.wait_for_stage_mask = src_stage_mask; + sub_cmd->barrier.wait_at_stage_mask = dst_stage_mask; + + return pvr_cmd_buffer_end_sub_cmd(cmd_buffer); } /* This is just enough to handle vkCmdPipelineBarrier(). @@ -6335,10 +6376,23 @@ void pvr_CmdPipelineBarrier2(VkCommandBuffer commandBuffer, pDependencyInfo->pImageMemoryBarriers); if (is_stencil_store_load_needed) { - pvr_insert_mid_frag_barrier(cmd_buffer); + VkResult result; + + result = pvr_cmd_buffer_insert_mid_frag_barrier_event(cmd_buffer, + src_stage_mask, + dst_stage_mask); + if (result != VK_SUCCESS) + mesa_loge("Failed to insert mid frag barrier event."); } else { - if (is_barrier_needed) - pvr_finishme("Insert barrier if needed."); + if (is_barrier_needed) { + VkResult result; + + result = pvr_cmd_buffer_insert_barrier_event(cmd_buffer, + src_stage_mask, + dst_stage_mask); + if (result != VK_SUCCESS) + mesa_loge("Failed to insert pipeline barrier event."); + } } } diff --git a/src/imagination/vulkan/pvr_job_compute.c b/src/imagination/vulkan/pvr_job_compute.c index a1d8413919c..843b2c18457 100644 --- a/src/imagination/vulkan/pvr_job_compute.c +++ b/src/imagination/vulkan/pvr_job_compute.c @@ -37,6 +37,7 @@ static void pvr_compute_job_ws_submit_info_init( struct pvr_compute_ctx *ctx, struct pvr_sub_cmd_compute *sub_cmd, + struct vk_sync *barrier, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, @@ -48,6 +49,8 @@ static void pvr_compute_job_ws_submit_info_init( submit_info->frame_num = ctx->device->global_queue_present_count; submit_info->job_num = ctx->device->global_queue_job_count; + submit_info->barrier = barrier; + submit_info->waits = waits; submit_info->wait_count = wait_count; submit_info->stage_flags = stage_flags; @@ -87,6 +90,7 @@ static void pvr_compute_job_ws_submit_info_init( VkResult pvr_compute_job_submit(struct pvr_compute_ctx *ctx, struct pvr_sub_cmd_compute *sub_cmd, + struct vk_sync *barrier, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, @@ -96,6 +100,7 @@ VkResult pvr_compute_job_submit(struct pvr_compute_ctx *ctx, pvr_compute_job_ws_submit_info_init(ctx, sub_cmd, + barrier, waits, wait_count, stage_flags, diff --git a/src/imagination/vulkan/pvr_job_compute.h b/src/imagination/vulkan/pvr_job_compute.h index d0ce2824687..72dfcd0c39a 100644 --- a/src/imagination/vulkan/pvr_job_compute.h +++ b/src/imagination/vulkan/pvr_job_compute.h @@ -33,6 +33,7 @@ struct vk_sync; VkResult pvr_compute_job_submit(struct pvr_compute_ctx *ctx, struct pvr_sub_cmd_compute *sub_cmd, + struct vk_sync *barrier, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, diff --git a/src/imagination/vulkan/pvr_job_render.c b/src/imagination/vulkan/pvr_job_render.c index 66497596770..713ad66a43a 100644 --- a/src/imagination/vulkan/pvr_job_render.c +++ b/src/imagination/vulkan/pvr_job_render.c @@ -1509,6 +1509,8 @@ static void pvr_render_job_ws_submit_info_init( struct pvr_render_job *job, const struct pvr_winsys_job_bo *bos, uint32_t bo_count, + struct vk_sync *barrier_geom, + struct vk_sync *barrier_frag, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, @@ -1527,6 +1529,9 @@ static void pvr_render_job_ws_submit_info_init( submit_info->bos = bos; submit_info->bo_count = bo_count; + submit_info->barrier_geom = barrier_geom; + submit_info->barrier_frag = barrier_frag; + submit_info->waits = waits; submit_info->wait_count = wait_count; submit_info->stage_flags = stage_flags; @@ -1544,6 +1549,8 @@ VkResult pvr_render_job_submit(struct pvr_render_ctx *ctx, struct pvr_render_job *job, const struct pvr_winsys_job_bo *bos, uint32_t bo_count, + struct vk_sync *barrier_geom, + struct vk_sync *barrier_frag, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, @@ -1559,6 +1566,8 @@ VkResult pvr_render_job_submit(struct pvr_render_ctx *ctx, job, bos, bo_count, + barrier_geom, + barrier_frag, waits, wait_count, stage_flags, diff --git a/src/imagination/vulkan/pvr_job_render.h b/src/imagination/vulkan/pvr_job_render.h index bdd846ab67c..35dd2f6fcca 100644 --- a/src/imagination/vulkan/pvr_job_render.h +++ b/src/imagination/vulkan/pvr_job_render.h @@ -120,6 +120,8 @@ VkResult pvr_render_job_submit(struct pvr_render_ctx *ctx, struct pvr_render_job *job, const struct pvr_winsys_job_bo *bos, uint32_t bo_count, + struct vk_sync *barrier_geom, + struct vk_sync *barrier_frag, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, diff --git a/src/imagination/vulkan/pvr_job_transfer.c b/src/imagination/vulkan/pvr_job_transfer.c index bf4fe0693ef..c4d6c1ba7dd 100644 --- a/src/imagination/vulkan/pvr_job_transfer.c +++ b/src/imagination/vulkan/pvr_job_transfer.c @@ -39,6 +39,7 @@ VkResult pvr_transfer_job_submit(struct pvr_device *device, struct pvr_transfer_ctx *ctx, struct pvr_sub_cmd_transfer *sub_cmd, + struct vk_sync *barrier, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, @@ -59,6 +60,17 @@ VkResult pvr_transfer_job_submit(struct pvr_device *device, } } + + if (barrier) { + VkResult result = vk_sync_wait(&device->vk, + barrier, + 0U, + VK_SYNC_WAIT_COMPLETE, + UINT64_MAX); + if (result != VK_SUCCESS) + return result; + } + list_for_each_entry_safe (struct pvr_transfer_cmd, transfer_cmd, &sub_cmd->transfer_cmds, diff --git a/src/imagination/vulkan/pvr_job_transfer.h b/src/imagination/vulkan/pvr_job_transfer.h index c05ca26793a..4550374efd9 100644 --- a/src/imagination/vulkan/pvr_job_transfer.h +++ b/src/imagination/vulkan/pvr_job_transfer.h @@ -35,6 +35,7 @@ struct vk_sync; VkResult pvr_transfer_job_submit(struct pvr_device *device, struct pvr_transfer_ctx *ctx, struct pvr_sub_cmd_transfer *sub_cmd, + struct vk_sync *barrier, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h index 7b960c18114..275576f9e06 100644 --- a/src/imagination/vulkan/pvr_private.h +++ b/src/imagination/vulkan/pvr_private.h @@ -290,6 +290,13 @@ struct pvr_queue { struct pvr_transfer_ctx *transfer_ctx; struct vk_sync *completion[PVR_JOB_TYPE_MAX]; + + /* Used to setup a job dependency from jobs previously submitted, onto + * the next job per job type. + * + * Used to create dependencies for pipeline barriers. + */ + struct vk_sync *job_dependancy[PVR_JOB_TYPE_MAX]; }; struct pvr_vertex_binding { @@ -764,6 +771,15 @@ struct pvr_sub_cmd_event { /* Stages to wait at. */ uint32_t *wait_at_stage_masks; } wait; + + struct { + bool in_render_pass; + + /* Stages to wait for. */ + uint32_t wait_for_stage_mask; + /* Stages to wait at. */ + uint32_t wait_at_stage_mask; + } barrier; }; }; diff --git a/src/imagination/vulkan/pvr_queue.c b/src/imagination/vulkan/pvr_queue.c index 56ff8a7b877..cc35f30ac59 100644 --- a/src/imagination/vulkan/pvr_queue.c +++ b/src/imagination/vulkan/pvr_queue.c @@ -64,6 +64,8 @@ static VkResult pvr_queue_init(struct pvr_device *device, struct pvr_render_ctx *gfx_ctx; VkResult result; + *queue = (struct pvr_queue){ 0 }; + result = vk_queue_init(&queue->vk, &device->vk, pCreateInfo, index_in_family); if (result != VK_SUCCESS) @@ -91,9 +93,6 @@ static VkResult pvr_queue_init(struct pvr_device *device, queue->compute_ctx = compute_ctx; queue->transfer_ctx = transfer_ctx; - for (uint32_t i = 0; i < ARRAY_SIZE(queue->completion); i++) - queue->completion[i] = NULL; - return VK_SUCCESS; err_compute_ctx_destroy: @@ -147,6 +146,11 @@ err_queues_finish: static void pvr_queue_finish(struct pvr_queue *queue) { + for (uint32_t i = 0; i < ARRAY_SIZE(queue->job_dependancy); i++) { + if (queue->job_dependancy[i]) + vk_sync_destroy(&queue->device->vk, queue->job_dependancy[i]); + } + for (uint32_t i = 0; i < ARRAY_SIZE(queue->completion); i++) { if (queue->completion[i]) vk_sync_destroy(&queue->device->vk, queue->completion[i]); @@ -194,6 +198,8 @@ pvr_process_graphics_cmd(struct pvr_device *device, struct pvr_queue *queue, struct pvr_cmd_buffer *cmd_buffer, struct pvr_sub_cmd_gfx *sub_cmd, + struct vk_sync *barrier_geom, + struct vk_sync *barrier_frag, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, @@ -256,6 +262,8 @@ pvr_process_graphics_cmd(struct pvr_device *device, &sub_cmd->job, bos, bo_count, + barrier_geom, + barrier_frag, waits, wait_count, stage_flags, @@ -288,6 +296,7 @@ static VkResult pvr_process_compute_cmd(struct pvr_device *device, struct pvr_queue *queue, struct pvr_sub_cmd_compute *sub_cmd, + struct vk_sync *barrier, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, @@ -307,6 +316,7 @@ pvr_process_compute_cmd(struct pvr_device *device, /* This passes ownership of the wait fences to pvr_compute_job_submit(). */ result = pvr_compute_job_submit(queue->compute_ctx, sub_cmd, + barrier, waits, wait_count, stage_flags, @@ -329,6 +339,7 @@ static VkResult pvr_process_transfer_cmds(struct pvr_device *device, struct pvr_queue *queue, struct pvr_sub_cmd_transfer *sub_cmd, + struct vk_sync *barrier, struct vk_sync **waits, uint32_t wait_count, uint32_t *stage_flags, @@ -349,6 +360,7 @@ pvr_process_transfer_cmds(struct pvr_device *device, result = pvr_transfer_job_submit(device, queue->transfer_ctx, sub_cmd, + barrier, waits, wait_count, stage_flags, @@ -367,6 +379,193 @@ pvr_process_transfer_cmds(struct pvr_device *device, return result; } +static VkResult pvr_process_event_cmd_barrier( + 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], + struct vk_sync *per_submit_syncobjs[static PVR_JOB_TYPE_MAX], + struct vk_sync *queue_syncobjs[static PVR_JOB_TYPE_MAX], + struct vk_sync *previous_queue_syncobjs[static PVR_JOB_TYPE_MAX]) +{ + const uint32_t src_mask = sub_cmd->barrier.wait_for_stage_mask; + const uint32_t dst_mask = sub_cmd->barrier.wait_at_stage_mask; + const bool in_render_pass = sub_cmd->barrier.in_render_pass; + struct vk_sync *new_barriers[PVR_JOB_TYPE_MAX] = { 0 }; + struct vk_sync *completions[PVR_JOB_TYPE_MAX] = { 0 }; + struct vk_sync *src_syncobjs[PVR_JOB_TYPE_MAX]; + uint32_t src_syncobj_count = 0; + VkResult result; + + assert(!(src_mask & ~PVR_PIPELINE_STAGE_ALL_BITS)); + assert(!(dst_mask & ~PVR_PIPELINE_STAGE_ALL_BITS)); + + /* TODO: We're likely over synchronizing here, but the kernel doesn't + * guarantee that jobs submitted on a context will execute and complete in + * order, even though in practice they will, so we play it safe and don't + * make any assumptions. If the kernel starts to offer this guarantee then + * remove the extra dependencies being added here. + */ + + u_foreach_bit (stage, src_mask) { + struct vk_sync *syncobj; + + syncobj = per_cmd_buffer_syncobjs[stage]; + + if (!in_render_pass & !syncobj) { + if (per_submit_syncobjs[stage]) + syncobj = per_submit_syncobjs[stage]; + else if (queue_syncobjs[stage]) + syncobj = queue_syncobjs[stage]; + else if (previous_queue_syncobjs[stage]) + syncobj = previous_queue_syncobjs[stage]; + } + + if (!syncobj) + continue; + + src_syncobjs[src_syncobj_count++] = syncobj; + } + + /* No previous src jobs that need finishing so no need for a barrier. */ + if (src_syncobj_count == 0) + return VK_SUCCESS; + + u_foreach_bit (stage, dst_mask) { + struct vk_sync *completion; + + result = vk_sync_create(&device->vk, + &device->pdevice->ws->syncobj_type, + 0U, + 0UL, + &completion); + if (result != VK_SUCCESS) + goto err_destroy_completions; + + 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); + + goto err_destroy_completions; + } + + completions[stage] = completion; + } + + u_foreach_bit (stage, dst_mask) { + struct vk_sync *barrier_src_syncobjs[2]; + uint32_t barrier_src_syncobj_count = 0; + struct vk_sync *barrier; + VkResult result; + + assert(completions[stage]); + barrier_src_syncobjs[barrier_src_syncobj_count++] = completions[stage]; + + /* If there is a previous barrier we want to merge it with the new one. + * + * E.g. + * A , B , + * X , + * C + * Y , + * D + * + * X barriers A and B at D. Y barriers C at D. So we want to merge both + * X and Y graphics vk_sync barriers to pass to D. + * + * Note that this is the same as: + * A , B , C + * X , + * Y , + * D + * + */ + if (barriers[stage]) + barrier_src_syncobjs[barrier_src_syncobj_count++] = barriers[stage]; + + result = vk_sync_create(&device->vk, + &device->pdevice->ws->syncobj_type, + 0U, + 0UL, + &barrier); + if (result != VK_SUCCESS) + goto err_destroy_new_barriers; + + result = device->ws->ops->null_job_submit(device->ws, + barrier_src_syncobjs, + barrier_src_syncobj_count, + barrier); + if (result != VK_SUCCESS) { + vk_sync_destroy(&device->vk, barrier); + + goto err_destroy_new_barriers; + } + + 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]; + } + + return VK_SUCCESS; + +err_destroy_new_barriers: + u_foreach_bit (stage, dst_mask) { + if (new_barriers[stage]) + vk_sync_destroy(&device->vk, new_barriers[stage]); + } + +err_destroy_completions: + u_foreach_bit (stage, dst_mask) { + if (completions[stage]) + vk_sync_destroy(&device->vk, completions[stage]); + } + + return result; +} + +static VkResult pvr_process_event_cmd( + 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], + struct vk_sync *per_submit_syncobjs[static PVR_JOB_TYPE_MAX], + struct vk_sync *queue_syncobjs[static PVR_JOB_TYPE_MAX], + struct vk_sync *previous_queue_syncobjs[static PVR_JOB_TYPE_MAX]) +{ + switch (sub_cmd->type) { + case PVR_EVENT_TYPE_SET: + case PVR_EVENT_TYPE_RESET: + case PVR_EVENT_TYPE_WAIT: + pvr_finishme("Add support for event sub command type: %d", sub_cmd->type); + return VK_SUCCESS; + + case PVR_EVENT_TYPE_BARRIER: + return pvr_process_event_cmd_barrier(device, + sub_cmd, + barriers, + per_cmd_buffer_syncobjs, + per_submit_syncobjs, + queue_syncobjs, + previous_queue_syncobjs); + + default: + unreachable("Invalid event sub-command type."); + }; +} + static VkResult pvr_set_semaphore_payloads(struct pvr_device *device, struct vk_sync *completions[static PVR_JOB_TYPE_MAX], @@ -459,15 +658,33 @@ pvr_set_fence_payload(struct pvr_device *device, return result; } -static VkResult -pvr_process_cmd_buffer(struct pvr_device *device, - struct pvr_queue *queue, - VkCommandBuffer commandBuffer, - struct vk_sync **waits, - uint32_t wait_count, - uint32_t *stage_flags, - struct vk_sync *completions[static PVR_JOB_TYPE_MAX]) +static void pvr_update_syncobjs(struct pvr_device *device, + struct vk_sync *src[static PVR_JOB_TYPE_MAX], + struct vk_sync *dst[static PVR_JOB_TYPE_MAX]) { + for (uint32_t i = 0; i < PVR_JOB_TYPE_MAX; i++) { + if (src[i]) { + if (dst[i]) + vk_sync_destroy(&device->vk, dst[i]); + + dst[i] = src[i]; + } + } +} + +static VkResult pvr_process_cmd_buffer( + struct pvr_device *device, + struct pvr_queue *queue, + VkCommandBuffer commandBuffer, + struct vk_sync *barriers[static PVR_JOB_TYPE_MAX], + struct vk_sync **waits, + uint32_t wait_count, + uint32_t *stage_flags, + struct vk_sync *per_submit_syncobjs[static PVR_JOB_TYPE_MAX], + struct vk_sync *queue_syncobjs[static PVR_JOB_TYPE_MAX], + struct vk_sync *previous_queue_syncobjs[static PVR_JOB_TYPE_MAX]) +{ + struct vk_sync *per_cmd_buffer_syncobjs[PVR_JOB_TYPE_MAX] = {}; PVR_FROM_HANDLE(pvr_cmd_buffer, cmd_buffer, commandBuffer); VkResult result; @@ -483,35 +700,44 @@ pvr_process_cmd_buffer(struct pvr_device *device, queue, cmd_buffer, &sub_cmd->gfx, + barriers[PVR_JOB_TYPE_GEOM], + barriers[PVR_JOB_TYPE_FRAG], waits, wait_count, stage_flags, - completions); + per_cmd_buffer_syncobjs); break; case PVR_SUB_CMD_TYPE_COMPUTE: result = pvr_process_compute_cmd(device, queue, &sub_cmd->compute, + barriers[PVR_JOB_TYPE_COMPUTE], waits, wait_count, stage_flags, - completions); + per_cmd_buffer_syncobjs); break; case PVR_SUB_CMD_TYPE_TRANSFER: result = pvr_process_transfer_cmds(device, queue, &sub_cmd->transfer, + barriers[PVR_JOB_TYPE_TRANSFER], waits, wait_count, stage_flags, - completions); + per_cmd_buffer_syncobjs); break; case PVR_SUB_CMD_TYPE_EVENT: - pvr_finishme("Add support to process event sub cmds."); - result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + result = pvr_process_event_cmd(device, + &sub_cmd->event, + barriers, + per_cmd_buffer_syncobjs, + per_submit_syncobjs, + queue_syncobjs, + previous_queue_syncobjs); break; default: @@ -527,6 +753,8 @@ pvr_process_cmd_buffer(struct pvr_device *device, p_atomic_inc(&device->global_queue_job_count); } + pvr_update_syncobjs(device, per_cmd_buffer_syncobjs, per_submit_syncobjs); + return VK_SUCCESS; } @@ -584,20 +812,6 @@ err_destroy_completion_syncs: return result; } -static void pvr_update_syncobjs(struct pvr_device *device, - struct vk_sync *src[static PVR_JOB_TYPE_MAX], - struct vk_sync *dst[static PVR_JOB_TYPE_MAX]) -{ - for (uint32_t i = 0; i < PVR_JOB_TYPE_MAX; i++) { - if (src[i]) { - if (dst[i]) - vk_sync_destroy(&device->vk, dst[i]); - - dst[i] = src[i]; - } - } -} - VkResult pvr_QueueSubmit(VkQueue _queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, @@ -636,10 +850,13 @@ VkResult pvr_QueueSubmit(VkQueue _queue, result = pvr_process_cmd_buffer(device, queue, desc->pCommandBuffers[j], + queue->job_dependancy, waits, wait_count, stage_flags, - per_submit_completion_syncobjs); + per_submit_completion_syncobjs, + completion_syncobjs, + queue->completion); if (result != VK_SUCCESS) return result; } diff --git a/src/imagination/vulkan/winsys/pvr_winsys.h b/src/imagination/vulkan/winsys/pvr_winsys.h index a69595ebd8d..96ef5a3b9ad 100644 --- a/src/imagination/vulkan/winsys/pvr_winsys.h +++ b/src/imagination/vulkan/winsys/pvr_winsys.h @@ -279,6 +279,8 @@ struct pvr_winsys_transfer_submit_info { uint32_t frame_num; uint32_t job_num; + struct vk_sync *barrier; + /* waits and stage_flags are arrays of length wait_count. */ struct vk_sync **waits; uint32_t wait_count; @@ -300,6 +302,8 @@ struct pvr_winsys_compute_submit_info { uint32_t frame_num; uint32_t job_num; + struct vk_sync *barrier; + /* waits and stage_flags are arrays of length wait_count. */ struct vk_sync **waits; uint32_t wait_count; @@ -349,6 +353,9 @@ struct pvr_winsys_render_submit_info { /* FIXME: should this be flags instead? */ bool run_frag; + struct vk_sync *barrier_geom; + struct vk_sync *barrier_frag; + /* waits and stage_flags are arrays of length wait_count. */ struct vk_sync **waits; uint32_t wait_count; diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.c index 57e8e36ead1..03faa250cc0 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.c @@ -196,6 +196,20 @@ VkResult pvr_srv_winsys_compute_submit( } } + if (submit_info->barrier) { + struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->barrier); + + if (srv_wait_sync->fd >= 0) { + int ret; + + ret = sync_accumulate("", &in_fd, srv_wait_sync->fd); + if (ret) { + result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + goto end_close_in_fd; + } + } + } + do { result = pvr_srv_rgx_kick_compute2(srv_ws->render_fd, srv_ctx->handle, diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c index 352f41fa6bc..0364db6d14a 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c @@ -587,6 +587,36 @@ VkResult pvr_srv_winsys_render_submit( } } + if (submit_info->barrier_geom) { + struct pvr_srv_sync *srv_wait_sync = + to_srv_sync(submit_info->barrier_geom); + + if (srv_wait_sync->fd >= 0) { + int ret; + + ret = sync_accumulate("", &in_geom_fd, srv_wait_sync->fd); + if (ret) { + result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + goto end_close_in_fds; + } + } + } + + if (submit_info->barrier_frag) { + struct pvr_srv_sync *srv_wait_sync = + to_srv_sync(submit_info->barrier_frag); + + if (srv_wait_sync->fd >= 0) { + int ret; + + ret = sync_accumulate("", &in_frag_fd, srv_wait_sync->fd); + if (ret) { + result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + goto end_close_in_fds; + } + } + } + if (submit_info->bo_count <= ARRAY_SIZE(sync_pmrs)) { sync_pmr_count = submit_info->bo_count; } else { diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c index 4838dd1b679..bd10355457e 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c @@ -244,6 +244,20 @@ VkResult pvr_srv_winsys_transfer_submit( } } + if (submit_info->barrier) { + struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->barrier); + + if (srv_wait_sync->fd >= 0) { + int ret; + + ret = sync_accumulate("", &in_fd, srv_wait_sync->fd); + if (ret) { + result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + goto end_close_in_fd; + } + } + } + job_num = submit_info->job_num; do {