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