• 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 <errno.h>
26 #include <fcntl.h>
27 #include <limits.h>
28 #include <stdbool.h>
29 #include <stddef.h>
30 #include <stdint.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <vulkan/vulkan.h>
34 
35 #include "fw-api/pvr_rogue_fwif.h"
36 #include "fw-api/pvr_rogue_fwif_rf.h"
37 #include "pvr_csb.h"
38 #include "pvr_job_render.h"
39 #include "pvr_private.h"
40 #include "pvr_srv.h"
41 #include "pvr_srv_bo.h"
42 #include "pvr_srv_bridge.h"
43 #include "pvr_srv_job_common.h"
44 #include "pvr_srv_job_render.h"
45 #include "pvr_srv_sync.h"
46 #include "pvr_srv_sync_prim.h"
47 #include "pvr_types.h"
48 #include "pvr_winsys.h"
49 #include "util/compiler.h"
50 #include "util/log.h"
51 #include "util/macros.h"
52 #include "util/u_math.h"
53 #include "vk_alloc.h"
54 #include "vk_log.h"
55 #include "vk_util.h"
56 
57 struct pvr_srv_winsys_free_list {
58    struct pvr_winsys_free_list base;
59 
60    void *handle;
61 
62    struct pvr_srv_winsys_free_list *parent;
63 };
64 
65 #define to_pvr_srv_winsys_free_list(free_list) \
66    container_of(free_list, struct pvr_srv_winsys_free_list, base)
67 
68 struct pvr_srv_winsys_rt_dataset {
69    struct pvr_winsys_rt_dataset base;
70 
71    struct {
72       void *handle;
73       struct pvr_srv_sync_prim *sync_prim;
74    } rt_datas[ROGUE_FWIF_NUM_RTDATAS];
75 };
76 
77 #define to_pvr_srv_winsys_rt_dataset(rt_dataset) \
78    container_of(rt_dataset, struct pvr_srv_winsys_rt_dataset, base)
79 
80 struct pvr_srv_winsys_render_ctx {
81    struct pvr_winsys_render_ctx base;
82 
83    /* Handle to kernel context. */
84    void *handle;
85 
86    int timeline_geom;
87    int timeline_frag;
88 };
89 
90 #define to_pvr_srv_winsys_render_ctx(ctx) \
91    container_of(ctx, struct pvr_srv_winsys_render_ctx, base)
92 
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)93 VkResult pvr_srv_winsys_free_list_create(
94    struct pvr_winsys *ws,
95    struct pvr_winsys_vma *free_list_vma,
96    uint32_t initial_num_pages,
97    uint32_t max_num_pages,
98    uint32_t grow_num_pages,
99    uint32_t grow_threshold,
100    struct pvr_winsys_free_list *parent_free_list,
101    struct pvr_winsys_free_list **const free_list_out)
102 {
103    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
104    struct pvr_srv_winsys_bo *srv_free_list_bo =
105       to_pvr_srv_winsys_bo(free_list_vma->bo);
106    struct pvr_srv_winsys_free_list *srv_free_list;
107    void *parent_handle;
108    VkResult result;
109 
110    srv_free_list = vk_zalloc(ws->alloc,
111                              sizeof(*srv_free_list),
112                              8,
113                              VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
114    if (!srv_free_list)
115       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
116 
117    if (parent_free_list) {
118       srv_free_list->parent = to_pvr_srv_winsys_free_list(parent_free_list);
119       parent_handle = srv_free_list->parent->handle;
120    } else {
121       srv_free_list->parent = NULL;
122       parent_handle = NULL;
123    }
124 
125    result = pvr_srv_rgx_create_free_list(ws->render_fd,
126                                          srv_ws->server_memctx_data,
127                                          max_num_pages,
128                                          initial_num_pages,
129                                          grow_num_pages,
130                                          grow_threshold,
131                                          parent_handle,
132 #if MESA_DEBUG
133                                          PVR_SRV_TRUE /* free_list_check */,
134 #else
135                                          PVR_SRV_FALSE /* free_list_check */,
136 #endif
137                                          free_list_vma->dev_addr,
138                                          srv_free_list_bo->pmr,
139                                          0 /* pmr_offset */,
140                                          &srv_free_list->handle);
141    if (result != VK_SUCCESS)
142       goto err_vk_free_srv_free_list;
143 
144    srv_free_list->base.ws = ws;
145 
146    *free_list_out = &srv_free_list->base;
147 
148    return VK_SUCCESS;
149 
150 err_vk_free_srv_free_list:
151    vk_free(ws->alloc, srv_free_list);
152 
153    return result;
154 }
155 
pvr_srv_winsys_free_list_destroy(struct pvr_winsys_free_list * free_list)156 void pvr_srv_winsys_free_list_destroy(struct pvr_winsys_free_list *free_list)
157 {
158    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(free_list->ws);
159    struct pvr_srv_winsys_free_list *srv_free_list =
160       to_pvr_srv_winsys_free_list(free_list);
161 
162    pvr_srv_rgx_destroy_free_list(srv_ws->base.render_fd, srv_free_list->handle);
163    vk_free(srv_ws->base.alloc, srv_free_list);
164 }
165 
pvr_rogue_get_cr_multisamplectl_val(uint32_t samples,bool y_flip)166 static uint64_t pvr_rogue_get_cr_multisamplectl_val(uint32_t samples,
167                                                     bool y_flip)
168 {
169    static const struct {
170       uint8_t x[8];
171       uint8_t y[8];
172    } sample_positions[4] = {
173       /* 1 sample */
174       {
175          .x = { 8 },
176          .y = { 8 },
177       },
178       /* 2 samples */
179       {
180          .x = { 12, 4 },
181          .y = { 12, 4 },
182       },
183       /* 4 samples */
184       {
185          .x = { 6, 14, 2, 10 },
186          .y = { 2, 6, 10, 14 },
187       },
188       /* 8 samples */
189       {
190          .x = { 9, 7, 13, 5, 3, 1, 11, 15 },
191          .y = { 5, 11, 9, 3, 13, 7, 15, 1 },
192       },
193    };
194    uint64_t multisamplectl;
195    uint8_t idx;
196 
197    idx = util_fast_log2(samples);
198    assert(idx < ARRAY_SIZE(sample_positions));
199 
200    pvr_csb_pack (&multisamplectl, CR_PPP_MULTISAMPLECTL, value) {
201       switch (samples) {
202       case 8:
203          value.msaa_x7 = sample_positions[idx].x[7];
204          value.msaa_x6 = sample_positions[idx].x[6];
205          value.msaa_x5 = sample_positions[idx].x[5];
206          value.msaa_x4 = sample_positions[idx].x[4];
207 
208          if (y_flip) {
209             value.msaa_y7 = 16U - sample_positions[idx].y[7];
210             value.msaa_y6 = 16U - sample_positions[idx].y[6];
211             value.msaa_y5 = 16U - sample_positions[idx].y[5];
212             value.msaa_y4 = 16U - sample_positions[idx].y[4];
213          } else {
214             value.msaa_y7 = sample_positions[idx].y[7];
215             value.msaa_y6 = sample_positions[idx].y[6];
216             value.msaa_y5 = sample_positions[idx].y[5];
217             value.msaa_y4 = sample_positions[idx].y[4];
218          }
219 
220          FALLTHROUGH;
221       case 4:
222          value.msaa_x3 = sample_positions[idx].x[3];
223          value.msaa_x2 = sample_positions[idx].x[2];
224 
225          if (y_flip) {
226             value.msaa_y3 = 16U - sample_positions[idx].y[3];
227             value.msaa_y2 = 16U - sample_positions[idx].y[2];
228          } else {
229             value.msaa_y3 = sample_positions[idx].y[3];
230             value.msaa_y2 = sample_positions[idx].y[2];
231          }
232 
233          FALLTHROUGH;
234       case 2:
235          value.msaa_x1 = sample_positions[idx].x[1];
236 
237          if (y_flip) {
238             value.msaa_y1 = 16U - sample_positions[idx].y[1];
239          } else {
240             value.msaa_y1 = sample_positions[idx].y[1];
241          }
242 
243          FALLTHROUGH;
244       case 1:
245          value.msaa_x0 = sample_positions[idx].x[0];
246 
247          if (y_flip) {
248             value.msaa_y0 = 16U - sample_positions[idx].y[0];
249          } else {
250             value.msaa_y0 = sample_positions[idx].y[0];
251          }
252 
253          break;
254       default:
255          unreachable("Unsupported number of samples");
256       }
257    }
258 
259    return multisamplectl;
260 }
261 
262 static uint32_t
pvr_rogue_get_cr_isp_mtile_size_val(const struct pvr_device_info * dev_info,const struct pvr_rt_mtile_info * mtile_info,uint32_t samples)263 pvr_rogue_get_cr_isp_mtile_size_val(const struct pvr_device_info *dev_info,
264                                     const struct pvr_rt_mtile_info *mtile_info,
265                                     uint32_t samples)
266 {
267    uint32_t samples_per_pixel =
268       PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0);
269    uint32_t isp_mtile_size;
270 
271    pvr_csb_pack (&isp_mtile_size, CR_ISP_MTILE_SIZE, value) {
272       value.x = mtile_info->mtile_x1;
273       value.y = mtile_info->mtile_y1;
274 
275       if (samples_per_pixel == 1) {
276          if (samples >= 4)
277             value.x <<= 1;
278 
279          if (samples >= 2)
280             value.y <<= 1;
281       } else if (samples_per_pixel == 2) {
282          if (samples >= 8)
283             value.x <<= 1;
284 
285          if (samples >= 4)
286             value.y <<= 1;
287       } else if (samples_per_pixel == 4) {
288          if (samples >= 8)
289             value.y <<= 1;
290       } else {
291          assert(!"Unsupported ISP samples per pixel value");
292       }
293    }
294 
295    return isp_mtile_size;
296 }
297 
pvr_rogue_get_ppp_screen_val(uint32_t width,uint32_t height)298 static uint32_t pvr_rogue_get_ppp_screen_val(uint32_t width, uint32_t height)
299 {
300    uint32_t val;
301 
302    pvr_csb_pack (&val, CR_PPP_SCREEN, state) {
303       state.pixxmax = width - 1;
304       state.pixymax = height - 1;
305    }
306 
307    return val;
308 }
309 
310 struct pvr_rogue_cr_te {
311    uint32_t aa;
312    uint32_t mtile1;
313    uint32_t mtile2;
314    uint32_t screen;
315    uint32_t mtile_stride;
316 };
317 
pvr_rogue_ct_te_init(const struct pvr_device_info * dev_info,const struct pvr_rt_mtile_info * mtile_info,uint32_t samples,struct pvr_rogue_cr_te * const te_regs)318 static void pvr_rogue_ct_te_init(const struct pvr_device_info *dev_info,
319                                  const struct pvr_rt_mtile_info *mtile_info,
320                                  uint32_t samples,
321                                  struct pvr_rogue_cr_te *const te_regs)
322 {
323    uint32_t samples_per_pixel =
324       PVR_GET_FEATURE_VALUE(dev_info, isp_samples_per_pixel, 0);
325 
326    pvr_csb_pack (&te_regs->aa, CR_TE_AA, value) {
327       if (samples_per_pixel == 1) {
328          if (samples >= 2)
329             value.y = true;
330          if (samples >= 4)
331             value.x = true;
332       } else if (samples_per_pixel == 2) {
333          if (samples >= 2)
334             value.x2 = true;
335          if (samples >= 4)
336             value.y = true;
337          if (samples >= 8)
338             value.x = true;
339       } else if (samples_per_pixel == 4) {
340          if (samples >= 2)
341             value.x2 = true;
342          if (samples >= 4)
343             value.y2 = true;
344          if (samples >= 8)
345             value.y = true;
346       } else {
347          assert(!"Unsupported ISP samples per pixel value");
348       }
349    }
350 
351    pvr_csb_pack (&te_regs->mtile1, CR_TE_MTILE1, value) {
352       value.x1 = mtile_info->mtile_x1;
353       if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) {
354          value.x2 = mtile_info->mtile_x2;
355          value.x3 = mtile_info->mtile_x3;
356       }
357    }
358 
359    pvr_csb_pack (&te_regs->mtile2, CR_TE_MTILE2, value) {
360       value.y1 = mtile_info->mtile_y1;
361       if (!PVR_HAS_FEATURE(dev_info, simple_internal_parameter_format)) {
362          value.y2 = mtile_info->mtile_y2;
363          value.y3 = mtile_info->mtile_y3;
364       }
365    }
366 
367    pvr_csb_pack (&te_regs->screen, CR_TE_SCREEN, value) {
368       value.xmax = mtile_info->x_tile_max;
369       value.ymax = mtile_info->y_tile_max;
370    }
371 
372    te_regs->mtile_stride = mtile_info->mtile_x1 * mtile_info->mtile_y1;
373 }
374 
pvr_srv_render_target_dataset_create(struct pvr_winsys * ws,const struct pvr_winsys_rt_dataset_create_info * create_info,const struct pvr_device_info * dev_info,struct pvr_winsys_rt_dataset ** const rt_dataset_out)375 VkResult pvr_srv_render_target_dataset_create(
376    struct pvr_winsys *ws,
377    const struct pvr_winsys_rt_dataset_create_info *create_info,
378    const struct pvr_device_info *dev_info,
379    struct pvr_winsys_rt_dataset **const rt_dataset_out)
380 {
381    const pvr_dev_addr_t macrotile_addrs[ROGUE_FWIF_NUM_RTDATAS] = {
382       [0] = create_info->rt_datas[0].macrotile_array_dev_addr,
383       [1] = create_info->rt_datas[1].macrotile_array_dev_addr,
384    };
385    const pvr_dev_addr_t pm_mlist_addrs[ROGUE_FWIF_NUM_RTDATAS] = {
386       [0] = create_info->rt_datas[0].pm_mlist_dev_addr,
387       [1] = create_info->rt_datas[1].pm_mlist_dev_addr,
388    };
389    const pvr_dev_addr_t rgn_header_addrs[ROGUE_FWIF_NUM_RTDATAS] = {
390       [0] = create_info->rt_datas[0].rgn_header_dev_addr,
391       [1] = create_info->rt_datas[1].rgn_header_dev_addr,
392    };
393 
394    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
395    struct pvr_srv_winsys_free_list *srv_local_free_list =
396       to_pvr_srv_winsys_free_list(create_info->local_free_list);
397    void *free_lists[ROGUE_FW_MAX_FREELISTS] = { NULL };
398    struct pvr_srv_winsys_rt_dataset *srv_rt_dataset;
399    void *handles[ROGUE_FWIF_NUM_RTDATAS];
400    struct pvr_rogue_cr_te rogue_te_regs;
401    struct pvr_rt_mtile_info mtile_info;
402    uint32_t isp_mtile_size;
403    VkResult result;
404 
405    free_lists[ROGUE_FW_LOCAL_FREELIST] = srv_local_free_list->handle;
406 
407    if (srv_local_free_list->parent) {
408       free_lists[ROGUE_FW_GLOBAL_FREELIST] =
409          srv_local_free_list->parent->handle;
410    }
411 
412    srv_rt_dataset = vk_zalloc(ws->alloc,
413                               sizeof(*srv_rt_dataset),
414                               8,
415                               VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
416    if (!srv_rt_dataset)
417       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
418 
419    /* If greater than 1 we'll have to pass in an array. For now just passing in
420     * the reference.
421     */
422    STATIC_ASSERT(ROGUE_FWIF_NUM_GEOMDATAS == 1);
423    /* If not 2 the arrays used in the bridge call will require updating. */
424    STATIC_ASSERT(ROGUE_FWIF_NUM_RTDATAS == 2);
425 
426    pvr_rt_mtile_info_init(dev_info,
427                           &mtile_info,
428                           create_info->width,
429                           create_info->height,
430                           create_info->samples);
431 
432    isp_mtile_size = pvr_rogue_get_cr_isp_mtile_size_val(dev_info,
433                                                         &mtile_info,
434                                                         create_info->samples);
435 
436    pvr_rogue_ct_te_init(dev_info,
437                         &mtile_info,
438                         create_info->samples,
439                         &rogue_te_regs);
440 
441    result = pvr_srv_rgx_create_hwrt_dataset(
442       ws->render_fd,
443       pvr_rogue_get_cr_multisamplectl_val(create_info->samples, true),
444       pvr_rogue_get_cr_multisamplectl_val(create_info->samples, false),
445       macrotile_addrs,
446       pm_mlist_addrs,
447       &create_info->rtc_dev_addr,
448       rgn_header_addrs,
449       &create_info->tpc_dev_addr,
450       &create_info->vheap_table_dev_addr,
451       free_lists,
452       create_info->isp_merge_lower_x,
453       create_info->isp_merge_lower_y,
454       create_info->isp_merge_scale_x,
455       create_info->isp_merge_scale_y,
456       create_info->isp_merge_upper_x,
457       create_info->isp_merge_upper_y,
458       isp_mtile_size,
459       rogue_te_regs.mtile_stride,
460       pvr_rogue_get_ppp_screen_val(create_info->width, create_info->height),
461       create_info->rgn_header_size,
462       rogue_te_regs.aa,
463       rogue_te_regs.mtile1,
464       rogue_te_regs.mtile2,
465       rogue_te_regs.screen,
466       create_info->tpc_size,
467       create_info->tpc_stride,
468       create_info->layers,
469       handles);
470    if (result != VK_SUCCESS)
471       goto err_vk_free_srv_rt_dataset;
472 
473    srv_rt_dataset->rt_datas[0].handle = handles[0];
474    srv_rt_dataset->rt_datas[1].handle = handles[1];
475 
476    for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) {
477       srv_rt_dataset->rt_datas[i].sync_prim = pvr_srv_sync_prim_alloc(srv_ws);
478       if (!srv_rt_dataset->rt_datas[i].sync_prim)
479          goto err_srv_sync_prim_free;
480    }
481 
482    srv_rt_dataset->base.ws = ws;
483 
484    *rt_dataset_out = &srv_rt_dataset->base;
485 
486    return VK_SUCCESS;
487 
488 err_srv_sync_prim_free:
489    for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) {
490       pvr_srv_sync_prim_free(srv_ws, srv_rt_dataset->rt_datas[i].sync_prim);
491 
492       if (srv_rt_dataset->rt_datas[i].handle) {
493          pvr_srv_rgx_destroy_hwrt_dataset(ws->render_fd,
494                                           srv_rt_dataset->rt_datas[i].handle);
495       }
496    }
497 
498 err_vk_free_srv_rt_dataset:
499    vk_free(ws->alloc, srv_rt_dataset);
500 
501    return result;
502 }
503 
pvr_srv_render_target_dataset_destroy(struct pvr_winsys_rt_dataset * rt_dataset)504 void pvr_srv_render_target_dataset_destroy(
505    struct pvr_winsys_rt_dataset *rt_dataset)
506 {
507    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(rt_dataset->ws);
508    struct pvr_srv_winsys_rt_dataset *srv_rt_dataset =
509       to_pvr_srv_winsys_rt_dataset(rt_dataset);
510 
511    for (uint32_t i = 0; i < ARRAY_SIZE(srv_rt_dataset->rt_datas); i++) {
512       pvr_srv_sync_prim_free(srv_ws, srv_rt_dataset->rt_datas[i].sync_prim);
513 
514       if (srv_rt_dataset->rt_datas[i].handle) {
515          pvr_srv_rgx_destroy_hwrt_dataset(srv_ws->base.render_fd,
516                                           srv_rt_dataset->rt_datas[i].handle);
517       }
518    }
519 
520    vk_free(srv_ws->base.alloc, srv_rt_dataset);
521 }
522 
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)523 static void pvr_srv_render_ctx_fw_static_state_init(
524    struct pvr_winsys_render_ctx_create_info *create_info,
525    struct rogue_fwif_static_rendercontext_state *static_state)
526 {
527    struct pvr_winsys_render_ctx_static_state *ws_static_state =
528       &create_info->static_state;
529    struct rogue_fwif_ta_regs_cswitch *regs =
530       &static_state->ctx_switch_geom_regs[0];
531 
532    memset(static_state, 0, sizeof(*static_state));
533 
534    regs->vdm_context_state_base_addr = ws_static_state->vdm_ctx_state_base_addr;
535    regs->ta_context_state_base_addr = ws_static_state->geom_ctx_state_base_addr;
536 
537    STATIC_ASSERT(ARRAY_SIZE(regs->ta_state) ==
538                  ARRAY_SIZE(ws_static_state->geom_state));
539    for (uint32_t i = 0; i < ARRAY_SIZE(ws_static_state->geom_state); i++) {
540       regs->ta_state[i].vdm_context_store_task0 =
541          ws_static_state->geom_state[i].vdm_ctx_store_task0;
542       regs->ta_state[i].vdm_context_store_task1 =
543          ws_static_state->geom_state[i].vdm_ctx_store_task1;
544       regs->ta_state[i].vdm_context_store_task2 =
545          ws_static_state->geom_state[i].vdm_ctx_store_task2;
546 
547       regs->ta_state[i].vdm_context_resume_task0 =
548          ws_static_state->geom_state[i].vdm_ctx_resume_task0;
549       regs->ta_state[i].vdm_context_resume_task1 =
550          ws_static_state->geom_state[i].vdm_ctx_resume_task1;
551       regs->ta_state[i].vdm_context_resume_task2 =
552          ws_static_state->geom_state[i].vdm_ctx_resume_task2;
553    }
554 }
555 
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)556 VkResult pvr_srv_winsys_render_ctx_create(
557    struct pvr_winsys *ws,
558    struct pvr_winsys_render_ctx_create_info *create_info,
559    struct pvr_winsys_render_ctx **const ctx_out)
560 {
561    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ws);
562    struct rogue_fwif_rf_cmd reset_cmd = { 0 };
563 
564    struct rogue_fwif_static_rendercontext_state static_state;
565    struct pvr_srv_winsys_render_ctx *srv_ctx;
566    const uint32_t call_stack_depth = 1U;
567    VkResult result;
568 
569    srv_ctx = vk_zalloc(ws->alloc,
570                        sizeof(*srv_ctx),
571                        8,
572                        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
573    if (!srv_ctx)
574       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
575 
576    result = pvr_srv_create_timeline(ws->render_fd, &srv_ctx->timeline_geom);
577    if (result != VK_SUCCESS)
578       goto err_free_srv_ctx;
579 
580    result = pvr_srv_create_timeline(ws->render_fd, &srv_ctx->timeline_frag);
581    if (result != VK_SUCCESS)
582       goto err_close_timeline_geom;
583 
584    pvr_srv_render_ctx_fw_static_state_init(create_info, &static_state);
585 
586    /* TODO: Add support for reset framework. Currently we subtract
587     * reset_cmd.regs size from reset_cmd size to only pass empty flags field.
588     */
589    result = pvr_srv_rgx_create_render_context(
590       ws->render_fd,
591       pvr_srv_from_winsys_priority(create_info->priority),
592       create_info->vdm_callstack_addr,
593       call_stack_depth,
594       sizeof(reset_cmd) - sizeof(reset_cmd.regs),
595       (uint8_t *)&reset_cmd,
596       srv_ws->server_memctx_data,
597       sizeof(static_state),
598       (uint8_t *)&static_state,
599       0,
600       RGX_CONTEXT_FLAG_DISABLESLR,
601       0,
602       UINT_MAX,
603       UINT_MAX,
604       &srv_ctx->handle);
605    if (result != VK_SUCCESS)
606       goto err_close_timeline_frag;
607 
608    srv_ctx->base.ws = ws;
609 
610    *ctx_out = &srv_ctx->base;
611 
612    return VK_SUCCESS;
613 
614 err_close_timeline_frag:
615    close(srv_ctx->timeline_frag);
616 
617 err_close_timeline_geom:
618    close(srv_ctx->timeline_geom);
619 
620 err_free_srv_ctx:
621    vk_free(ws->alloc, srv_ctx);
622 
623    return vk_error(NULL, VK_ERROR_INITIALIZATION_FAILED);
624 }
625 
pvr_srv_winsys_render_ctx_destroy(struct pvr_winsys_render_ctx * ctx)626 void pvr_srv_winsys_render_ctx_destroy(struct pvr_winsys_render_ctx *ctx)
627 {
628    struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
629    struct pvr_srv_winsys_render_ctx *srv_ctx =
630       to_pvr_srv_winsys_render_ctx(ctx);
631 
632    pvr_srv_rgx_destroy_render_context(srv_ws->base.render_fd, srv_ctx->handle);
633    close(srv_ctx->timeline_frag);
634    close(srv_ctx->timeline_geom);
635    vk_free(srv_ws->base.alloc, srv_ctx);
636 }
637 
638 static uint32_t
pvr_srv_geometry_cmd_stream_load(struct rogue_fwif_cmd_ta * const cmd,const uint8_t * const stream,const uint32_t stream_len,const struct pvr_device_info * const dev_info)639 pvr_srv_geometry_cmd_stream_load(struct rogue_fwif_cmd_ta *const cmd,
640                                  const uint8_t *const stream,
641                                  const uint32_t stream_len,
642                                  const struct pvr_device_info *const dev_info)
643 {
644    const uint32_t *stream_ptr = (const uint32_t *)stream;
645    struct rogue_fwif_ta_regs *const regs = &cmd->regs;
646    uint32_t main_stream_len =
647       pvr_csb_unpack((const uint64_t *)stream_ptr, KMD_STREAM_HDR).length;
648 
649    stream_ptr += pvr_cmd_length(KMD_STREAM_HDR);
650 
651    regs->vdm_ctrl_stream_base = *(const uint64_t *)stream_ptr;
652    stream_ptr += pvr_cmd_length(CR_VDM_CTRL_STREAM_BASE);
653 
654    regs->tpu_border_colour_table = *(const uint64_t *)stream_ptr;
655    stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_VDM);
656 
657    regs->ppp_ctrl = *stream_ptr;
658    stream_ptr += pvr_cmd_length(CR_PPP_CTRL);
659 
660    regs->te_psg = *stream_ptr;
661    stream_ptr += pvr_cmd_length(CR_TE_PSG);
662 
663    regs->vdm_context_resume_task0_size = *stream_ptr;
664    stream_ptr += pvr_cmd_length(VDMCTRL_PDS_STATE0);
665 
666    regs->view_idx = *stream_ptr;
667    stream_ptr++;
668 
669    assert((const uint8_t *)stream_ptr - stream <= stream_len);
670    assert((const uint8_t *)stream_ptr - stream == main_stream_len);
671 
672    return main_stream_len;
673 }
674 
pvr_srv_geometry_cmd_ext_stream_load(struct rogue_fwif_cmd_ta * 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)675 static void pvr_srv_geometry_cmd_ext_stream_load(
676    struct rogue_fwif_cmd_ta *const cmd,
677    const uint8_t *const stream,
678    const uint32_t stream_len,
679    const uint32_t ext_stream_offset,
680    const struct pvr_device_info *const dev_info)
681 {
682    const uint32_t *ext_stream_ptr =
683       (const uint32_t *)((uint8_t *)stream + ext_stream_offset);
684    struct rogue_fwif_ta_regs *const regs = &cmd->regs;
685 
686    struct ROGUE_KMD_STREAM_EXTHDR_GEOM0 header0;
687 
688    header0 = pvr_csb_unpack(ext_stream_ptr, KMD_STREAM_EXTHDR_GEOM0);
689    ext_stream_ptr += pvr_cmd_length(KMD_STREAM_EXTHDR_GEOM0);
690 
691    assert(PVR_HAS_QUIRK(dev_info, 49927) == header0.has_brn49927);
692    if (header0.has_brn49927) {
693       regs->tpu = *ext_stream_ptr;
694       ext_stream_ptr += pvr_cmd_length(CR_TPU);
695    }
696 
697    assert((const uint8_t *)ext_stream_ptr - stream == stream_len);
698 }
699 
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,const struct pvr_device_info * const dev_info)700 static void pvr_srv_geometry_cmd_init(
701    const struct pvr_winsys_render_submit_info *submit_info,
702    const struct pvr_srv_sync_prim *sync_prim,
703    struct rogue_fwif_cmd_ta *cmd,
704    const struct pvr_device_info *const dev_info)
705 {
706    const struct pvr_winsys_geometry_state *state = &submit_info->geometry;
707    uint32_t ext_stream_offset;
708 
709    memset(cmd, 0, sizeof(*cmd));
710 
711    cmd->cmd_shared.cmn.frame_num = submit_info->frame_num;
712 
713    ext_stream_offset = pvr_srv_geometry_cmd_stream_load(cmd,
714                                                         state->fw_stream,
715                                                         state->fw_stream_len,
716                                                         dev_info);
717 
718    if (ext_stream_offset < state->fw_stream_len) {
719       pvr_srv_geometry_cmd_ext_stream_load(cmd,
720                                            state->fw_stream,
721                                            state->fw_stream_len,
722                                            ext_stream_offset,
723                                            dev_info);
724    }
725 
726    if (state->flags.is_first_geometry)
727       cmd->flags |= ROGUE_FWIF_TAFLAGS_FIRSTKICK;
728 
729    if (state->flags.is_last_geometry)
730       cmd->flags |= ROGUE_FWIF_TAFLAGS_LASTKICK;
731 
732    if (state->flags.use_single_core)
733       cmd->flags |= ROGUE_FWIF_TAFLAGS_SINGLE_CORE;
734 
735    cmd->partial_render_ta_3d_fence.ufo_addr.addr =
736       pvr_srv_sync_prim_get_fw_addr(sync_prim);
737    cmd->partial_render_ta_3d_fence.value = sync_prim->value;
738 }
739 
740 static uint32_t
pvr_srv_fragment_cmd_stream_load(struct rogue_fwif_cmd_3d * const cmd,const uint8_t * const stream,const uint32_t stream_len,const struct pvr_device_info * const dev_info)741 pvr_srv_fragment_cmd_stream_load(struct rogue_fwif_cmd_3d *const cmd,
742                                  const uint8_t *const stream,
743                                  const uint32_t stream_len,
744                                  const struct pvr_device_info *const dev_info)
745 {
746    const uint32_t *stream_ptr = (const uint32_t *)stream;
747    struct rogue_fwif_3d_regs *const regs = &cmd->regs;
748    uint32_t main_stream_len =
749       pvr_csb_unpack((const uint64_t *)stream_ptr, KMD_STREAM_HDR).length;
750 
751    stream_ptr += pvr_cmd_length(KMD_STREAM_HDR);
752 
753    regs->isp_scissor_base = *(const uint64_t *)stream_ptr;
754    stream_ptr += pvr_cmd_length(CR_ISP_SCISSOR_BASE);
755 
756    regs->isp_dbias_base = *(const uint64_t *)stream_ptr;
757    stream_ptr += pvr_cmd_length(CR_ISP_DBIAS_BASE);
758 
759    regs->isp_oclqry_base = *(const uint64_t *)stream_ptr;
760    stream_ptr += pvr_cmd_length(CR_ISP_OCLQRY_BASE);
761 
762    regs->isp_zlsctl = *(const uint64_t *)stream_ptr;
763    stream_ptr += pvr_cmd_length(CR_ISP_ZLSCTL);
764 
765    regs->isp_zload_store_base = *(const uint64_t *)stream_ptr;
766    stream_ptr += pvr_cmd_length(CR_ISP_ZLOAD_BASE);
767 
768    regs->isp_stencil_load_store_base = *(const uint64_t *)stream_ptr;
769    stream_ptr += pvr_cmd_length(CR_ISP_STENCIL_LOAD_BASE);
770 
771    if (PVR_HAS_FEATURE(dev_info, requires_fb_cdc_zls_setup)) {
772       regs->fb_cdc_zls = *(const uint64_t *)stream_ptr;
773       stream_ptr += 2U;
774    }
775 
776    STATIC_ASSERT(ARRAY_SIZE(regs->pbe_word) == 8U);
777    STATIC_ASSERT(ARRAY_SIZE(regs->pbe_word[0]) == 3U);
778    STATIC_ASSERT(sizeof(regs->pbe_word[0][0]) == sizeof(uint64_t));
779    memcpy(regs->pbe_word, stream_ptr, sizeof(regs->pbe_word));
780    stream_ptr += 8U * 3U * 2U;
781 
782    regs->tpu_border_colour_table = *(const uint64_t *)stream_ptr;
783    stream_ptr += pvr_cmd_length(CR_TPU_BORDER_COLOUR_TABLE_PDM);
784 
785    STATIC_ASSERT(ARRAY_SIZE(regs->pds_bgnd) == 3U);
786    STATIC_ASSERT(sizeof(regs->pds_bgnd[0]) == sizeof(uint64_t));
787    memcpy(regs->pds_bgnd, stream_ptr, sizeof(regs->pds_bgnd));
788    stream_ptr += 3U * 2U;
789 
790    STATIC_ASSERT(ARRAY_SIZE(regs->pds_pr_bgnd) == 3U);
791    STATIC_ASSERT(sizeof(regs->pds_pr_bgnd[0]) == sizeof(uint64_t));
792    memcpy(regs->pds_pr_bgnd, stream_ptr, sizeof(regs->pds_pr_bgnd));
793    stream_ptr += 3U * 2U;
794 
795    STATIC_ASSERT(ARRAY_SIZE(regs->usc_clear_register) == 8U);
796    STATIC_ASSERT(sizeof(regs->usc_clear_register[0]) == sizeof(uint32_t));
797    memcpy(regs->usc_clear_register,
798           stream_ptr,
799           sizeof(regs->usc_clear_register));
800    stream_ptr += 8U;
801 
802    regs->usc_pixel_output_ctrl = *stream_ptr;
803    stream_ptr += pvr_cmd_length(CR_USC_PIXEL_OUTPUT_CTRL);
804 
805    regs->isp_bgobjdepth = *stream_ptr;
806    stream_ptr += pvr_cmd_length(CR_ISP_BGOBJDEPTH);
807 
808    regs->isp_bgobjvals = *stream_ptr;
809    stream_ptr += pvr_cmd_length(CR_ISP_BGOBJVALS);
810 
811    regs->isp_aa = *stream_ptr;
812    stream_ptr += pvr_cmd_length(CR_ISP_AA);
813 
814    regs->isp_ctl = *stream_ptr;
815    stream_ptr += pvr_cmd_length(CR_ISP_CTL);
816 
817    regs->event_pixel_pds_info = *stream_ptr;
818    stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_INFO);
819 
820    if (PVR_HAS_FEATURE(dev_info, cluster_grouping)) {
821       regs->pixel_phantom = *stream_ptr;
822       stream_ptr++;
823    }
824 
825    regs->view_idx = *stream_ptr;
826    stream_ptr++;
827 
828    regs->event_pixel_pds_data = *stream_ptr;
829    stream_ptr += pvr_cmd_length(CR_EVENT_PIXEL_PDS_DATA);
830 
831    if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) {
832       regs->isp_oclqry_stride = *stream_ptr;
833       stream_ptr++;
834    }
835 
836    if (PVR_HAS_FEATURE(dev_info, zls_subtile)) {
837       regs->isp_zls_pixels = *stream_ptr;
838       stream_ptr += pvr_cmd_length(CR_ISP_ZLS_PIXELS);
839    }
840 
841    cmd->zls_stride = *stream_ptr;
842    stream_ptr++;
843 
844    cmd->sls_stride = *stream_ptr;
845    stream_ptr++;
846 
847    if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) {
848       cmd->execute_count = *stream_ptr;
849       stream_ptr++;
850    }
851 
852    assert((const uint8_t *)stream_ptr - stream <= stream_len);
853    assert((const uint8_t *)stream_ptr - stream == main_stream_len);
854 
855    return main_stream_len;
856 }
857 
pvr_srv_fragment_cmd_ext_stream_load(struct rogue_fwif_cmd_3d * 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)858 static void pvr_srv_fragment_cmd_ext_stream_load(
859    struct rogue_fwif_cmd_3d *const cmd,
860    const uint8_t *const stream,
861    const uint32_t stream_len,
862    const uint32_t ext_stream_offset,
863    const struct pvr_device_info *const dev_info)
864 {
865    const uint32_t *ext_stream_ptr =
866       (const uint32_t *)((uint8_t *)stream + ext_stream_offset);
867    struct rogue_fwif_3d_regs *const regs = &cmd->regs;
868 
869    struct ROGUE_KMD_STREAM_EXTHDR_FRAG0 header0;
870 
871    header0 = pvr_csb_unpack(ext_stream_ptr, KMD_STREAM_EXTHDR_FRAG0);
872    ext_stream_ptr += pvr_cmd_length(KMD_STREAM_EXTHDR_FRAG0);
873 
874    assert(PVR_HAS_QUIRK(dev_info, 49927) == header0.has_brn49927);
875    if (header0.has_brn49927) {
876       regs->tpu = *ext_stream_ptr;
877       ext_stream_ptr += pvr_cmd_length(CR_TPU);
878    }
879 
880    assert((const uint8_t *)ext_stream_ptr - stream == stream_len);
881 }
882 
883 static void
pvr_srv_fragment_cmd_init(struct rogue_fwif_cmd_3d * cmd,const struct pvr_winsys_fragment_state * state,const struct pvr_device_info * dev_info,uint32_t frame_num)884 pvr_srv_fragment_cmd_init(struct rogue_fwif_cmd_3d *cmd,
885                           const struct pvr_winsys_fragment_state *state,
886                           const struct pvr_device_info *dev_info,
887                           uint32_t frame_num)
888 {
889    uint32_t ext_stream_offset;
890 
891    memset(cmd, 0, sizeof(*cmd));
892 
893    cmd->cmd_shared.cmn.frame_num = frame_num;
894 
895    ext_stream_offset = pvr_srv_fragment_cmd_stream_load(cmd,
896                                                         state->fw_stream,
897                                                         state->fw_stream_len,
898                                                         dev_info);
899 
900    if (ext_stream_offset < state->fw_stream_len) {
901       pvr_srv_fragment_cmd_ext_stream_load(cmd,
902                                            state->fw_stream,
903                                            state->fw_stream_len,
904                                            ext_stream_offset,
905                                            dev_info);
906    }
907 
908    if (state->flags.has_depth_buffer)
909       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_DEPTHBUFFER;
910 
911    if (state->flags.has_stencil_buffer)
912       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_STENCILBUFFER;
913 
914    if (state->flags.prevent_cdm_overlap)
915       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_PREVENT_CDM_OVERLAP;
916 
917    if (state->flags.use_single_core)
918       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_SINGLE_CORE;
919 
920    if (state->flags.get_vis_results)
921       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_GETVISRESULTS;
922 
923    if (state->flags.has_spm_scratch_buffer)
924       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_SPMSCRATCHBUFFER;
925 
926    if (state->flags.disable_pixel_merging)
927       cmd->flags |= ROGUE_FWIF_RENDERFLAGS_DISABLE_PIXELMERGE;
928 }
929 
pvr_srv_winsys_render_submit(const struct pvr_winsys_render_ctx * ctx,const struct pvr_winsys_render_submit_info * submit_info,const struct pvr_device_info * dev_info,struct vk_sync * signal_sync_geom,struct vk_sync * signal_sync_frag)930 VkResult pvr_srv_winsys_render_submit(
931    const struct pvr_winsys_render_ctx *ctx,
932    const struct pvr_winsys_render_submit_info *submit_info,
933    const struct pvr_device_info *dev_info,
934    struct vk_sync *signal_sync_geom,
935    struct vk_sync *signal_sync_frag)
936 {
937    const struct pvr_srv_winsys_rt_dataset *srv_rt_dataset =
938       to_pvr_srv_winsys_rt_dataset(submit_info->rt_dataset);
939    struct pvr_srv_sync_prim *sync_prim =
940       srv_rt_dataset->rt_datas[submit_info->rt_data_idx].sync_prim;
941    void *rt_data_handle =
942       srv_rt_dataset->rt_datas[submit_info->rt_data_idx].handle;
943    const struct pvr_srv_winsys_render_ctx *srv_ctx =
944       to_pvr_srv_winsys_render_ctx(ctx);
945    const struct pvr_srv_winsys *srv_ws = to_pvr_srv_winsys(ctx->ws);
946 
947    struct pvr_srv_sync *srv_signal_sync_geom;
948    struct pvr_srv_sync *srv_signal_sync_frag;
949 
950    struct rogue_fwif_cmd_ta geom_cmd;
951    struct rogue_fwif_cmd_3d frag_cmd = { 0 };
952    struct rogue_fwif_cmd_3d pr_cmd = { 0 };
953 
954    uint8_t *frag_cmd_ptr = NULL;
955    uint32_t frag_cmd_size = 0;
956 
957    uint32_t current_sync_value = sync_prim->value;
958    uint32_t geom_sync_update_value;
959    uint32_t frag_to_geom_fence_count = 0;
960    uint32_t frag_to_geom_fence_value;
961    uint32_t frag_sync_update_count = 0;
962    uint32_t frag_sync_update_value;
963 
964    int in_frag_fd = -1;
965    int in_geom_fd = -1;
966    int fence_frag;
967    int fence_geom;
968 
969    VkResult result;
970 
971    pvr_srv_geometry_cmd_init(submit_info, sync_prim, &geom_cmd, dev_info);
972 
973    pvr_srv_fragment_cmd_init(&pr_cmd,
974                              &submit_info->fragment_pr,
975                              dev_info,
976                              submit_info->frame_num);
977 
978    if (submit_info->has_fragment_job) {
979       pvr_srv_fragment_cmd_init(&frag_cmd,
980                                 &submit_info->fragment,
981                                 dev_info,
982                                 submit_info->frame_num);
983 
984       frag_cmd_ptr = (uint8_t *)&frag_cmd;
985       frag_cmd_size = sizeof(frag_cmd);
986    }
987 
988    if (submit_info->geometry.wait) {
989       struct pvr_srv_sync *srv_wait_sync =
990          to_srv_sync(submit_info->geometry.wait);
991 
992       if (srv_wait_sync->fd >= 0) {
993          in_geom_fd = dup(srv_wait_sync->fd);
994          if (in_geom_fd == -1) {
995             return vk_errorf(NULL,
996                              VK_ERROR_OUT_OF_HOST_MEMORY,
997                              "dup called on wait sync failed, Errno: %s",
998                              strerror(errno));
999          }
1000       }
1001    }
1002 
1003    if (submit_info->fragment.wait) {
1004       struct pvr_srv_sync *srv_wait_sync =
1005          to_srv_sync(submit_info->fragment.wait);
1006 
1007       if (srv_wait_sync->fd >= 0) {
1008          in_frag_fd = dup(srv_wait_sync->fd);
1009          if (in_frag_fd == -1) {
1010             return vk_errorf(NULL,
1011                              VK_ERROR_OUT_OF_HOST_MEMORY,
1012                              "dup called on wait sync failed, Errno: %s",
1013                              strerror(errno));
1014          }
1015       }
1016    }
1017 
1018    if (submit_info->geometry.flags.is_first_geometry) {
1019       frag_to_geom_fence_count = 1;
1020       frag_to_geom_fence_value = current_sync_value;
1021    }
1022 
1023    /* Geometery is always kicked */
1024    geom_sync_update_value = ++current_sync_value;
1025 
1026    if (submit_info->has_fragment_job) {
1027       frag_sync_update_count = 1;
1028       frag_sync_update_value = ++current_sync_value;
1029    }
1030 
1031    do {
1032       /* The fw allows the ZS and MSAA scratch buffers to be lazily allocated in
1033        * which case we need to provide a status update (i.e. if they are
1034        * physically backed or not) to the fw. In our case they will always be
1035        * physically backed so no need to inform the fw about their status and
1036        * pass in anything. We'll just pass in NULL.
1037        */
1038       result = pvr_srv_rgx_kick_render2(srv_ws->base.render_fd,
1039                                         srv_ctx->handle,
1040                                         frag_to_geom_fence_count,
1041                                         &sync_prim->ctx->block_handle,
1042                                         &sync_prim->offset,
1043                                         &frag_to_geom_fence_value,
1044                                         1,
1045                                         &sync_prim->ctx->block_handle,
1046                                         &sync_prim->offset,
1047                                         &geom_sync_update_value,
1048                                         frag_sync_update_count,
1049                                         &sync_prim->ctx->block_handle,
1050                                         &sync_prim->offset,
1051                                         &frag_sync_update_value,
1052                                         sync_prim->ctx->block_handle,
1053                                         sync_prim->offset,
1054                                         geom_sync_update_value,
1055                                         in_geom_fd,
1056                                         srv_ctx->timeline_geom,
1057                                         &fence_geom,
1058                                         "GEOM",
1059                                         in_frag_fd,
1060                                         srv_ctx->timeline_frag,
1061                                         &fence_frag,
1062                                         "FRAG",
1063                                         sizeof(geom_cmd),
1064                                         (uint8_t *)&geom_cmd,
1065                                         sizeof(pr_cmd),
1066                                         (uint8_t *)&pr_cmd,
1067                                         frag_cmd_size,
1068                                         frag_cmd_ptr,
1069                                         submit_info->job_num,
1070                                         /* Always kick the TA. */
1071                                         true,
1072                                         /* Always kick a PR. */
1073                                         true,
1074                                         submit_info->has_fragment_job,
1075                                         false,
1076                                         0,
1077                                         rt_data_handle,
1078                                         NULL,
1079                                         NULL,
1080                                         0,
1081                                         NULL,
1082                                         NULL,
1083                                         0,
1084                                         0,
1085                                         0,
1086                                         0,
1087                                         0);
1088    } while (result == VK_NOT_READY);
1089 
1090    if (result != VK_SUCCESS)
1091       goto end_close_in_fds;
1092 
1093    /* The job submission was succesful, update the sync prim value. */
1094    sync_prim->value = current_sync_value;
1095 
1096    if (signal_sync_geom) {
1097       srv_signal_sync_geom = to_srv_sync(signal_sync_geom);
1098       pvr_srv_set_sync_payload(srv_signal_sync_geom, fence_geom);
1099    } else if (fence_geom != -1) {
1100       close(fence_geom);
1101    }
1102 
1103    if (signal_sync_frag) {
1104       srv_signal_sync_frag = to_srv_sync(signal_sync_frag);
1105       pvr_srv_set_sync_payload(srv_signal_sync_frag, fence_frag);
1106    } else if (fence_frag != -1) {
1107       close(fence_frag);
1108    }
1109 
1110 end_close_in_fds:
1111    if (in_geom_fd >= 0)
1112       close(in_geom_fd);
1113 
1114    if (in_frag_fd >= 0)
1115       close(in_frag_fd);
1116 
1117    return result;
1118 }
1119