• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2022 Imagination Technologies Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23 
24 #include <fcntl.h>
25 #include <stddef.h>
26 #include <stdint.h>
27 #include <unistd.h>
28 #include <vulkan/vulkan.h>
29 
30 #include "fw-api/pvr_rogue_fwif.h"
31 #include "fw-api/pvr_rogue_fwif_rf.h"
32 #include "pvr_private.h"
33 #include "pvr_srv.h"
34 #include "pvr_srv_bridge.h"
35 #include "pvr_srv_job_common.h"
36 #include "pvr_srv_job_transfer.h"
37 #include "pvr_srv_sync.h"
38 #include "pvr_winsys.h"
39 #include "util/libsync.h"
40 #include "util/macros.h"
41 #include "vk_alloc.h"
42 #include "vk_log.h"
43 #include "vk_util.h"
44 
45 #define PVR_SRV_TRANSFER_CONTEXT_INITIAL_CCB_SIZE_LOG2 16U
46 #define PVR_SRV_TRANSFER_CONTEXT_MAX_CCB_SIZE_LOG2 0U
47 
48 struct pvr_srv_winsys_transfer_ctx {
49    struct pvr_winsys_transfer_ctx base;
50 
51    void *handle;
52 
53    int timeline_3d;
54 };
55 
56 #define to_pvr_srv_winsys_transfer_ctx(ctx) \
57    container_of(ctx, struct pvr_srv_winsys_transfer_ctx, base)
58 
pvr_srv_winsys_transfer_ctx_create(struct pvr_winsys * ws,const struct pvr_winsys_transfer_ctx_create_info * create_info,struct pvr_winsys_transfer_ctx ** const ctx_out)59 VkResult pvr_srv_winsys_transfer_ctx_create(
60    struct pvr_winsys *ws,
61    const struct pvr_winsys_transfer_ctx_create_info *create_info,
62    struct pvr_winsys_transfer_ctx **const ctx_out)
63 {
64    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
65    struct pvr_srv_winsys_transfer_ctx *srv_ctx;
66    struct rogue_fwif_rf_cmd reset_cmd = { 0 };
67    VkResult result;
68 
69    /* First 2 U8s are 2d work load related, and the last 2 are 3d workload
70     * related.
71     */
72    const uint32_t packed_ccb_size =
73       PVR_U8888_TO_U32(PVR_SRV_TRANSFER_CONTEXT_INITIAL_CCB_SIZE_LOG2,
74                        PVR_SRV_TRANSFER_CONTEXT_MAX_CCB_SIZE_LOG2,
75                        PVR_SRV_TRANSFER_CONTEXT_INITIAL_CCB_SIZE_LOG2,
76                        PVR_SRV_TRANSFER_CONTEXT_MAX_CCB_SIZE_LOG2);
77 
78    srv_ctx = vk_alloc(srv_ws->alloc,
79                       sizeof(*srv_ctx),
80                       8U,
81                       VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
82    if (!srv_ctx)
83       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
84 
85    result = pvr_srv_create_timeline(srv_ws->render_fd, &srv_ctx->timeline_3d);
86    if (result != VK_SUCCESS)
87       goto err_free_srv_ctx;
88 
89    /* TODO: Add support for reset framework. Currently we subtract
90     * reset_cmd.regs size from reset_cmd size to only pass empty flags field.
91     */
92    result = pvr_srv_rgx_create_transfer_context(
93       srv_ws->render_fd,
94       pvr_srv_from_winsys_priority(create_info->priority),
95       sizeof(reset_cmd) - sizeof(reset_cmd.regs),
96       (uint8_t *)&reset_cmd,
97       srv_ws->server_memctx_data,
98       packed_ccb_size,
99       RGX_CONTEXT_FLAG_DISABLESLR,
100       0U,
101       NULL,
102       NULL,
103       &srv_ctx->handle);
104    if (result != VK_SUCCESS)
105       goto err_close_timeline;
106 
107    srv_ctx->base.ws = ws;
108    *ctx_out = &srv_ctx->base;
109 
110    return VK_SUCCESS;
111 
112 err_close_timeline:
113    close(srv_ctx->timeline_3d);
114 
115 err_free_srv_ctx:
116    vk_free(srv_ws->alloc, srv_ctx);
117 
118    return result;
119 }
120 
pvr_srv_winsys_transfer_ctx_destroy(struct pvr_winsys_transfer_ctx * ctx)121 void pvr_srv_winsys_transfer_ctx_destroy(struct pvr_winsys_transfer_ctx *ctx)
122 {
123    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
124    struct pvr_srv_winsys_transfer_ctx *srv_ctx =
125       to_pvr_srv_winsys_transfer_ctx(ctx);
126 
127    pvr_srv_rgx_destroy_transfer_context(srv_ws->render_fd, srv_ctx->handle);
128    close(srv_ctx->timeline_3d);
129    vk_free(srv_ws->alloc, srv_ctx);
130 }
131 
pvr_srv_transfer_cmds_init(const struct pvr_winsys_transfer_submit_info * submit_info,struct rogue_fwif_cmd_transfer * cmds,uint32_t cmd_count)132 static void pvr_srv_transfer_cmds_init(
133    const struct pvr_winsys_transfer_submit_info *submit_info,
134    struct rogue_fwif_cmd_transfer *cmds,
135    uint32_t cmd_count)
136 {
137    memset(cmds, 0, sizeof(*cmds) * submit_info->cmd_count);
138 
139    for (uint32_t i = 0; i < cmd_count; i++) {
140       struct rogue_fwif_transfer_regs *fw_regs = &cmds[i].regs;
141 
142       cmds[i].cmn.frame_num = submit_info->frame_num;
143 
144       fw_regs->isp_bgobjvals = submit_info->cmds[i].regs.isp_bgobjvals;
145       fw_regs->usc_pixel_output_ctrl =
146          submit_info->cmds[i].regs.usc_pixel_output_ctrl;
147       fw_regs->usc_clear_register0 =
148          submit_info->cmds[i].regs.usc_clear_register0;
149       fw_regs->usc_clear_register1 =
150          submit_info->cmds[i].regs.usc_clear_register1;
151       fw_regs->usc_clear_register2 =
152          submit_info->cmds[i].regs.usc_clear_register2;
153       fw_regs->usc_clear_register3 =
154          submit_info->cmds[i].regs.usc_clear_register3;
155       fw_regs->isp_mtile_size = submit_info->cmds[i].regs.isp_mtile_size;
156       fw_regs->isp_render_origin = submit_info->cmds[i].regs.isp_render_origin;
157       fw_regs->isp_ctl = submit_info->cmds[i].regs.isp_ctl;
158       fw_regs->isp_aa = submit_info->cmds[i].regs.isp_aa;
159       fw_regs->event_pixel_pds_info =
160          submit_info->cmds[i].regs.event_pixel_pds_info;
161       fw_regs->event_pixel_pds_code =
162          submit_info->cmds[i].regs.event_pixel_pds_code;
163       fw_regs->event_pixel_pds_data =
164          submit_info->cmds[i].regs.event_pixel_pds_data;
165       fw_regs->isp_render = submit_info->cmds[i].regs.isp_render;
166       fw_regs->isp_rgn = submit_info->cmds[i].regs.isp_rgn;
167       fw_regs->pds_bgnd0_base = submit_info->cmds[i].regs.pds_bgnd0_base;
168       fw_regs->pds_bgnd1_base = submit_info->cmds[i].regs.pds_bgnd1_base;
169       fw_regs->pds_bgnd3_sizeinfo =
170          submit_info->cmds[i].regs.pds_bgnd3_sizeinfo;
171       fw_regs->isp_mtile_base = submit_info->cmds[i].regs.isp_mtile_base;
172 
173       STATIC_ASSERT(ARRAY_SIZE(fw_regs->pbe_wordx_mrty) ==
174                     ARRAY_SIZE(submit_info->cmds[i].regs.pbe_wordx_mrty));
175       for (uint32_t j = 0; j < ARRAY_SIZE(fw_regs->pbe_wordx_mrty); j++) {
176          fw_regs->pbe_wordx_mrty[j] =
177             submit_info->cmds[i].regs.pbe_wordx_mrty[j];
178       }
179    }
180 }
181 
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)182 VkResult pvr_srv_winsys_transfer_submit(
183    const struct pvr_winsys_transfer_ctx *ctx,
184    const struct pvr_winsys_transfer_submit_info *submit_info,
185    struct vk_sync *signal_sync)
186 {
187    const struct pvr_srv_winsys_transfer_ctx *srv_ctx =
188       to_pvr_srv_winsys_transfer_ctx(ctx);
189    const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
190 
191    struct rogue_fwif_cmd_transfer
192       *cmds_ptr_arr[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT];
193    uint32_t *update_sync_offsets[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
194    uint32_t client_update_count[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
195    void **update_ufo_syc_prims[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
196    uint32_t *update_values[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
197    uint32_t cmd_sizes[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT];
198    uint32_t cmd_flags[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT];
199 
200    struct pvr_srv_sync *srv_signal_sync;
201    uint32_t job_num;
202    VkResult result;
203    int in_fd = -1;
204    int fence;
205 
206    STACK_ARRAY(struct rogue_fwif_cmd_transfer,
207                transfer_cmds,
208                submit_info->cmd_count);
209    if (!transfer_cmds)
210       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
211 
212    pvr_srv_transfer_cmds_init(submit_info,
213                               transfer_cmds,
214                               submit_info->cmd_count);
215 
216    for (uint32_t i = 0U; i < submit_info->cmd_count; i++) {
217       cmd_sizes[i] = sizeof(**cmds_ptr_arr);
218 
219       cmd_flags[i] = 0;
220       if (submit_info->cmds[i].flags & PVR_WINSYS_TRANSFER_FLAG_START)
221          cmd_flags[i] |= PVR_TRANSFER_PREP_FLAGS_START;
222 
223       if (submit_info->cmds[i].flags & PVR_WINSYS_TRANSFER_FLAG_END)
224          cmd_flags[i] |= PVR_TRANSFER_PREP_FLAGS_END;
225 
226       cmds_ptr_arr[i] = &transfer_cmds[i];
227    }
228 
229    for (uint32_t i = 0U; i < submit_info->wait_count; i++) {
230       struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->waits[i]);
231       int ret;
232 
233       if (!submit_info->waits[i] || srv_wait_sync->fd < 0)
234          continue;
235 
236       if (submit_info->stage_flags[i] & PVR_PIPELINE_STAGE_TRANSFER_BIT) {
237          ret = sync_accumulate("", &in_fd, srv_wait_sync->fd);
238          if (ret) {
239             result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
240             goto err_close_in_fd;
241          }
242 
243          submit_info->stage_flags[i] &= ~PVR_PIPELINE_STAGE_TRANSFER_BIT;
244       }
245    }
246 
247    job_num = submit_info->job_num;
248 
249    do {
250       result = pvr_srv_rgx_submit_transfer2(srv_ws->render_fd,
251                                             srv_ctx->handle,
252                                             submit_info->cmd_count,
253                                             client_update_count,
254                                             update_ufo_syc_prims,
255                                             update_sync_offsets,
256                                             update_values,
257                                             in_fd,
258                                             -1,
259                                             srv_ctx->timeline_3d,
260                                             "TRANSFER",
261                                             cmd_sizes,
262                                             (uint8_t **)cmds_ptr_arr,
263                                             cmd_flags,
264                                             job_num,
265                                             /* TODO: Add sync PMR support. */
266                                             0U,
267                                             NULL,
268                                             NULL,
269                                             NULL,
270                                             &fence);
271    } while (result == VK_NOT_READY);
272 
273    if (result != VK_SUCCESS)
274       goto err_close_in_fd;
275 
276    if (signal_sync) {
277       srv_signal_sync = to_srv_sync(signal_sync);
278       pvr_srv_set_sync_payload(srv_signal_sync, fence);
279    } else if (fence != -1) {
280       close(fence);
281    }
282 
283    STACK_ARRAY_FINISH(transfer_cmds);
284 
285    return VK_SUCCESS;
286 
287 err_close_in_fd:
288    if (in_fd >= 0)
289       close(in_fd);
290 
291    STACK_ARRAY_FINISH(transfer_cmds);
292 
293    return result;
294 }
295