xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_transfer.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 <errno.h>
25 #include <fcntl.h>
26 #include <stddef.h>
27 #include <stdint.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <vulkan/vulkan.h>
31 
32 #include "fw-api/pvr_rogue_fwif.h"
33 #include "fw-api/pvr_rogue_fwif_rf.h"
34 #include "pvr_device_info.h"
35 #include "pvr_private.h"
36 #include "pvr_srv.h"
37 #include "pvr_srv_bridge.h"
38 #include "pvr_srv_job_common.h"
39 #include "pvr_srv_job_transfer.h"
40 #include "pvr_srv_sync.h"
41 #include "pvr_winsys.h"
42 #include "util/macros.h"
43 #include "vk_alloc.h"
44 #include "vk_log.h"
45 #include "vk_util.h"
46 
47 #define PVR_SRV_TRANSFER_CONTEXT_INITIAL_CCB_SIZE_LOG2 16U
48 #define PVR_SRV_TRANSFER_CONTEXT_MAX_CCB_SIZE_LOG2 0U
49 
50 struct pvr_srv_winsys_transfer_ctx {
51    struct pvr_winsys_transfer_ctx base;
52 
53    void *handle;
54 
55    int timeline_3d;
56 };
57 
58 #define to_pvr_srv_winsys_transfer_ctx(ctx) \
59    container_of(ctx, struct pvr_srv_winsys_transfer_ctx, base)
60 
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)61 VkResult pvr_srv_winsys_transfer_ctx_create(
62    struct pvr_winsys *ws,
63    const struct pvr_winsys_transfer_ctx_create_info *create_info,
64    struct pvr_winsys_transfer_ctx **const ctx_out)
65 {
66    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
67    struct pvr_srv_winsys_transfer_ctx *srv_ctx;
68    struct rogue_fwif_rf_cmd reset_cmd = { 0 };
69    VkResult result;
70 
71    /* First 2 U8s are 2d work load related, and the last 2 are 3d workload
72     * related.
73     */
74    const uint32_t packed_ccb_size =
75       PVR_U8888_TO_U32(PVR_SRV_TRANSFER_CONTEXT_INITIAL_CCB_SIZE_LOG2,
76                        PVR_SRV_TRANSFER_CONTEXT_MAX_CCB_SIZE_LOG2,
77                        PVR_SRV_TRANSFER_CONTEXT_INITIAL_CCB_SIZE_LOG2,
78                        PVR_SRV_TRANSFER_CONTEXT_MAX_CCB_SIZE_LOG2);
79 
80    srv_ctx = vk_alloc(ws->alloc,
81                       sizeof(*srv_ctx),
82                       8U,
83                       VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
84    if (!srv_ctx)
85       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
86 
87    result = pvr_srv_create_timeline(ws->render_fd, &srv_ctx->timeline_3d);
88    if (result != VK_SUCCESS)
89       goto err_free_srv_ctx;
90 
91    /* TODO: Add support for reset framework. Currently we subtract
92     * reset_cmd.regs size from reset_cmd size to only pass empty flags field.
93     */
94    result = pvr_srv_rgx_create_transfer_context(
95       ws->render_fd,
96       pvr_srv_from_winsys_priority(create_info->priority),
97       sizeof(reset_cmd) - sizeof(reset_cmd.regs),
98       (uint8_t *)&reset_cmd,
99       srv_ws->server_memctx_data,
100       packed_ccb_size,
101       RGX_CONTEXT_FLAG_DISABLESLR,
102       0U,
103       NULL,
104       NULL,
105       &srv_ctx->handle);
106    if (result != VK_SUCCESS)
107       goto err_close_timeline;
108 
109    srv_ctx->base.ws = ws;
110    *ctx_out = &srv_ctx->base;
111 
112    return VK_SUCCESS;
113 
114 err_close_timeline:
115    close(srv_ctx->timeline_3d);
116 
117 err_free_srv_ctx:
118    vk_free(ws->alloc, srv_ctx);
119 
120    return result;
121 }
122 
pvr_srv_winsys_transfer_ctx_destroy(struct pvr_winsys_transfer_ctx * ctx)123 void pvr_srv_winsys_transfer_ctx_destroy(struct pvr_winsys_transfer_ctx *ctx)
124 {
125    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
126    struct pvr_srv_winsys_transfer_ctx *srv_ctx =
127       to_pvr_srv_winsys_transfer_ctx(ctx);
128 
129    pvr_srv_rgx_destroy_transfer_context(srv_ws->base.render_fd,
130                                         srv_ctx->handle);
131    close(srv_ctx->timeline_3d);
132    vk_free(srv_ws->base.alloc, srv_ctx);
133 }
134 
135 static void
pvr_srv_transfer_cmd_stream_load(struct rogue_fwif_cmd_transfer * const cmd,const uint8_t * const stream,const uint32_t stream_len,const struct pvr_device_info * const dev_info)136 pvr_srv_transfer_cmd_stream_load(struct rogue_fwif_cmd_transfer *const cmd,
137                                  const uint8_t *const stream,
138                                  const uint32_t stream_len,
139                                  const struct pvr_device_info *const dev_info)
140 {
141    const uint32_t *stream_ptr = (const uint32_t *)stream;
142    struct rogue_fwif_transfer_regs *const regs = &cmd->regs;
143    uint32_t main_stream_len =
144       pvr_csb_unpack((uint64_t *)stream_ptr, KMD_STREAM_HDR).length;
145 
146    stream_ptr += pvr_cmd_length(KMD_STREAM_HDR);
147 
148    regs->pds_bgnd0_base = *(uint64_t *)stream_ptr;
149    stream_ptr += pvr_cmd_length(CR_PDS_BGRND0_BASE);
150 
151    regs->pds_bgnd1_base = *(uint64_t *)stream_ptr;
152    stream_ptr += pvr_cmd_length(CR_PDS_BGRND1_BASE);
153 
154    regs->pds_bgnd3_sizeinfo = *(uint64_t *)stream_ptr;
155    stream_ptr += pvr_cmd_length(CR_PDS_BGRND3_SIZEINFO);
156 
157    regs->isp_mtile_base = *(uint64_t *)stream_ptr;
158    stream_ptr += pvr_cmd_length(CR_ISP_MTILE_BASE);
159 
160    STATIC_ASSERT(ARRAY_SIZE(regs->pbe_wordx_mrty) == 9U);
161    STATIC_ASSERT(sizeof(regs->pbe_wordx_mrty[0]) == sizeof(uint64_t));
162    memcpy(regs->pbe_wordx_mrty, stream_ptr, sizeof(regs->pbe_wordx_mrty));
163    stream_ptr += 9U * 2U;
164 
165    regs->isp_bgobjvals = *stream_ptr;
166    stream_ptr += pvr_cmd_length(CR_ISP_BGOBJVALS);
167 
168    regs->usc_pixel_output_ctrl = *stream_ptr;
169    stream_ptr += pvr_cmd_length(CR_USC_PIXEL_OUTPUT_CTRL);
170 
171    regs->usc_clear_register0 = *stream_ptr;
172    stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER);
173 
174    regs->usc_clear_register1 = *stream_ptr;
175    stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER);
176 
177    regs->usc_clear_register2 = *stream_ptr;
178    stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER);
179 
180    regs->usc_clear_register3 = *stream_ptr;
181    stream_ptr += pvr_cmd_length(CR_USC_CLEAR_REGISTER);
182 
183    regs->isp_mtile_size = *stream_ptr;
184    stream_ptr += pvr_cmd_length(CR_ISP_MTILE_SIZE);
185 
186    regs->isp_render_origin = *stream_ptr;
187    stream_ptr += pvr_cmd_length(CR_ISP_RENDER_ORIGIN);
188 
189    regs->isp_ctl = *stream_ptr;
190    stream_ptr += pvr_cmd_length(CR_ISP_CTL);
191 
192    regs->isp_aa = *stream_ptr;
193    stream_ptr += pvr_cmd_length(CR_ISP_AA);
194 
195    regs->event_pixel_pds_info = *stream_ptr;
196    stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_INFO);
197 
198    regs->event_pixel_pds_code = *stream_ptr;
199    stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_CODE);
200 
201    regs->event_pixel_pds_data = *stream_ptr;
202    stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_DATA);
203 
204    regs->isp_render = *stream_ptr;
205    stream_ptr += pvr_cmd_length(CR_ISP_RENDER);
206 
207    regs->isp_rgn = *stream_ptr;
208    stream_ptr++;
209 
210    if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) {
211       regs->frag_screen = *stream_ptr;
212       stream_ptr++;
213    }
214 
215    assert((const uint8_t *)stream_ptr - stream == stream_len);
216    assert((const uint8_t *)stream_ptr - stream == main_stream_len);
217 }
218 
pvr_srv_transfer_cmds_init(const struct pvr_winsys_transfer_submit_info * submit_info,struct rogue_fwif_cmd_transfer * cmds,uint32_t cmd_count,const struct pvr_device_info * const dev_info)219 static void pvr_srv_transfer_cmds_init(
220    const struct pvr_winsys_transfer_submit_info *submit_info,
221    struct rogue_fwif_cmd_transfer *cmds,
222    uint32_t cmd_count,
223    const struct pvr_device_info *const dev_info)
224 {
225    memset(cmds, 0, sizeof(*cmds) * submit_info->cmd_count);
226 
227    for (uint32_t i = 0; i < cmd_count; i++) {
228       const struct pvr_winsys_transfer_cmd *submit_cmd = &submit_info->cmds[i];
229       struct rogue_fwif_cmd_transfer *cmd = &cmds[i];
230 
231       cmd->cmn.frame_num = submit_info->frame_num;
232 
233       pvr_srv_transfer_cmd_stream_load(cmd,
234                                        submit_cmd->fw_stream,
235                                        submit_cmd->fw_stream_len,
236                                        dev_info);
237 
238       if (submit_info->cmds[i].flags.use_single_core)
239          cmd->flags |= ROGUE_FWIF_CMDTRANSFER_SINGLE_CORE;
240    }
241 }
242 
pvr_srv_winsys_transfer_submit(const struct pvr_winsys_transfer_ctx * ctx,const struct pvr_winsys_transfer_submit_info * submit_info,const struct pvr_device_info * const dev_info,struct vk_sync * signal_sync)243 VkResult pvr_srv_winsys_transfer_submit(
244    const struct pvr_winsys_transfer_ctx *ctx,
245    const struct pvr_winsys_transfer_submit_info *submit_info,
246    const struct pvr_device_info *const dev_info,
247    struct vk_sync *signal_sync)
248 {
249    const struct pvr_srv_winsys_transfer_ctx *srv_ctx =
250       to_pvr_srv_winsys_transfer_ctx(ctx);
251    const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
252 
253    struct rogue_fwif_cmd_transfer
254       *cmds_ptr_arr[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT];
255    uint32_t *update_sync_offsets[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
256    uint32_t client_update_count[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
257    void **update_ufo_syc_prims[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
258    uint32_t *update_values[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
259    uint32_t cmd_flags[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT] = { 0 };
260    uint32_t cmd_sizes[PVR_TRANSFER_MAX_PREPARES_PER_SUBMIT];
261 
262    struct pvr_srv_sync *srv_signal_sync;
263    uint32_t job_num;
264    VkResult result;
265    int in_fd = -1;
266    int fence;
267 
268    STACK_ARRAY(struct rogue_fwif_cmd_transfer,
269                transfer_cmds,
270                submit_info->cmd_count);
271    if (!transfer_cmds)
272       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
273 
274    pvr_srv_transfer_cmds_init(submit_info,
275                               transfer_cmds,
276                               submit_info->cmd_count,
277                               dev_info);
278 
279    for (uint32_t i = 0U; i < submit_info->cmd_count; i++) {
280       cmd_sizes[i] = sizeof(**cmds_ptr_arr);
281       cmds_ptr_arr[i] = &transfer_cmds[i];
282    }
283 
284    if (submit_info->wait) {
285       struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->wait);
286 
287       if (srv_wait_sync->fd >= 0) {
288          in_fd = dup(srv_wait_sync->fd);
289          if (in_fd == -1) {
290             return vk_errorf(NULL,
291                              VK_ERROR_OUT_OF_HOST_MEMORY,
292                              "dup called on wait sync failed, Errno: %s",
293                              strerror(errno));
294          }
295       }
296    }
297 
298    job_num = submit_info->job_num;
299 
300    do {
301       result = pvr_srv_rgx_submit_transfer2(srv_ws->base.render_fd,
302                                             srv_ctx->handle,
303                                             submit_info->cmd_count,
304                                             client_update_count,
305                                             update_ufo_syc_prims,
306                                             update_sync_offsets,
307                                             update_values,
308                                             in_fd,
309                                             -1,
310                                             srv_ctx->timeline_3d,
311                                             "TRANSFER",
312                                             cmd_sizes,
313                                             (uint8_t **)cmds_ptr_arr,
314                                             cmd_flags,
315                                             job_num,
316                                             0U,
317                                             NULL,
318                                             NULL,
319                                             NULL,
320                                             &fence);
321    } while (result == VK_NOT_READY);
322 
323    if (result != VK_SUCCESS)
324       goto end_close_in_fd;
325 
326    if (signal_sync) {
327       srv_signal_sync = to_srv_sync(signal_sync);
328       pvr_srv_set_sync_payload(srv_signal_sync, fence);
329    } else if (fence != -1) {
330       close(fence);
331    }
332 
333 end_close_in_fd:
334    if (in_fd >= 0)
335       close(in_fd);
336 
337    STACK_ARRAY_FINISH(transfer_cmds);
338 
339    return result;
340 }
341