diff --git a/src/imagination/vulkan/pvr_job_context.h b/src/imagination/vulkan/pvr_job_context.h index 5cd948acfad..a655abf0010 100644 --- a/src/imagination/vulkan/pvr_job_context.h +++ b/src/imagination/vulkan/pvr_job_context.h @@ -24,8 +24,8 @@ #ifndef PVR_JOB_CONTEXT_H #define PVR_JOB_CONTEXT_H -#include "pvr_winsys.h" #include "pvr_private.h" +#include "pvr_winsys.h" /* Support PDS code/data loading/storing to the 'B' shared register state * buffers. @@ -132,8 +132,6 @@ struct pvr_compute_ctx { "Transfer queue can not support more DMA kicks than supported by PDS codegen." #endif -#define PVR_TRANSFER_MAX_RENDER_TARGETS 3U - struct pvr_transfer_ctx { struct pvr_device *device; diff --git a/src/imagination/vulkan/winsys/pvr_winsys.h b/src/imagination/vulkan/winsys/pvr_winsys.h index 9cb5bda4c07..a895f3cf42b 100644 --- a/src/imagination/vulkan/winsys/pvr_winsys.h +++ b/src/imagination/vulkan/winsys/pvr_winsys.h @@ -253,6 +253,54 @@ struct pvr_winsys_transfer_ctx { struct pvr_winsys *ws; }; +#define PVR_WINSYS_TRANSFER_FLAG_START BITFIELD_BIT(0U) +#define PVR_WINSYS_TRANSFER_FLAG_END BITFIELD_BIT(1U) + +#define PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT 16U +#define PVR_TRANSFER_MAX_RENDER_TARGETS 3U + +struct pvr_winsys_transfer_regs { + uint32_t event_pixel_pds_code; + uint32_t event_pixel_pds_data; + uint32_t event_pixel_pds_info; + uint32_t isp_aa; + uint32_t isp_bgobjvals; + uint32_t isp_ctl; + uint64_t isp_mtile_base; + uint32_t isp_mtile_size; + uint32_t isp_render; + uint32_t isp_render_origin; + uint32_t isp_rgn; + uint64_t pbe_wordx_mrty[PVR_TRANSFER_MAX_RENDER_TARGETS * + ROGUE_NUM_PBESTATE_REG_WORDS]; + uint64_t pds_bgnd0_base; + uint64_t pds_bgnd1_base; + uint64_t pds_bgnd3_sizeinfo; + uint32_t usc_clear_register0; + uint32_t usc_clear_register1; + uint32_t usc_clear_register2; + uint32_t usc_clear_register3; + uint32_t usc_pixel_output_ctrl; +}; + +struct pvr_winsys_transfer_submit_info { + uint32_t frame_num; + uint32_t job_num; + + /* waits and stage_flags are arrays of length wait_count. */ + struct vk_sync **waits; + uint32_t wait_count; + uint32_t *stage_flags; + + uint32_t cmd_count; + struct { + struct pvr_winsys_transfer_regs regs; + + /* Must be 0 or a combination of PVR_WINSYS_TRANSFER_FLAG_* flags. */ + uint32_t flags; + } cmds[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT]; +}; + #define PVR_WINSYS_COMPUTE_FLAG_PREVENT_ALL_OVERLAP BITFIELD_BIT(0U) #define PVR_WINSYS_COMPUTE_FLAG_SINGLE_CORE BITFIELD_BIT(1U) @@ -440,6 +488,10 @@ struct pvr_winsys_ops { const struct pvr_winsys_transfer_ctx_create_info *create_info, struct pvr_winsys_transfer_ctx **const ctx_out); void (*transfer_ctx_destroy)(struct pvr_winsys_transfer_ctx *ctx); + VkResult (*transfer_submit)( + const struct pvr_winsys_transfer_ctx *ctx, + const struct pvr_winsys_transfer_submit_info *submit_info, + struct vk_sync *signal_sync); VkResult (*null_job_submit)(struct pvr_winsys *ws, struct vk_sync **waits, diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/fw-api/pvr_rogue_fwif.h b/src/imagination/vulkan/winsys/pvrsrvkm/fw-api/pvr_rogue_fwif.h index 43f72d06b12..365fd37ffa8 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/fw-api/pvr_rogue_fwif.h +++ b/src/imagination/vulkan/winsys/pvrsrvkm/fw-api/pvr_rogue_fwif.h @@ -28,7 +28,9 @@ #include #include +#include "hwdef/rogue_hw_defs.h" #include "pvr_rogue_fwif_shared.h" +#include "pvr_winsys.h" /** * \name Frag DM command flags. @@ -358,9 +360,9 @@ struct rogue_fwif_transfer_regs { /* FIXME: HIGH: RGX_PBE_WORDS_REQUIRED_FOR_TQS changes the structure's * layout. */ -#define ROGUE_PBE_WORDS_REQUIRED_FOR_TRANSFER 3 /* TQ_MAX_RENDER_TARGETS * PBE_STATE_SIZE */ - uint64_t pbe_wordx_mrty[3U * ROGUE_PBE_WORDS_REQUIRED_FOR_TRANSFER]; + uint64_t pbe_wordx_mrty[PVR_TRANSFER_MAX_RENDER_TARGETS * + ROGUE_NUM_PBESTATE_REG_WORDS]; }; /** diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv.c index 2d298e15bf4..de3393c50fa 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv.c @@ -452,6 +452,7 @@ static const struct pvr_winsys_ops srv_winsys_ops = { .compute_submit = pvr_srv_winsys_compute_submit, .transfer_ctx_create = pvr_srv_winsys_transfer_ctx_create, .transfer_ctx_destroy = pvr_srv_winsys_transfer_ctx_destroy, + .transfer_submit = pvr_srv_winsys_transfer_submit, .null_job_submit = pvr_srv_winsys_null_job_submit, }; diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_bridge.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_bridge.c index 9a6da62d8db..8aff3014fe5 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_bridge.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_bridge.c @@ -871,6 +871,75 @@ void pvr_srv_rgx_destroy_transfer_context(int fd, void *transfer_context) } } +VkResult pvr_srv_rgx_submit_transfer2(int fd, + void *transfer_context, + uint32_t prepare_count, + uint32_t *client_update_count, + void ***update_ufo_sync_prim_block, + uint32_t **update_sync_offset, + uint32_t **update_value, + int32_t check_fence, + int32_t update_timeline_2d, + int32_t update_timeline_3d, + char *update_fence_name, + uint32_t *cmd_size, + uint8_t **fw_command, + uint32_t *tq_prepare_flags, + uint32_t ext_job_ref, + uint32_t sync_pmr_count, + uint32_t *sync_pmr_flags, + void **sync_pmrs, + int32_t *const update_fence_2d_out, + int32_t *const update_fence_3d_out) +{ + struct pvr_srv_rgx_submit_transfer2_cmd cmd = { + .transfer_context = transfer_context, + .client_update_count = client_update_count, + .cmd_size = cmd_size, + .sync_pmr_flags = sync_pmr_flags, + .tq_prepare_flags = tq_prepare_flags, + .update_sync_offset = update_sync_offset, + .update_value = update_value, + .fw_command = fw_command, + .update_fence_name = update_fence_name, + .sync_pmrs = sync_pmrs, + .update_ufo_sync_prim_block = update_ufo_sync_prim_block, + .update_timeline_2d = update_timeline_2d, + .update_timeline_3d = update_timeline_3d, + .check_fence = check_fence, + .ext_job_ref = ext_job_ref, + .prepare_count = prepare_count, + .sync_pmr_count = sync_pmr_count, + }; + + struct pvr_srv_rgx_submit_transfer2_ret ret = { + .error = PVR_SRV_ERROR_BRIDGE_CALL_FAILED, + }; + + int result; + + result = pvr_srv_bridge_call(fd, + PVR_SRV_BRIDGE_RGXTQ, + PVR_SRV_BRIDGE_RGXTQ_RGXSUBMITTRANSFER2, + &cmd, + sizeof(cmd), + &ret, + sizeof(ret)); + if (result || ret.error != PVR_SRV_OK) { + return vk_bridge_err(VK_ERROR_OUT_OF_DEVICE_MEMORY, + "PVR_SRV_BRIDGE_RGXTQ_RGXSUBMITTRANSFER2", + ret); + } + + if (update_fence_2d_out) + *update_fence_2d_out = ret.update_fence_2d; + + if (update_fence_3d_out) + *update_fence_3d_out = ret.update_fence_3d; + + return VK_SUCCESS; +} + VkResult pvr_srv_rgx_create_compute_context(int fd, uint32_t priority, diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_bridge.h b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_bridge.h index 978e4fa3fe5..7c475cd63c3 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_bridge.h +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_bridge.h @@ -73,6 +73,7 @@ #define PVR_SRV_BRIDGE_RGXTQ_RGXCREATETRANSFERCONTEXT 0UL #define PVR_SRV_BRIDGE_RGXTQ_RGXDESTROYTRANSFERCONTEXT 1UL +#define PVR_SRV_BRIDGE_RGXTQ_RGXSUBMITTRANSFER2 3UL #define PVR_SRV_BRIDGE_RGXCMP 129UL @@ -105,6 +106,14 @@ #define DRM_IOCTL_SRVKM_INIT \ DRM_IOWR(DRM_COMMAND_BASE + DRM_SRVKM_INIT, struct drm_srvkm_init_data) +/****************************************************************************** + Bridge call specific defines + ******************************************************************************/ + +/* Flags for PVR_SRV_BRIDGE_RGXTQ_RGXSUBMITTRANSFER2 bridge call. */ +#define PVR_TRANSFER_PREP_FLAGS_START BITFIELD_BIT(5U) +#define PVR_TRANSFER_PREP_FLAGS_END BITFIELD_BIT(6U) + /****************************************************************************** Misc defines ******************************************************************************/ @@ -504,6 +513,36 @@ struct pvr_srv_rgx_destroy_transfer_context_ret { enum pvr_srv_error error; } PACKED; +/****************************************************************************** + PVR_SRV_BRIDGE_RGXTQ_RGXSUBMITTRANSFER2 structs + ******************************************************************************/ + +struct pvr_srv_rgx_submit_transfer2_cmd { + void *transfer_context; + uint32_t *client_update_count; + uint32_t *cmd_size; + uint32_t *sync_pmr_flags; + uint32_t *tq_prepare_flags; + uint32_t **update_sync_offset; + uint32_t **update_value; + uint8_t **fw_command; + char *update_fence_name; + void **sync_pmrs; + void ***update_ufo_sync_prim_block; + int32_t update_timeline_2d; + int32_t update_timeline_3d; + int32_t check_fence; + uint32_t ext_job_ref; + uint32_t prepare_count; + uint32_t sync_pmr_count; +} PACKED; + +struct pvr_srv_rgx_submit_transfer2_ret { + enum pvr_srv_error error; + int32_t update_fence_2d; + int32_t update_fence_3d; +} PACKED; + /****************************************************************************** PVR_SRV_BRIDGE_RGXCMP_RGXCREATECOMPUTECONTEXT structs ******************************************************************************/ @@ -935,6 +974,26 @@ VkResult pvr_srv_rgx_create_transfer_context(int fd, void **const usc_pmr_out, void **const transfer_context_out); void pvr_srv_rgx_destroy_transfer_context(int fd, void *transfer_context); +VkResult pvr_srv_rgx_submit_transfer2(int fd, + void *transfer_context, + uint32_t prepare_count, + uint32_t *client_update_count, + void ***update_ufo_sync_prim_block, + uint32_t **update_sync_offset, + uint32_t **update_value, + int32_t check_fence, + int32_t update_timeline_2d, + int32_t update_timeline_3d, + char *update_fence_name, + uint32_t *cmd_size, + uint8_t **fw_command, + uint32_t *tq_prepare_flags, + uint32_t ext_job_ref, + uint32_t sync_pmr_count, + uint32_t *sync_pmr_flags, + void **sync_pmrs, + int32_t *update_fence_2d_out, + int32_t *update_fence_3d_out); VkResult pvr_srv_rgx_create_hwrt_dataset(int fd, 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 44b43da1953..670a71ea525 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c @@ -27,16 +27,20 @@ #include #include +#include "fw-api/pvr_rogue_fwif.h" #include "fw-api/pvr_rogue_fwif_rf.h" #include "pvr_private.h" #include "pvr_srv.h" #include "pvr_srv_bridge.h" #include "pvr_srv_job_common.h" #include "pvr_srv_job_transfer.h" +#include "pvr_srv_sync.h" #include "pvr_winsys.h" +#include "util/libsync.h" #include "util/macros.h" #include "vk_alloc.h" #include "vk_log.h" +#include "vk_util.h" #define PVR_SRV_TRANSFER_CONTEXT_INITIAL_CCB_SIZE_LOG2 16U #define PVR_SRV_TRANSFER_CONTEXT_MAX_CCB_SIZE_LOG2 0U @@ -46,7 +50,7 @@ struct pvr_srv_winsys_transfer_ctx { void *handle; - int timeline; + int timeline_3d; }; #define to_pvr_srv_winsys_transfer_ctx(ctx) \ @@ -78,7 +82,7 @@ VkResult pvr_srv_winsys_transfer_ctx_create( if (!srv_ctx) return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); - result = pvr_srv_create_timeline(srv_ws->render_fd, &srv_ctx->timeline); + result = pvr_srv_create_timeline(srv_ws->render_fd, &srv_ctx->timeline_3d); if (result != VK_SUCCESS) goto err_free_srv_ctx; @@ -106,7 +110,7 @@ VkResult pvr_srv_winsys_transfer_ctx_create( return VK_SUCCESS; err_close_timeline: - close(srv_ctx->timeline); + close(srv_ctx->timeline_3d); err_free_srv_ctx: vk_free(srv_ws->alloc, srv_ctx); @@ -121,6 +125,170 @@ void pvr_srv_winsys_transfer_ctx_destroy(struct pvr_winsys_transfer_ctx *ctx) to_pvr_srv_winsys_transfer_ctx(ctx); pvr_srv_rgx_destroy_transfer_context(srv_ws->render_fd, srv_ctx->handle); - close(srv_ctx->timeline); + close(srv_ctx->timeline_3d); vk_free(srv_ws->alloc, srv_ctx); } + +static void pvr_srv_transfer_cmds_init( + const struct pvr_winsys_transfer_submit_info *submit_info, + struct rogue_fwif_cmd_transfer *cmds, + uint32_t cmd_count) +{ + memset(cmds, 0, sizeof(*cmds) * submit_info->cmd_count); + + for (uint32_t i = 0; i < cmd_count; i++) { + struct rogue_fwif_transfer_regs *fw_regs = &cmds[i].regs; + + cmds[i].cmn.frame_num = submit_info->frame_num; + + fw_regs->isp_bgobjvals = submit_info->cmds[i].regs.isp_bgobjvals; + fw_regs->usc_pixel_output_ctrl = + submit_info->cmds[i].regs.usc_pixel_output_ctrl; + fw_regs->usc_clear_register0 = + submit_info->cmds[i].regs.usc_clear_register0; + fw_regs->usc_clear_register1 = + submit_info->cmds[i].regs.usc_clear_register1; + fw_regs->usc_clear_register2 = + submit_info->cmds[i].regs.usc_clear_register2; + fw_regs->usc_clear_register3 = + submit_info->cmds[i].regs.usc_clear_register3; + fw_regs->isp_mtile_size = submit_info->cmds[i].regs.isp_mtile_size; + fw_regs->isp_render_origin = submit_info->cmds[i].regs.isp_render_origin; + fw_regs->isp_ctl = submit_info->cmds[i].regs.isp_ctl; + fw_regs->isp_aa = submit_info->cmds[i].regs.isp_aa; + fw_regs->event_pixel_pds_info = + submit_info->cmds[i].regs.event_pixel_pds_info; + fw_regs->event_pixel_pds_code = + submit_info->cmds[i].regs.event_pixel_pds_code; + fw_regs->event_pixel_pds_data = + submit_info->cmds[i].regs.event_pixel_pds_data; + fw_regs->isp_render = submit_info->cmds[i].regs.isp_render; + fw_regs->isp_rgn = submit_info->cmds[i].regs.isp_rgn; + fw_regs->pds_bgnd0_base = submit_info->cmds[i].regs.pds_bgnd0_base; + fw_regs->pds_bgnd1_base = submit_info->cmds[i].regs.pds_bgnd1_base; + fw_regs->pds_bgnd3_sizeinfo = + submit_info->cmds[i].regs.pds_bgnd3_sizeinfo; + fw_regs->isp_mtile_base = submit_info->cmds[i].regs.isp_mtile_base; + + STATIC_ASSERT(ARRAY_SIZE(fw_regs->pbe_wordx_mrty) == + ARRAY_SIZE(submit_info->cmds[i].regs.pbe_wordx_mrty)); + for (uint32_t j = 0; j < ARRAY_SIZE(fw_regs->pbe_wordx_mrty); j++) { + fw_regs->pbe_wordx_mrty[j] = + submit_info->cmds[i].regs.pbe_wordx_mrty[j]; + } + } +} + +VkResult pvr_srv_winsys_transfer_submit( + const struct pvr_winsys_transfer_ctx *ctx, + const struct pvr_winsys_transfer_submit_info *submit_info, + struct vk_sync *signal_sync) +{ + const struct pvr_srv_winsys_transfer_ctx *srv_ctx = + to_pvr_srv_winsys_transfer_ctx(ctx); + const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws); + + struct rogue_fwif_cmd_transfer + *cmds_ptr_arr[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT]; + uint32_t *update_sync_offsets[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 }; + uint32_t client_update_count[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 }; + void **update_ufo_syc_prims[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 }; + uint32_t *update_values[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 }; + uint32_t cmd_sizes[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT]; + uint32_t cmd_flags[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT]; + + struct pvr_srv_sync *srv_signal_sync; + uint32_t job_num; + VkResult result; + int in_fd = -1; + int fence; + + STACK_ARRAY(struct rogue_fwif_cmd_transfer, + transfer_cmds, + submit_info->cmd_count); + if (!transfer_cmds) + return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + + pvr_srv_transfer_cmds_init(submit_info, + transfer_cmds, + submit_info->cmd_count); + + for (uint32_t i = 0U; i < submit_info->cmd_count; i++) { + cmd_sizes[i] = sizeof(**cmds_ptr_arr); + + cmd_flags[i] = 0; + if (submit_info->cmds[i].flags & PVR_WINSYS_TRANSFER_FLAG_START) + cmd_flags[i] |= PVR_TRANSFER_PREP_FLAGS_START; + + if (submit_info->cmds[i].flags & PVR_WINSYS_TRANSFER_FLAG_END) + cmd_flags[i] |= PVR_TRANSFER_PREP_FLAGS_END; + + cmds_ptr_arr[i] = &transfer_cmds[i]; + } + + for (uint32_t i = 0U; i < submit_info->wait_count; i++) { + struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->waits[i]); + int ret; + + if (!submit_info->waits[i] || srv_wait_sync->fd < 0) + continue; + + if (submit_info->stage_flags[i] & PVR_PIPELINE_STAGE_TRANSFER_BIT) { + ret = sync_accumulate("", &in_fd, srv_wait_sync->fd); + if (ret) { + result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); + goto err_close_in_fd; + } + + submit_info->stage_flags[i] &= ~PVR_PIPELINE_STAGE_TRANSFER_BIT; + } + } + + job_num = submit_info->job_num; + + do { + result = pvr_srv_rgx_submit_transfer2(srv_ws->render_fd, + srv_ctx->handle, + submit_info->cmd_count, + client_update_count, + update_ufo_syc_prims, + update_sync_offsets, + update_values, + in_fd, + -1, + srv_ctx->timeline_3d, + "TRANSFER", + cmd_sizes, + (uint8_t **)cmds_ptr_arr, + cmd_flags, + job_num, + /* TODO: Add sync PMR support. */ + 0U, + NULL, + NULL, + NULL, + &fence); + } while (result == VK_NOT_READY); + + if (result != VK_SUCCESS) + goto err_close_in_fd; + + if (signal_sync) { + srv_signal_sync = to_srv_sync(signal_sync); + pvr_srv_set_sync_payload(srv_signal_sync, fence); + } else if (fence != -1) { + close(fence); + } + + STACK_ARRAY_FINISH(transfer_cmds); + + return VK_SUCCESS; + +err_close_in_fd: + if (in_fd >= 0) + close(in_fd); + + STACK_ARRAY_FINISH(transfer_cmds); + + return result; +} diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.h b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.h index dc3af2e29f0..acc4a14836a 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.h +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.h @@ -29,6 +29,8 @@ struct pvr_winsys; struct pvr_winsys_transfer_ctx; struct pvr_winsys_transfer_ctx_create_info; +struct pvr_winsys_transfer_submit_info; +struct vk_sync; /******************************************* Function prototypes @@ -40,4 +42,9 @@ VkResult pvr_srv_winsys_transfer_ctx_create( struct pvr_winsys_transfer_ctx **const ctx_out); void pvr_srv_winsys_transfer_ctx_destroy(struct pvr_winsys_transfer_ctx *ctx); +VkResult pvr_srv_winsys_transfer_submit( + const struct pvr_winsys_transfer_ctx *ctx, + const struct pvr_winsys_transfer_submit_info *submit_info, + struct vk_sync *signal_sync); + #endif /* PVR_SRV_JOB_TRANSFER_H */