xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_compute.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 <limits.h>
27 #include <stddef.h>
28 #include <stdint.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <vulkan/vulkan.h>
32 
33 #include "fw-api/pvr_rogue_fwif.h"
34 #include "fw-api/pvr_rogue_fwif_rf.h"
35 #include "pvr_device_info.h"
36 #include "pvr_private.h"
37 #include "pvr_srv.h"
38 #include "pvr_srv_bridge.h"
39 #include "pvr_srv_job_common.h"
40 #include "pvr_srv_job_compute.h"
41 #include "pvr_srv_sync.h"
42 #include "pvr_winsys.h"
43 #include "util/macros.h"
44 #include "vk_alloc.h"
45 #include "vk_log.h"
46 
47 struct pvr_srv_winsys_compute_ctx {
48    struct pvr_winsys_compute_ctx base;
49 
50    void *handle;
51 
52    int timeline;
53 };
54 
55 #define to_pvr_srv_winsys_compute_ctx(ctx) \
56    container_of(ctx, struct pvr_srv_winsys_compute_ctx, base)
57 
pvr_srv_winsys_compute_ctx_create(struct pvr_winsys * ws,const struct pvr_winsys_compute_ctx_create_info * create_info,struct pvr_winsys_compute_ctx ** const ctx_out)58 VkResult pvr_srv_winsys_compute_ctx_create(
59    struct pvr_winsys *ws,
60    const struct pvr_winsys_compute_ctx_create_info *create_info,
61    struct pvr_winsys_compute_ctx **const ctx_out)
62 {
63    struct rogue_fwif_static_computecontext_state static_state = {
64 		.ctx_switch_regs = {
65 			.cdm_context_pds0 = create_info->static_state.cdm_ctx_store_pds0,
66 			.cdm_context_pds0_b =
67 				create_info->static_state.cdm_ctx_store_pds0_b,
68 			.cdm_context_pds1 = create_info->static_state.cdm_ctx_store_pds1,
69 
70 			.cdm_terminate_pds = create_info->static_state.cdm_ctx_terminate_pds,
71 			.cdm_terminate_pds1 =
72 				create_info->static_state.cdm_ctx_terminate_pds1,
73 
74 			.cdm_resume_pds0 = create_info->static_state.cdm_ctx_resume_pds0,
75 			.cdm_resume_pds0_b = create_info->static_state.cdm_ctx_resume_pds0_b,
76 		},
77 	};
78 
79    struct rogue_fwif_rf_cmd reset_cmd = { 0 };
80 
81    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
82    struct pvr_srv_winsys_compute_ctx *srv_ctx;
83    VkResult result;
84 
85    srv_ctx = vk_alloc(ws->alloc,
86                       sizeof(*srv_ctx),
87                       8U,
88                       VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
89    if (!srv_ctx)
90       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
91 
92    result = pvr_srv_create_timeline(ws->render_fd, &srv_ctx->timeline);
93    if (result != VK_SUCCESS)
94       goto err_free_srv_ctx;
95 
96    /* TODO: Add support for reset framework. Currently we subtract
97     * reset_cmd.regs size from reset_cmd size to only pass empty flags field.
98     */
99    result = pvr_srv_rgx_create_compute_context(
100       ws->render_fd,
101       pvr_srv_from_winsys_priority(create_info->priority),
102       sizeof(reset_cmd) - sizeof(reset_cmd.regs),
103       (uint8_t *)&reset_cmd,
104       srv_ws->server_memctx_data,
105       sizeof(static_state),
106       (uint8_t *)&static_state,
107       0U,
108       RGX_CONTEXT_FLAG_DISABLESLR,
109       0U,
110       UINT_MAX,
111       &srv_ctx->handle);
112    if (result != VK_SUCCESS)
113       goto err_close_timeline;
114 
115    srv_ctx->base.ws = ws;
116 
117    *ctx_out = &srv_ctx->base;
118 
119    return VK_SUCCESS;
120 
121 err_close_timeline:
122    close(srv_ctx->timeline);
123 
124 err_free_srv_ctx:
125    vk_free(ws->alloc, srv_ctx);
126 
127    return result;
128 }
129 
pvr_srv_winsys_compute_ctx_destroy(struct pvr_winsys_compute_ctx * ctx)130 void pvr_srv_winsys_compute_ctx_destroy(struct pvr_winsys_compute_ctx *ctx)
131 {
132    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
133    struct pvr_srv_winsys_compute_ctx *srv_ctx =
134       to_pvr_srv_winsys_compute_ctx(ctx);
135 
136    pvr_srv_rgx_destroy_compute_context(srv_ws->base.render_fd, srv_ctx->handle);
137    close(srv_ctx->timeline);
138    vk_free(srv_ws->base.alloc, srv_ctx);
139 }
140 
141 static uint32_t
pvr_srv_compute_cmd_stream_load(struct rogue_fwif_cmd_compute * const cmd,const uint8_t * const stream,const uint32_t stream_len,const struct pvr_device_info * const dev_info)142 pvr_srv_compute_cmd_stream_load(struct rogue_fwif_cmd_compute *const cmd,
143                                 const uint8_t *const stream,
144                                 const uint32_t stream_len,
145                                 const struct pvr_device_info *const dev_info)
146 {
147    const uint32_t *stream_ptr = (const uint32_t *)stream;
148    struct rogue_fwif_cdm_regs *const regs = &cmd->regs;
149    uint32_t main_stream_len =
150       pvr_csb_unpack((uint64_t *)stream_ptr, KMD_STREAM_HDR).length;
151 
152    stream_ptr += pvr_cmd_length(KMD_STREAM_HDR);
153 
154    regs->tpu_border_colour_table = *(const uint64_t *)stream_ptr;
155    stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_CDM);
156 
157    regs->cdm_ctrl_stream_base = *(const uint64_t *)stream_ptr;
158    stream_ptr += pvr_cmd_length(CR_CDM_CTRL_STREAM_BASE);
159 
160    regs->cdm_context_state_base_addr = *(const uint64_t *)stream_ptr;
161    stream_ptr += pvr_cmd_length(CR_CDM_CONTEXT_STATE_BASE);
162 
163    regs->cdm_resume_pds1 = *stream_ptr;
164    stream_ptr += pvr_cmd_length(CR_CDM_CONTEXT_PDS1);
165 
166    regs->cdm_item = *stream_ptr;
167    stream_ptr += pvr_cmd_length(CR_CDM_ITEM);
168 
169    if (PVR_HAS_FEATURE(dev_info, cluster_grouping)) {
170       regs->compute_cluster = *stream_ptr;
171       stream_ptr += pvr_cmd_length(CR_COMPUTE_CLUSTER);
172    }
173 
174    if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) {
175       cmd->execute_count = *stream_ptr;
176       stream_ptr++;
177    }
178 
179    assert((const uint8_t *)stream_ptr - stream <= stream_len);
180    assert((const uint8_t *)stream_ptr - stream == main_stream_len);
181 
182    return main_stream_len;
183 }
184 
pvr_srv_compute_cmd_ext_stream_load(struct rogue_fwif_cmd_compute * const cmd,const uint8_t * const stream,const uint32_t stream_len,const uint32_t ext_stream_offset,const struct pvr_device_info * const dev_info)185 static void pvr_srv_compute_cmd_ext_stream_load(
186    struct rogue_fwif_cmd_compute *const cmd,
187    const uint8_t *const stream,
188    const uint32_t stream_len,
189    const uint32_t ext_stream_offset,
190    const struct pvr_device_info *const dev_info)
191 {
192    const uint32_t *ext_stream_ptr =
193       (const uint32_t *)((uint8_t *)stream + ext_stream_offset);
194    struct rogue_fwif_cdm_regs *const regs = &cmd->regs;
195 
196    struct PVRX(KMD_STREAM_EXTHDR_COMPUTE0) header0;
197 
198    header0 = pvr_csb_unpack(ext_stream_ptr, KMD_STREAM_EXTHDR_COMPUTE0);
199    ext_stream_ptr += pvr_cmd_length(KMD_STREAM_EXTHDR_COMPUTE0);
200 
201    assert(PVR_HAS_QUIRK(dev_info, 49927) == header0.has_brn49927);
202    if (header0.has_brn49927) {
203       regs->tpu = *ext_stream_ptr;
204       ext_stream_ptr += pvr_cmd_length(CR_TPU);
205    }
206 
207    assert((const uint8_t *)ext_stream_ptr - stream == stream_len);
208 }
209 
pvr_srv_compute_cmd_init(const struct pvr_winsys_compute_submit_info * submit_info,struct rogue_fwif_cmd_compute * cmd,const struct pvr_device_info * const dev_info)210 static void pvr_srv_compute_cmd_init(
211    const struct pvr_winsys_compute_submit_info *submit_info,
212    struct rogue_fwif_cmd_compute *cmd,
213    const struct pvr_device_info *const dev_info)
214 {
215    uint32_t ext_stream_offset;
216 
217    memset(cmd, 0, sizeof(*cmd));
218 
219    cmd->cmn.frame_num = submit_info->frame_num;
220 
221    ext_stream_offset =
222       pvr_srv_compute_cmd_stream_load(cmd,
223                                       submit_info->fw_stream,
224                                       submit_info->fw_stream_len,
225                                       dev_info);
226 
227    if (ext_stream_offset < submit_info->fw_stream_len) {
228       pvr_srv_compute_cmd_ext_stream_load(cmd,
229                                           submit_info->fw_stream,
230                                           submit_info->fw_stream_len,
231                                           ext_stream_offset,
232                                           dev_info);
233    }
234 
235    if (submit_info->flags.prevent_all_overlap)
236       cmd->flags |= ROGUE_FWIF_COMPUTE_FLAG_PREVENT_ALL_OVERLAP;
237 
238    if (submit_info->flags.use_single_core)
239       cmd->flags |= ROGUE_FWIF_COMPUTE_FLAG_SINGLE_CORE;
240 }
241 
pvr_srv_winsys_compute_submit(const struct pvr_winsys_compute_ctx * ctx,const struct pvr_winsys_compute_submit_info * submit_info,const struct pvr_device_info * const dev_info,struct vk_sync * signal_sync)242 VkResult pvr_srv_winsys_compute_submit(
243    const struct pvr_winsys_compute_ctx *ctx,
244    const struct pvr_winsys_compute_submit_info *submit_info,
245    const struct pvr_device_info *const dev_info,
246    struct vk_sync *signal_sync)
247 {
248    const struct pvr_srv_winsys_compute_ctx *srv_ctx =
249       to_pvr_srv_winsys_compute_ctx(ctx);
250    const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
251    struct rogue_fwif_cmd_compute compute_cmd;
252    struct pvr_srv_sync *srv_signal_sync;
253    VkResult result;
254    int in_fd = -1;
255    int fence;
256 
257    pvr_srv_compute_cmd_init(submit_info, &compute_cmd, dev_info);
258 
259    if (submit_info->wait) {
260       struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->wait);
261 
262       if (srv_wait_sync->fd >= 0) {
263          in_fd = dup(srv_wait_sync->fd);
264          if (in_fd == -1) {
265             return vk_errorf(NULL,
266                              VK_ERROR_OUT_OF_HOST_MEMORY,
267                              "dup called on wait sync failed, Errno: %s",
268                              strerror(errno));
269          }
270       }
271    }
272 
273    do {
274       result = pvr_srv_rgx_kick_compute2(srv_ws->base.render_fd,
275                                          srv_ctx->handle,
276                                          0U,
277                                          NULL,
278                                          NULL,
279                                          NULL,
280                                          in_fd,
281                                          srv_ctx->timeline,
282                                          sizeof(compute_cmd),
283                                          (uint8_t *)&compute_cmd,
284                                          submit_info->job_num,
285                                          0,
286                                          NULL,
287                                          NULL,
288                                          0U,
289                                          0U,
290                                          0U,
291                                          0U,
292                                          "COMPUTE",
293                                          &fence);
294    } while (result == VK_NOT_READY);
295 
296    if (result != VK_SUCCESS)
297       goto end_close_in_fd;
298 
299    if (signal_sync) {
300       srv_signal_sync = to_srv_sync(signal_sync);
301       pvr_srv_set_sync_payload(srv_signal_sync, fence);
302    } else if (fence != -1) {
303       close(fence);
304    }
305 
306 end_close_in_fd:
307    if (in_fd >= 0)
308       close(in_fd);
309 
310    return result;
311 }
312