• 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 <assert.h>
25 #include <fcntl.h>
26 #include <limits.h>
27 #include <stdbool.h>
28 #include <stddef.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <vulkan/vulkan.h>
33 
34 #include "fw-api/pvr_rogue_fwif.h"
35 #include "fw-api/pvr_rogue_fwif_rf.h"
36 #include "pvr_private.h"
37 #include "pvr_srv.h"
38 #include "pvr_srv_bo.h"
39 #include "pvr_srv_bridge.h"
40 #include "pvr_srv_job_common.h"
41 #include "pvr_srv_job_render.h"
42 #include "pvr_srv_sync.h"
43 #include "pvr_types.h"
44 #include "pvr_winsys.h"
45 #include "util/libsync.h"
46 #include "util/log.h"
47 #include "util/macros.h"
48 #include "vk_alloc.h"
49 #include "vk_log.h"
50 #include "vk_util.h"
51 
52 struct pvr_srv_winsys_free_list {
53    struct pvr_winsys_free_list base;
54 
55    void *handle;
56 
57    struct pvr_srv_winsys_free_list *parent;
58 };
59 
60 #define to_pvr_srv_winsys_free_list(free_list) \
61    container_of(free_list, struct pvr_srv_winsys_free_list, base)
62 
63 struct pvr_srv_winsys_rt_dataset {
64    struct pvr_winsys_rt_dataset base;
65 
66    struct {
67       void *handle;
68       struct pvr_srv_sync_prim *sync_prim;
69    } rt_datas[ROGUE_FWIF_NUM_RTDATAS];
70 };
71 
72 #define to_pvr_srv_winsys_rt_dataset(rt_dataset) \
73    container_of(rt_dataset, struct pvr_srv_winsys_rt_dataset, base)
74 
75 struct pvr_srv_winsys_render_ctx {
76    struct pvr_winsys_render_ctx base;
77 
78    /* Handle to kernel context. */
79    void *handle;
80 
81    int timeline_geom;
82    int timeline_frag;
83 };
84 
85 #define to_pvr_srv_winsys_render_ctx(ctx) \
86    container_of(ctx, struct pvr_srv_winsys_render_ctx, base)
87 
pvr_srv_winsys_free_list_create(struct pvr_winsys * ws,struct pvr_winsys_vma * free_list_vma,uint32_t initial_num_pages,uint32_t max_num_pages,uint32_t grow_num_pages,uint32_t grow_threshold,struct pvr_winsys_free_list * parent_free_list,struct pvr_winsys_free_list ** const free_list_out)88 VkResult pvr_srv_winsys_free_list_create(
89    struct pvr_winsys *ws,
90    struct pvr_winsys_vma *free_list_vma,
91    uint32_t initial_num_pages,
92    uint32_t max_num_pages,
93    uint32_t grow_num_pages,
94    uint32_t grow_threshold,
95    struct pvr_winsys_free_list *parent_free_list,
96    struct pvr_winsys_free_list **const free_list_out)
97 {
98    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
99    struct pvr_srv_winsys_bo *srv_free_list_bo =
100       to_pvr_srv_winsys_bo(free_list_vma->bo);
101    struct pvr_srv_winsys_free_list *srv_free_list;
102    void *parent_handle;
103    VkResult result;
104 
105    srv_free_list = vk_zalloc(srv_ws->alloc,
106                              sizeof(*srv_free_list),
107                              8,
108                              VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
109    if (!srv_free_list)
110       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
111 
112    if (parent_free_list) {
113       srv_free_list->parent = to_pvr_srv_winsys_free_list(parent_free_list);
114       parent_handle = srv_free_list->parent->handle;
115    } else {
116       srv_free_list->parent = NULL;
117       parent_handle = NULL;
118    }
119 
120    result = pvr_srv_rgx_create_free_list(srv_ws->render_fd,
121                                          srv_ws->server_memctx_data,
122                                          max_num_pages,
123                                          initial_num_pages,
124                                          grow_num_pages,
125                                          grow_threshold,
126                                          parent_handle,
127 #if defined(DEBUG)
128                                          PVR_SRV_TRUE /* free_list_check */,
129 #else
130                                          PVR_SRV_FALSE /* free_list_check */,
131 #endif
132                                          free_list_vma->dev_addr,
133                                          srv_free_list_bo->pmr,
134                                          0 /* pmr_offset */,
135                                          &srv_free_list->handle);
136    if (result != VK_SUCCESS)
137       goto err_vk_free_srv_free_list;
138 
139    srv_free_list->base.ws = ws;
140 
141    *free_list_out = &srv_free_list->base;
142 
143    return VK_SUCCESS;
144 
145 err_vk_free_srv_free_list:
146    vk_free(srv_ws->alloc, srv_free_list);
147 
148    return result;
149 }
150 
pvr_srv_winsys_free_list_destroy(struct pvr_winsys_free_list * free_list)151 void pvr_srv_winsys_free_list_destroy(struct pvr_winsys_free_list *free_list)
152 {
153    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(free_list->ws);
154    struct pvr_srv_winsys_free_list *srv_free_list =
155       to_pvr_srv_winsys_free_list(free_list);
156 
157    pvr_srv_rgx_destroy_free_list(srv_ws->render_fd, srv_free_list->handle);
158    vk_free(srv_ws->alloc, srv_free_list);
159 }
160 
pvr_srv_render_target_dataset_create(struct pvr_winsys * ws,const struct pvr_winsys_rt_dataset_create_info * create_info,struct pvr_winsys_rt_dataset ** const rt_dataset_out)161 VkResult pvr_srv_render_target_dataset_create(
162    struct pvr_winsys *ws,
163    const struct pvr_winsys_rt_dataset_create_info *create_info,
164    struct pvr_winsys_rt_dataset **const rt_dataset_out)
165 {
166    const pvr_dev_addr_t macrotile_addrs[ROGUE_FWIF_NUM_RTDATAS] = {
167       [0] = create_info->rt_datas[0].macrotile_array_dev_addr,
168       [1] = create_info->rt_datas[1].macrotile_array_dev_addr,
169    };
170    const pvr_dev_addr_t pm_mlist_addrs[ROGUE_FWIF_NUM_RTDATAS] = {
171       [0] = create_info->rt_datas[0].pm_mlist_dev_addr,
172       [1] = create_info->rt_datas[1].pm_mlist_dev_addr,
173    };
174    const pvr_dev_addr_t rgn_header_addrs[ROGUE_FWIF_NUM_RTDATAS] = {
175       [0] = create_info->rt_datas[0].rgn_header_dev_addr,
176       [1] = create_info->rt_datas[1].rgn_header_dev_addr,
177    };
178 
179    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
180    struct pvr_srv_winsys_free_list *srv_local_free_list =
181       to_pvr_srv_winsys_free_list(create_info->local_free_list);
182    void *free_lists[ROGUE_FW_MAX_FREELISTS] = { NULL };
183    struct pvr_srv_winsys_rt_dataset *srv_rt_dataset;
184    void *handles[ROGUE_FWIF_NUM_RTDATAS];
185    VkResult result;
186 
187    free_lists[ROGUE_FW_LOCAL_FREELIST] = srv_local_free_list->handle;
188 
189    if (srv_local_free_list->parent) {
190       free_lists[ROGUE_FW_GLOBAL_FREELIST] =
191          srv_local_free_list->parent->handle;
192    }
193 
194    srv_rt_dataset = vk_zalloc(srv_ws->alloc,
195                               sizeof(*srv_rt_dataset),
196                               8,
197                               VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
198    if (!srv_rt_dataset)
199       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
200 
201    /* If greater than 1 we'll have to pass in an array. For now just passing in
202     * the reference.
203     */
204    STATIC_ASSERT(ROGUE_FWIF_NUM_GEOMDATAS == 1);
205    /* If not 2 the arrays used in the bridge call will require updating. */
206    STATIC_ASSERT(ROGUE_FWIF_NUM_RTDATAS == 2);
207 
208    result = pvr_srv_rgx_create_hwrt_dataset(
209       srv_ws->render_fd,
210       create_info->ppp_multi_sample_ctl_y_flipped,
211       create_info->ppp_multi_sample_ctl,
212       macrotile_addrs,
213       pm_mlist_addrs,
214       &create_info->rtc_dev_addr,
215       rgn_header_addrs,
216       &create_info->tpc_dev_addr,
217       &create_info->vheap_table_dev_addr,
218       free_lists,
219       create_info->isp_merge_lower_x,
220       create_info->isp_merge_lower_y,
221       create_info->isp_merge_scale_x,
222       create_info->isp_merge_scale_y,
223       create_info->isp_merge_upper_x,
224       create_info->isp_merge_upper_y,
225       create_info->isp_mtile_size,
226       create_info->mtile_stride,
227       create_info->ppp_screen,
228       create_info->rgn_header_size,
229       create_info->te_aa,
230       create_info->te_mtile1,
231       create_info->te_mtile2,
232       create_info->te_screen,
233       create_info->tpc_size,
234       create_info->tpc_stride,
235       create_info->max_rts,
236       handles);
237    if (result != VK_SUCCESS)
238       goto err_vk_free_srv_rt_dataset;
239 
240    srv_rt_dataset->rt_datas[0].handle = handles[0];
241    srv_rt_dataset->rt_datas[1].handle = handles[1];
242 
243    for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) {
244       srv_rt_dataset->rt_datas[i].sync_prim = pvr_srv_sync_prim_alloc(srv_ws);
245       if (!srv_rt_dataset->rt_datas[i].sync_prim)
246          goto err_srv_sync_prim_free;
247    }
248 
249    srv_rt_dataset->base.ws = ws;
250 
251    *rt_dataset_out = &srv_rt_dataset->base;
252 
253    return VK_SUCCESS;
254 
255 err_srv_sync_prim_free:
256    for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) {
257       pvr_srv_sync_prim_free(srv_rt_dataset->rt_datas[i].sync_prim);
258 
259       if (srv_rt_dataset->rt_datas[i].handle) {
260          pvr_srv_rgx_destroy_hwrt_dataset(srv_ws->render_fd,
261                                           srv_rt_dataset->rt_datas[i].handle);
262       }
263    }
264 
265 err_vk_free_srv_rt_dataset:
266    vk_free(srv_ws->alloc, srv_rt_dataset);
267 
268    return result;
269 }
270 
pvr_srv_render_target_dataset_destroy(struct pvr_winsys_rt_dataset * rt_dataset)271 void pvr_srv_render_target_dataset_destroy(
272    struct pvr_winsys_rt_dataset *rt_dataset)
273 {
274    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(rt_dataset->ws);
275    struct pvr_srv_winsys_rt_dataset *srv_rt_dataset =
276       to_pvr_srv_winsys_rt_dataset(rt_dataset);
277 
278    for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) {
279       pvr_srv_sync_prim_free(srv_rt_dataset->rt_datas[i].sync_prim);
280 
281       if (srv_rt_dataset->rt_datas[i].handle) {
282          pvr_srv_rgx_destroy_hwrt_dataset(srv_ws->render_fd,
283                                           srv_rt_dataset->rt_datas[i].handle);
284       }
285    }
286 
287    vk_free(srv_ws->alloc, srv_rt_dataset);
288 }
289 
pvr_srv_render_ctx_fw_static_state_init(struct pvr_winsys_render_ctx_create_info * create_info,struct rogue_fwif_static_rendercontext_state * static_state)290 static void pvr_srv_render_ctx_fw_static_state_init(
291    struct pvr_winsys_render_ctx_create_info *create_info,
292    struct rogue_fwif_static_rendercontext_state *static_state)
293 {
294    struct pvr_winsys_render_ctx_static_state *ws_static_state =
295       &create_info->static_state;
296    struct rogue_fwif_ta_regs_cswitch *regs =
297       &static_state->ctx_switch_geom_regs[0];
298 
299    memset(static_state, 0, sizeof(*static_state));
300 
301    regs->vdm_context_state_base_addr = ws_static_state->vdm_ctx_state_base_addr;
302    regs->ta_context_state_base_addr = ws_static_state->geom_ctx_state_base_addr;
303 
304    STATIC_ASSERT(ARRAY_SIZE(regs->ta_state) ==
305                  ARRAY_SIZE(ws_static_state->geom_state));
306    for (uint32_t i = 0; i < ARRAY_SIZE(ws_static_state->geom_state); i++) {
307       regs->ta_state[i].vdm_context_store_task0 =
308          ws_static_state->geom_state[i].vdm_ctx_store_task0;
309       regs->ta_state[i].vdm_context_store_task1 =
310          ws_static_state->geom_state[i].vdm_ctx_store_task1;
311       regs->ta_state[i].vdm_context_store_task2 =
312          ws_static_state->geom_state[i].vdm_ctx_store_task2;
313 
314       regs->ta_state[i].vdm_context_resume_task0 =
315          ws_static_state->geom_state[i].vdm_ctx_resume_task0;
316       regs->ta_state[i].vdm_context_resume_task1 =
317          ws_static_state->geom_state[i].vdm_ctx_resume_task1;
318       regs->ta_state[i].vdm_context_resume_task2 =
319          ws_static_state->geom_state[i].vdm_ctx_resume_task2;
320    }
321 }
322 
pvr_srv_winsys_render_ctx_create(struct pvr_winsys * ws,struct pvr_winsys_render_ctx_create_info * create_info,struct pvr_winsys_render_ctx ** const ctx_out)323 VkResult pvr_srv_winsys_render_ctx_create(
324    struct pvr_winsys *ws,
325    struct pvr_winsys_render_ctx_create_info *create_info,
326    struct pvr_winsys_render_ctx **const ctx_out)
327 {
328    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
329    struct rogue_fwif_rf_cmd reset_cmd = { 0 };
330 
331    struct rogue_fwif_static_rendercontext_state static_state;
332    struct pvr_srv_winsys_render_ctx *srv_ctx;
333    const uint32_t call_stack_depth = 1U;
334    VkResult result;
335 
336    srv_ctx = vk_zalloc(srv_ws->alloc,
337                        sizeof(*srv_ctx),
338                        8,
339                        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
340    if (!srv_ctx)
341       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
342 
343    result = pvr_srv_create_timeline(srv_ws->render_fd, &srv_ctx->timeline_geom);
344    if (result != VK_SUCCESS)
345       goto err_free_srv_ctx;
346 
347    result = pvr_srv_create_timeline(srv_ws->render_fd, &srv_ctx->timeline_frag);
348    if (result != VK_SUCCESS)
349       goto err_close_timeline_geom;
350 
351    pvr_srv_render_ctx_fw_static_state_init(create_info, &static_state);
352 
353    /* TODO: Add support for reset framework. Currently we subtract
354     * reset_cmd.regs size from reset_cmd size to only pass empty flags field.
355     */
356    result = pvr_srv_rgx_create_render_context(
357       srv_ws->render_fd,
358       pvr_srv_from_winsys_priority(create_info->priority),
359       create_info->vdm_callstack_addr,
360       call_stack_depth,
361       sizeof(reset_cmd) - sizeof(reset_cmd.regs),
362       (uint8_t *)&reset_cmd,
363       srv_ws->server_memctx_data,
364       sizeof(static_state),
365       (uint8_t *)&static_state,
366       0,
367       RGX_CONTEXT_FLAG_DISABLESLR,
368       0,
369       UINT_MAX,
370       UINT_MAX,
371       &srv_ctx->handle);
372    if (result != VK_SUCCESS)
373       goto err_close_timeline_frag;
374 
375    srv_ctx->base.ws = ws;
376 
377    *ctx_out = &srv_ctx->base;
378 
379    return VK_SUCCESS;
380 
381 err_close_timeline_frag:
382    close(srv_ctx->timeline_frag);
383 
384 err_close_timeline_geom:
385    close(srv_ctx->timeline_geom);
386 
387 err_free_srv_ctx:
388    vk_free(srv_ws->alloc, srv_ctx);
389 
390    return vk_error(NULL, VK_ERROR_INITIALIZATION_FAILED);
391 }
392 
pvr_srv_winsys_render_ctx_destroy(struct pvr_winsys_render_ctx * ctx)393 void pvr_srv_winsys_render_ctx_destroy(struct pvr_winsys_render_ctx *ctx)
394 {
395    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
396    struct pvr_srv_winsys_render_ctx *srv_ctx =
397       to_pvr_srv_winsys_render_ctx(ctx);
398 
399    pvr_srv_rgx_destroy_render_context(srv_ws->render_fd, srv_ctx->handle);
400    close(srv_ctx->timeline_frag);
401    close(srv_ctx->timeline_geom);
402    vk_free(srv_ws->alloc, srv_ctx);
403 }
404 
pvr_srv_geometry_cmd_init(const struct pvr_winsys_render_submit_info * submit_info,const struct pvr_srv_sync_prim * sync_prim,struct rogue_fwif_cmd_ta * cmd)405 static void pvr_srv_geometry_cmd_init(
406    const struct pvr_winsys_render_submit_info *submit_info,
407    const struct pvr_srv_sync_prim *sync_prim,
408    struct rogue_fwif_cmd_ta *cmd)
409 {
410    const struct pvr_winsys_geometry_state *state = &submit_info->geometry;
411    struct rogue_fwif_ta_regs *fw_regs = &cmd->geom_regs;
412 
413    memset(cmd, 0, sizeof(*cmd));
414 
415    cmd->cmd_shared.cmn.frame_num = submit_info->frame_num;
416 
417    fw_regs->vdm_ctrl_stream_base = state->regs.vdm_ctrl_stream_base;
418    fw_regs->tpu_border_colour_table = state->regs.tpu_border_colour_table;
419    fw_regs->ppp_ctrl = state->regs.ppp_ctrl;
420    fw_regs->te_psg = state->regs.te_psg;
421    fw_regs->tpu = state->regs.tpu;
422    fw_regs->vdm_context_resume_task0_size =
423       state->regs.vdm_ctx_resume_task0_size;
424 
425    assert(state->regs.pds_ctrl >> 32U == 0U);
426    fw_regs->pds_ctrl = (uint32_t)state->regs.pds_ctrl;
427 
428    if (state->flags & PVR_WINSYS_GEOM_FLAG_FIRST_GEOMETRY)
429       cmd->flags |= ROGUE_FWIF_TAFLAGS_FIRSTKICK;
430 
431    if (state->flags & PVR_WINSYS_GEOM_FLAG_LAST_GEOMETRY)
432       cmd->flags |= ROGUE_FWIF_TAFLAGS_LASTKICK;
433 
434    if (state->flags & PVR_WINSYS_GEOM_FLAG_SINGLE_CORE)
435       cmd->flags |= ROGUE_FWIF_TAFLAGS_SINGLE_CORE;
436 
437    cmd->partial_render_ta_3d_fence.ufo_addr.addr =
438       pvr_srv_sync_prim_get_fw_addr(sync_prim);
439    cmd->partial_render_ta_3d_fence.value = sync_prim->value;
440 }
441 
pvr_srv_fragment_cmd_init(const struct pvr_winsys_render_submit_info * submit_info,struct rogue_fwif_cmd_3d * cmd)442 static void pvr_srv_fragment_cmd_init(
443    const struct pvr_winsys_render_submit_info *submit_info,
444    struct rogue_fwif_cmd_3d *cmd)
445 {
446    const struct pvr_winsys_fragment_state *state = &submit_info->fragment;
447    struct rogue_fwif_3d_regs *fw_regs = &cmd->regs;
448 
449    memset(cmd, 0, sizeof(*cmd));
450 
451    cmd->cmd_shared.cmn.frame_num = submit_info->frame_num;
452 
453    fw_regs->usc_pixel_output_ctrl = state->regs.usc_pixel_output_ctrl;
454    fw_regs->isp_bgobjdepth = state->regs.isp_bgobjdepth;
455    fw_regs->isp_bgobjvals = state->regs.isp_bgobjvals;
456    fw_regs->isp_aa = state->regs.isp_aa;
457    fw_regs->isp_ctl = state->regs.isp_ctl;
458    fw_regs->tpu = state->regs.tpu;
459    fw_regs->event_pixel_pds_info = state->regs.event_pixel_pds_info;
460    fw_regs->pixel_phantom = state->regs.pixel_phantom;
461    fw_regs->event_pixel_pds_data = state->regs.event_pixel_pds_data;
462    fw_regs->isp_scissor_base = state->regs.isp_scissor_base;
463    fw_regs->isp_dbias_base = state->regs.isp_dbias_base;
464    fw_regs->isp_oclqry_base = state->regs.isp_oclqry_base;
465    fw_regs->isp_zlsctl = state->regs.isp_zlsctl;
466    fw_regs->isp_zload_store_base = state->regs.isp_zload_store_base;
467    fw_regs->isp_stencil_load_store_base =
468       state->regs.isp_stencil_load_store_base;
469    fw_regs->isp_zls_pixels = state->regs.isp_zls_pixels;
470 
471    STATIC_ASSERT(ARRAY_SIZE(fw_regs->pbe_word) ==
472                  ARRAY_SIZE(state->regs.pbe_word));
473 
474    STATIC_ASSERT(ARRAY_SIZE(fw_regs->pbe_word[0]) <=
475                  ARRAY_SIZE(state->regs.pbe_word[0]));
476 
477 #if !defined(NDEBUG)
478    /* Depending on the hardware we might have more PBE words than the firmware
479     * accepts so check that the extra words are 0.
480     */
481    if (ARRAY_SIZE(fw_regs->pbe_word[0]) < ARRAY_SIZE(state->regs.pbe_word[0])) {
482       /* For each color attachment. */
483       for (uint32_t i = 0; i < ARRAY_SIZE(state->regs.pbe_word); i++) {
484          /* For each extra PBE word not used by the firmware. */
485          for (uint32_t j = ARRAY_SIZE(fw_regs->pbe_word[0]);
486               j < ARRAY_SIZE(state->regs.pbe_word[0]);
487               j++) {
488             assert(state->regs.pbe_word[i][j] == 0);
489          }
490       }
491    }
492 #endif
493 
494    memcpy(fw_regs->pbe_word, state->regs.pbe_word, sizeof(fw_regs->pbe_word));
495 
496    fw_regs->tpu_border_colour_table = state->regs.tpu_border_colour_table;
497 
498    STATIC_ASSERT(ARRAY_SIZE(fw_regs->pds_bgnd) ==
499                  ARRAY_SIZE(state->regs.pds_bgnd));
500    typed_memcpy(fw_regs->pds_bgnd,
501                 state->regs.pds_bgnd,
502                 ARRAY_SIZE(fw_regs->pds_bgnd));
503 
504    STATIC_ASSERT(ARRAY_SIZE(fw_regs->pds_pr_bgnd) ==
505                  ARRAY_SIZE(state->regs.pds_pr_bgnd));
506    typed_memcpy(fw_regs->pds_pr_bgnd,
507                 state->regs.pds_pr_bgnd,
508                 ARRAY_SIZE(fw_regs->pds_pr_bgnd));
509 
510    if (state->flags & PVR_WINSYS_FRAG_FLAG_DEPTH_BUFFER_PRESENT)
511       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_DEPTHBUFFER;
512 
513    if (state->flags & PVR_WINSYS_FRAG_FLAG_STENCIL_BUFFER_PRESENT)
514       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_STENCILBUFFER;
515 
516    if (state->flags & PVR_WINSYS_FRAG_FLAG_PREVENT_CDM_OVERLAP)
517       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_PREVENT_CDM_OVERLAP;
518 
519    if (state->flags & PVR_WINSYS_FRAG_FLAG_SINGLE_CORE)
520       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_SINGLE_CORE;
521 
522    cmd->zls_stride = state->zls_stride;
523    cmd->sls_stride = state->sls_stride;
524 }
525 
pvr_srv_winsys_render_submit(const struct pvr_winsys_render_ctx * ctx,const struct pvr_winsys_render_submit_info * submit_info,struct vk_sync * signal_sync_geom,struct vk_sync * signal_sync_frag)526 VkResult pvr_srv_winsys_render_submit(
527    const struct pvr_winsys_render_ctx *ctx,
528    const struct pvr_winsys_render_submit_info *submit_info,
529    struct vk_sync *signal_sync_geom,
530    struct vk_sync *signal_sync_frag)
531 {
532    const struct pvr_srv_winsys_rt_dataset *srv_rt_dataset =
533       to_pvr_srv_winsys_rt_dataset(submit_info->rt_dataset);
534    struct pvr_srv_sync_prim *sync_prim =
535       srv_rt_dataset->rt_datas[submit_info->rt_data_idx].sync_prim;
536    void *rt_data_handle =
537       srv_rt_dataset->rt_datas[submit_info->rt_data_idx].handle;
538    const struct pvr_srv_winsys_render_ctx *srv_ctx =
539       to_pvr_srv_winsys_render_ctx(ctx);
540    const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
541 
542    uint32_t sync_pmr_flags[PVR_SRV_SYNC_MAX] = { 0U };
543    void *sync_pmrs[PVR_SRV_SYNC_MAX] = { NULL };
544    uint32_t sync_pmr_count;
545 
546    struct pvr_srv_sync *srv_signal_sync_geom;
547    struct pvr_srv_sync *srv_signal_sync_frag;
548 
549    struct rogue_fwif_cmd_ta geom_cmd;
550    struct rogue_fwif_cmd_3d frag_cmd;
551 
552    int in_frag_fd = -1;
553    int in_geom_fd = -1;
554    int fence_frag;
555    int fence_geom;
556 
557    VkResult result;
558 
559    pvr_srv_geometry_cmd_init(submit_info, sync_prim, &geom_cmd);
560    pvr_srv_fragment_cmd_init(submit_info, &frag_cmd);
561 
562    for (uint32_t i = 0U; i < submit_info->wait_count; i++) {
563       struct pvr_srv_sync *srv_wait_sync = to_srv_sync(submit_info->waits[i]);
564       int ret;
565 
566       if (!submit_info->waits[i] || srv_wait_sync->fd < 0)
567          continue;
568 
569       if (submit_info->stage_flags[i] & PVR_PIPELINE_STAGE_GEOM_BIT) {
570          ret = sync_accumulate("", &in_geom_fd, srv_wait_sync->fd);
571          if (ret) {
572             result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
573             goto err_close_in_fds;
574          }
575 
576          submit_info->stage_flags[i] &= ~PVR_PIPELINE_STAGE_GEOM_BIT;
577       }
578 
579       if (submit_info->stage_flags[i] & PVR_PIPELINE_STAGE_FRAG_BIT) {
580          ret = sync_accumulate("", &in_frag_fd, srv_wait_sync->fd);
581          if (ret) {
582             result = vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
583             goto err_close_in_fds;
584          }
585 
586          submit_info->stage_flags[i] &= ~PVR_PIPELINE_STAGE_FRAG_BIT;
587       }
588    }
589 
590    if (submit_info->bo_count <= ARRAY_SIZE(sync_pmrs)) {
591       sync_pmr_count = submit_info->bo_count;
592    } else {
593       mesa_logw("Too many bos to synchronize access to (ignoring %zu bos)\n",
594                 submit_info->bo_count - ARRAY_SIZE(sync_pmrs));
595       sync_pmr_count = ARRAY_SIZE(sync_pmrs);
596    }
597 
598    STATIC_ASSERT(ARRAY_SIZE(sync_pmrs) == ARRAY_SIZE(sync_pmr_flags));
599    assert(sync_pmr_count <= ARRAY_SIZE(sync_pmrs));
600    for (uint32_t i = 0; i < sync_pmr_count; i++) {
601       const struct pvr_winsys_job_bo *job_bo = &submit_info->bos[i];
602       const struct pvr_srv_winsys_bo *srv_bo = to_pvr_srv_winsys_bo(job_bo->bo);
603 
604       sync_pmrs[i] = srv_bo->pmr;
605 
606       if (job_bo->flags & PVR_WINSYS_JOB_BO_FLAG_WRITE)
607          sync_pmr_flags[i] = PVR_BUFFER_FLAG_WRITE;
608       else
609          sync_pmr_flags[i] = PVR_BUFFER_FLAG_READ;
610    }
611 
612    /* The 1.14 PowerVR Services KM driver doesn't add a sync dependency to the
613     * fragment phase on the geometry phase for us. This makes it
614     * necessary to use a sync prim for this purpose. This requires that we pass
615     * in the same sync prim information for the geometry phase update and the
616     * PR fence. We update the sync prim value here as this is the value the
617     * sync prim will get updated to once the geometry phase has completed and
618     * the value the PR or fragment phase will be fenced on.
619     */
620    sync_prim->value++;
621 
622    do {
623       result = pvr_srv_rgx_kick_render2(srv_ws->render_fd,
624                                         srv_ctx->handle,
625                                         0,
626                                         NULL,
627                                         NULL,
628                                         NULL,
629                                         1,
630                                         &sync_prim->srv_ws->sync_block_handle,
631                                         &sync_prim->offset,
632                                         &sync_prim->value,
633                                         0,
634                                         NULL,
635                                         NULL,
636                                         NULL,
637                                         sync_prim->srv_ws->sync_block_handle,
638                                         sync_prim->offset,
639                                         sync_prim->value,
640                                         in_geom_fd,
641                                         srv_ctx->timeline_geom,
642                                         &fence_geom,
643                                         "GEOM",
644                                         in_frag_fd,
645                                         srv_ctx->timeline_frag,
646                                         &fence_frag,
647                                         "FRAG",
648                                         sizeof(geom_cmd),
649                                         (uint8_t *)&geom_cmd,
650                                         /* Currently no support for PRs. */
651                                         0,
652                                         /* Currently no support for PRs. */
653                                         NULL,
654                                         sizeof(frag_cmd),
655                                         (uint8_t *)&frag_cmd,
656                                         submit_info->job_num,
657                                         /* Always kick the TA. */
658                                         true,
659                                         /* Always kick a PR. */
660                                         true,
661                                         submit_info->run_frag,
662                                         false,
663                                         0,
664                                         rt_data_handle,
665                                         /* Currently no support for PRs. */
666                                         NULL,
667                                         /* Currently no support for PRs. */
668                                         NULL,
669                                         sync_pmr_count,
670                                         sync_pmr_count ? sync_pmr_flags : NULL,
671                                         sync_pmr_count ? sync_pmrs : NULL,
672                                         0,
673                                         0,
674                                         0,
675                                         0,
676                                         0);
677    } while (result == VK_NOT_READY);
678 
679    if (result != VK_SUCCESS)
680       goto err_close_in_fds;
681 
682    if (signal_sync_geom) {
683       srv_signal_sync_geom = to_srv_sync(signal_sync_geom);
684       pvr_srv_set_sync_payload(srv_signal_sync_geom, fence_geom);
685    } else if (fence_geom != -1) {
686       close(fence_geom);
687    }
688 
689    if (signal_sync_frag) {
690       srv_signal_sync_frag = to_srv_sync(signal_sync_frag);
691       pvr_srv_set_sync_payload(srv_signal_sync_frag, fence_frag);
692    } else if (fence_frag != -1) {
693       close(fence_frag);
694    }
695 
696    return VK_SUCCESS;
697 
698 err_close_in_fds:
699    if (in_geom_fd >= 0)
700       close(in_geom_fd);
701 
702    if (in_frag_fd >= 0)
703       close(in_frag_fd);
704 
705    return result;
706 }
707