xref: /aosp_15_r20/external/mesa3d/src/asahi/vulkan/hk_queue.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright 2024 Valve Corporation
3*61046927SAndroid Build Coastguard Worker  * Copyright 2024 Alyssa Rosenzweig
4*61046927SAndroid Build Coastguard Worker  * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
5*61046927SAndroid Build Coastguard Worker  * Copyright 2024 Valve Corporation
6*61046927SAndroid Build Coastguard Worker  * Copyright 2024 Alyssa Rosenzweig
7*61046927SAndroid Build Coastguard Worker  * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
8*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
9*61046927SAndroid Build Coastguard Worker  */
10*61046927SAndroid Build Coastguard Worker #include "hk_queue.h"
11*61046927SAndroid Build Coastguard Worker 
12*61046927SAndroid Build Coastguard Worker #include "agx_bo.h"
13*61046927SAndroid Build Coastguard Worker #include "agx_device.h"
14*61046927SAndroid Build Coastguard Worker #include "agx_pack.h"
15*61046927SAndroid Build Coastguard Worker #include "decode.h"
16*61046927SAndroid Build Coastguard Worker #include "hk_cmd_buffer.h"
17*61046927SAndroid Build Coastguard Worker #include "hk_device.h"
18*61046927SAndroid Build Coastguard Worker #include "hk_physical_device.h"
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker #include <xf86drm.h>
21*61046927SAndroid Build Coastguard Worker #include "asahi/lib/unstable_asahi_drm.h"
22*61046927SAndroid Build Coastguard Worker #include "util/list.h"
23*61046927SAndroid Build Coastguard Worker #include "vulkan/vulkan_core.h"
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker #include "vk_drm_syncobj.h"
26*61046927SAndroid Build Coastguard Worker #include "vk_sync.h"
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker /*
29*61046927SAndroid Build Coastguard Worker  * We need to specially handle submits with no control streams. The kernel
30*61046927SAndroid Build Coastguard Worker  * can't accept empty submits, but we can end up here in Vulkan for
31*61046927SAndroid Build Coastguard Worker  * synchronization purposes only. Rather than submit a no-op job (slow),
32*61046927SAndroid Build Coastguard Worker  * we simply tie the fences together.
33*61046927SAndroid Build Coastguard Worker  */
34*61046927SAndroid Build Coastguard Worker static VkResult
queue_submit_empty(struct hk_device * dev,struct hk_queue * queue,struct vk_queue_submit * submit)35*61046927SAndroid Build Coastguard Worker queue_submit_empty(struct hk_device *dev, struct hk_queue *queue,
36*61046927SAndroid Build Coastguard Worker                    struct vk_queue_submit *submit)
37*61046927SAndroid Build Coastguard Worker {
38*61046927SAndroid Build Coastguard Worker    int fd = dev->dev.fd;
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker    /* Transfer the waits into the queue timeline. */
41*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < submit->wait_count; ++i) {
42*61046927SAndroid Build Coastguard Worker       struct vk_sync_wait *wait = &submit->waits[i];
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker       assert(vk_sync_type_is_drm_syncobj(wait->sync->type));
45*61046927SAndroid Build Coastguard Worker       const struct vk_drm_syncobj *syncobj = vk_sync_as_drm_syncobj(wait->sync);
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker       drmSyncobjTransfer(fd, queue->drm.syncobj, ++queue->drm.timeline_value,
48*61046927SAndroid Build Coastguard Worker                          syncobj->syncobj, wait->wait_value, 0);
49*61046927SAndroid Build Coastguard Worker    }
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker    /* Transfer the queue timeline into each out fence. They will all be
52*61046927SAndroid Build Coastguard Worker     * signalled when we reach this point.
53*61046927SAndroid Build Coastguard Worker     */
54*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < submit->signal_count; ++i) {
55*61046927SAndroid Build Coastguard Worker       struct vk_sync_signal *signal = &submit->signals[i];
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker       assert(vk_sync_type_is_drm_syncobj(signal->sync->type));
58*61046927SAndroid Build Coastguard Worker       const struct vk_drm_syncobj *syncobj =
59*61046927SAndroid Build Coastguard Worker          vk_sync_as_drm_syncobj(signal->sync);
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker       drmSyncobjTransfer(fd, syncobj->syncobj, signal->signal_value,
62*61046927SAndroid Build Coastguard Worker                          queue->drm.syncobj, queue->drm.timeline_value, 0);
63*61046927SAndroid Build Coastguard Worker    }
64*61046927SAndroid Build Coastguard Worker 
65*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
66*61046927SAndroid Build Coastguard Worker }
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker static void
asahi_fill_cdm_command(struct hk_device * dev,struct hk_cs * cs,struct drm_asahi_cmd_compute * cmd)69*61046927SAndroid Build Coastguard Worker asahi_fill_cdm_command(struct hk_device *dev, struct hk_cs *cs,
70*61046927SAndroid Build Coastguard Worker                        struct drm_asahi_cmd_compute *cmd)
71*61046927SAndroid Build Coastguard Worker {
72*61046927SAndroid Build Coastguard Worker    size_t len = cs->stream_linked ? 65536 /* XXX */ : (cs->current - cs->start);
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker    *cmd = (struct drm_asahi_cmd_compute){
75*61046927SAndroid Build Coastguard Worker       .encoder_ptr = cs->addr,
76*61046927SAndroid Build Coastguard Worker       .encoder_end = cs->addr + len,
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker       .sampler_array = dev->samplers.table.bo->va->addr,
79*61046927SAndroid Build Coastguard Worker       .sampler_count = dev->samplers.table.alloc,
80*61046927SAndroid Build Coastguard Worker       .sampler_max = dev->samplers.table.alloc + 1,
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker       .usc_base = dev->dev.shader_base,
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker       .encoder_id = agx_get_global_id(&dev->dev),
85*61046927SAndroid Build Coastguard Worker       .cmd_id = agx_get_global_id(&dev->dev),
86*61046927SAndroid Build Coastguard Worker       .unk_mask = 0xffffffff,
87*61046927SAndroid Build Coastguard Worker    };
88*61046927SAndroid Build Coastguard Worker 
89*61046927SAndroid Build Coastguard Worker    if (cs->scratch.cs.main || cs->scratch.cs.preamble) {
90*61046927SAndroid Build Coastguard Worker       cmd->helper_arg = dev->scratch.cs.buf->va->addr;
91*61046927SAndroid Build Coastguard Worker       cmd->helper_cfg = cs->scratch.cs.preamble << 16;
92*61046927SAndroid Build Coastguard Worker       cmd->helper_program = dev->dev.helper->va->addr | 1;
93*61046927SAndroid Build Coastguard Worker    }
94*61046927SAndroid Build Coastguard Worker }
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker static void
asahi_fill_vdm_command(struct hk_device * dev,struct hk_cs * cs,struct drm_asahi_cmd_render * c)97*61046927SAndroid Build Coastguard Worker asahi_fill_vdm_command(struct hk_device *dev, struct hk_cs *cs,
98*61046927SAndroid Build Coastguard Worker                        struct drm_asahi_cmd_render *c)
99*61046927SAndroid Build Coastguard Worker {
100*61046927SAndroid Build Coastguard Worker #if 0
101*61046927SAndroid Build Coastguard Worker    bool clear_pipeline_textures =
102*61046927SAndroid Build Coastguard Worker       agx_tilebuffer_spills(&batch->tilebuffer_layout);
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < batch->key.nr_cbufs; ++i) {
105*61046927SAndroid Build Coastguard Worker       struct pipe_surface *surf = batch->key.cbufs[i];
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker       clear_pipeline_textures |=
108*61046927SAndroid Build Coastguard Worker          surf && surf->texture && !(batch->clear & (PIPE_CLEAR_COLOR0 << i));
109*61046927SAndroid Build Coastguard Worker    }
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker #endif
112*61046927SAndroid Build Coastguard Worker    unsigned cmd_ta_id = agx_get_global_id(&dev->dev);
113*61046927SAndroid Build Coastguard Worker    unsigned cmd_3d_id = agx_get_global_id(&dev->dev);
114*61046927SAndroid Build Coastguard Worker    unsigned encoder_id = agx_get_global_id(&dev->dev);
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker    memset(c, 0, sizeof(*c));
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker    c->encoder_ptr = cs->addr;
119*61046927SAndroid Build Coastguard Worker    c->encoder_id = encoder_id;
120*61046927SAndroid Build Coastguard Worker    c->cmd_3d_id = cmd_3d_id;
121*61046927SAndroid Build Coastguard Worker    c->cmd_ta_id = cmd_ta_id;
122*61046927SAndroid Build Coastguard Worker    c->ppp_ctrl = 0x202;
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker    c->fragment_usc_base = dev->dev.shader_base;
125*61046927SAndroid Build Coastguard Worker    c->vertex_usc_base = c->fragment_usc_base;
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker    c->fb_width = cs->cr.width;
128*61046927SAndroid Build Coastguard Worker    c->fb_height = cs->cr.height;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker    c->isp_bgobjdepth = cs->cr.isp_bgobjdepth;
131*61046927SAndroid Build Coastguard Worker    c->isp_bgobjvals = cs->cr.isp_bgobjvals;
132*61046927SAndroid Build Coastguard Worker 
133*61046927SAndroid Build Coastguard Worker    static_assert(sizeof(c->zls_ctrl) == sizeof(cs->cr.zls_control));
134*61046927SAndroid Build Coastguard Worker    memcpy(&c->zls_ctrl, &cs->cr.zls_control, sizeof(cs->cr.zls_control));
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker    c->depth_dimensions = (cs->cr.width - 1) | ((cs->cr.height - 1) << 15);
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker    c->depth_buffer_load = cs->cr.depth.buffer;
139*61046927SAndroid Build Coastguard Worker    c->depth_buffer_store = cs->cr.depth.buffer;
140*61046927SAndroid Build Coastguard Worker    c->depth_buffer_partial = cs->cr.depth.buffer;
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker    c->depth_buffer_load_stride = cs->cr.depth.stride;
143*61046927SAndroid Build Coastguard Worker    c->depth_buffer_store_stride = cs->cr.depth.stride;
144*61046927SAndroid Build Coastguard Worker    c->depth_buffer_partial_stride = cs->cr.depth.stride;
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker    c->depth_meta_buffer_load = cs->cr.depth.meta;
147*61046927SAndroid Build Coastguard Worker    c->depth_meta_buffer_store = cs->cr.depth.meta;
148*61046927SAndroid Build Coastguard Worker    c->depth_meta_buffer_partial = cs->cr.depth.meta;
149*61046927SAndroid Build Coastguard Worker 
150*61046927SAndroid Build Coastguard Worker    c->depth_meta_buffer_load_stride = cs->cr.depth.stride;
151*61046927SAndroid Build Coastguard Worker    c->depth_meta_buffer_store_stride = cs->cr.depth.meta_stride;
152*61046927SAndroid Build Coastguard Worker    c->depth_meta_buffer_partial_stride = cs->cr.depth.meta_stride;
153*61046927SAndroid Build Coastguard Worker 
154*61046927SAndroid Build Coastguard Worker    c->stencil_buffer_load = cs->cr.stencil.buffer;
155*61046927SAndroid Build Coastguard Worker    c->stencil_buffer_store = cs->cr.stencil.buffer;
156*61046927SAndroid Build Coastguard Worker    c->stencil_buffer_partial = cs->cr.stencil.buffer;
157*61046927SAndroid Build Coastguard Worker 
158*61046927SAndroid Build Coastguard Worker    c->stencil_buffer_load_stride = cs->cr.stencil.stride;
159*61046927SAndroid Build Coastguard Worker    c->stencil_buffer_store_stride = cs->cr.stencil.stride;
160*61046927SAndroid Build Coastguard Worker    c->stencil_buffer_partial_stride = cs->cr.stencil.stride;
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker    c->stencil_meta_buffer_load = cs->cr.stencil.meta;
163*61046927SAndroid Build Coastguard Worker    c->stencil_meta_buffer_store = cs->cr.stencil.meta;
164*61046927SAndroid Build Coastguard Worker    c->stencil_meta_buffer_partial = cs->cr.stencil.meta;
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker    c->stencil_meta_buffer_load_stride = cs->cr.stencil.stride;
167*61046927SAndroid Build Coastguard Worker    c->stencil_meta_buffer_store_stride = cs->cr.stencil.meta_stride;
168*61046927SAndroid Build Coastguard Worker    c->stencil_meta_buffer_partial_stride = cs->cr.stencil.meta_stride;
169*61046927SAndroid Build Coastguard Worker 
170*61046927SAndroid Build Coastguard Worker    c->iogpu_unk_214 = cs->cr.iogpu_unk_214;
171*61046927SAndroid Build Coastguard Worker 
172*61046927SAndroid Build Coastguard Worker #if 0
173*61046927SAndroid Build Coastguard Worker    if (clear_pipeline_textures)
174*61046927SAndroid Build Coastguard Worker       c->flags |= ASAHI_RENDER_SET_WHEN_RELOADING_Z_OR_S;
175*61046927SAndroid Build Coastguard Worker    else
176*61046927SAndroid Build Coastguard Worker       c->flags |= ASAHI_RENDER_NO_CLEAR_PIPELINE_TEXTURES;
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker    if (zres && !(batch->clear & PIPE_CLEAR_DEPTH))
179*61046927SAndroid Build Coastguard Worker       c->flags |= ASAHI_RENDER_SET_WHEN_RELOADING_Z_OR_S;
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    if (sres && !(batch->clear & PIPE_CLEAR_STENCIL))
182*61046927SAndroid Build Coastguard Worker       c->flags |= ASAHI_RENDER_SET_WHEN_RELOADING_Z_OR_S;
183*61046927SAndroid Build Coastguard Worker #endif
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker    if (dev->dev.debug & AGX_DBG_NOCLUSTER)
186*61046927SAndroid Build Coastguard Worker       c->flags |= ASAHI_RENDER_NO_VERTEX_CLUSTERING;
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker #if 0
189*61046927SAndroid Build Coastguard Worker    /* XXX is this for just MSAA+Z+S or MSAA+(Z|S)? */
190*61046927SAndroid Build Coastguard Worker    if (tib->nr_samples > 1 && framebuffer->zsbuf)
191*61046927SAndroid Build Coastguard Worker       c->flags |= ASAHI_RENDER_MSAA_ZS;
192*61046927SAndroid Build Coastguard Worker #endif
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker    c->utile_width = cs->tib.tile_size.width;
195*61046927SAndroid Build Coastguard Worker    c->utile_height = cs->tib.tile_size.height;
196*61046927SAndroid Build Coastguard Worker 
197*61046927SAndroid Build Coastguard Worker    /* Can be 0 for attachmentless rendering with no draws */
198*61046927SAndroid Build Coastguard Worker    c->samples = MAX2(cs->tib.nr_samples, 1);
199*61046927SAndroid Build Coastguard Worker    c->layers = cs->cr.layers;
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker    c->ppp_multisamplectl = cs->ppp_multisamplectl;
202*61046927SAndroid Build Coastguard Worker    c->sample_size = cs->tib.sample_size_B;
203*61046927SAndroid Build Coastguard Worker    c->tib_blocks = ALIGN_POT(agx_tilebuffer_total_size(&cs->tib), 2048) / 2048;
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker    float tan_60 = 1.732051f;
206*61046927SAndroid Build Coastguard Worker    c->merge_upper_x = fui(tan_60 / cs->cr.width);
207*61046927SAndroid Build Coastguard Worker    c->merge_upper_y = fui(tan_60 / cs->cr.height);
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker    c->load_pipeline = cs->cr.bg.main.usc | 4;
210*61046927SAndroid Build Coastguard Worker    c->store_pipeline = cs->cr.eot.main.usc | 4;
211*61046927SAndroid Build Coastguard Worker    c->partial_reload_pipeline = cs->cr.bg.partial.usc | 4;
212*61046927SAndroid Build Coastguard Worker    c->partial_store_pipeline = cs->cr.eot.partial.usc | 4;
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker    memcpy(&c->load_pipeline_bind, &cs->cr.bg.main.counts,
215*61046927SAndroid Build Coastguard Worker           sizeof(struct agx_counts_packed));
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker    memcpy(&c->store_pipeline_bind, &cs->cr.eot.main.counts,
218*61046927SAndroid Build Coastguard Worker           sizeof(struct agx_counts_packed));
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker    memcpy(&c->partial_reload_pipeline_bind, &cs->cr.bg.partial.counts,
221*61046927SAndroid Build Coastguard Worker           sizeof(struct agx_counts_packed));
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker    memcpy(&c->partial_store_pipeline_bind, &cs->cr.eot.partial.counts,
224*61046927SAndroid Build Coastguard Worker           sizeof(struct agx_counts_packed));
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker    c->scissor_array = cs->uploaded_scissor;
227*61046927SAndroid Build Coastguard Worker    c->depth_bias_array = cs->uploaded_zbias;
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker    c->vertex_sampler_array = dev->samplers.table.bo->va->addr;
230*61046927SAndroid Build Coastguard Worker    c->vertex_sampler_count = dev->samplers.table.alloc;
231*61046927SAndroid Build Coastguard Worker    c->vertex_sampler_max = dev->samplers.table.alloc + 1;
232*61046927SAndroid Build Coastguard Worker 
233*61046927SAndroid Build Coastguard Worker    c->fragment_sampler_array = c->vertex_sampler_array;
234*61046927SAndroid Build Coastguard Worker    c->fragment_sampler_count = c->vertex_sampler_count;
235*61046927SAndroid Build Coastguard Worker    c->fragment_sampler_max = c->vertex_sampler_max;
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker    c->visibility_result_buffer = dev->occlusion_queries.bo->va->addr;
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    /* If a tile is empty, we do not want to process it, as the redundant
240*61046927SAndroid Build Coastguard Worker     * roundtrip of memory-->tilebuffer-->memory wastes a tremendous amount of
241*61046927SAndroid Build Coastguard Worker     * memory bandwidth. Any draw marks a tile as non-empty, so we only need to
242*61046927SAndroid Build Coastguard Worker     * process empty tiles if the background+EOT programs have a side effect.
243*61046927SAndroid Build Coastguard Worker     * This is the case exactly when there is an attachment we are clearing (some
244*61046927SAndroid Build Coastguard Worker     * attachment A in clear and in resolve <==> non-empty intersection).
245*61046927SAndroid Build Coastguard Worker     *
246*61046927SAndroid Build Coastguard Worker     * This case matters a LOT for performance in workloads that split batches.
247*61046927SAndroid Build Coastguard Worker     */
248*61046927SAndroid Build Coastguard Worker    if (true /* TODO */)
249*61046927SAndroid Build Coastguard Worker       c->flags |= ASAHI_RENDER_PROCESS_EMPTY_TILES;
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker    if (cs->scratch.vs.main || cs->scratch.vs.preamble) {
252*61046927SAndroid Build Coastguard Worker       c->flags |= ASAHI_RENDER_VERTEX_SPILLS;
253*61046927SAndroid Build Coastguard Worker       c->vertex_helper_arg = dev->scratch.vs.buf->va->addr;
254*61046927SAndroid Build Coastguard Worker       c->vertex_helper_cfg = cs->scratch.vs.preamble << 16;
255*61046927SAndroid Build Coastguard Worker       c->vertex_helper_program = dev->dev.helper->va->addr | 1;
256*61046927SAndroid Build Coastguard Worker    }
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker    if (cs->scratch.fs.main || cs->scratch.fs.preamble) {
259*61046927SAndroid Build Coastguard Worker       c->fragment_helper_arg = dev->scratch.fs.buf->va->addr;
260*61046927SAndroid Build Coastguard Worker       c->fragment_helper_cfg = cs->scratch.fs.preamble << 16;
261*61046927SAndroid Build Coastguard Worker       c->fragment_helper_program = dev->dev.helper->va->addr | 1;
262*61046927SAndroid Build Coastguard Worker    }
263*61046927SAndroid Build Coastguard Worker }
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker static void
asahi_fill_sync(struct drm_asahi_sync * sync,struct vk_sync * vk_sync,uint64_t value)266*61046927SAndroid Build Coastguard Worker asahi_fill_sync(struct drm_asahi_sync *sync, struct vk_sync *vk_sync,
267*61046927SAndroid Build Coastguard Worker                 uint64_t value)
268*61046927SAndroid Build Coastguard Worker {
269*61046927SAndroid Build Coastguard Worker    if (unlikely(!vk_sync_type_is_drm_syncobj(vk_sync->type))) {
270*61046927SAndroid Build Coastguard Worker       unreachable("Unsupported sync type");
271*61046927SAndroid Build Coastguard Worker       return;
272*61046927SAndroid Build Coastguard Worker    }
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker    const struct vk_drm_syncobj *syncobj = vk_sync_as_drm_syncobj(vk_sync);
275*61046927SAndroid Build Coastguard Worker    *sync = (struct drm_asahi_sync){.handle = syncobj->syncobj};
276*61046927SAndroid Build Coastguard Worker 
277*61046927SAndroid Build Coastguard Worker    if (vk_sync->flags & VK_SYNC_IS_TIMELINE) {
278*61046927SAndroid Build Coastguard Worker       sync->sync_type = DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ;
279*61046927SAndroid Build Coastguard Worker       sync->timeline_value = value;
280*61046927SAndroid Build Coastguard Worker    } else {
281*61046927SAndroid Build Coastguard Worker       sync->sync_type = DRM_ASAHI_SYNC_SYNCOBJ;
282*61046927SAndroid Build Coastguard Worker    }
283*61046927SAndroid Build Coastguard Worker }
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker union drm_asahi_cmd {
286*61046927SAndroid Build Coastguard Worker    struct drm_asahi_cmd_compute compute;
287*61046927SAndroid Build Coastguard Worker    struct drm_asahi_cmd_render render;
288*61046927SAndroid Build Coastguard Worker };
289*61046927SAndroid Build Coastguard Worker 
290*61046927SAndroid Build Coastguard Worker /* XXX: Batching multiple commands per submission is causing rare (7ppm) flakes
291*61046927SAndroid Build Coastguard Worker  * on the CTS once lossless compression is enabled. This needs to be
292*61046927SAndroid Build Coastguard Worker  * investigated before we can reenable this mechanism. We are likely missing a
293*61046927SAndroid Build Coastguard Worker  * cache flush or barrier somewhere.
294*61046927SAndroid Build Coastguard Worker  *
295*61046927SAndroid Build Coastguard Worker  * TODO: I think the actual maximum is 64. Can we query from the kernel?
296*61046927SAndroid Build Coastguard Worker  */
297*61046927SAndroid Build Coastguard Worker #define MAX_COMMANDS_PER_SUBMIT (1)
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker static VkResult
queue_submit_single(struct agx_device * dev,struct drm_asahi_submit * submit)300*61046927SAndroid Build Coastguard Worker queue_submit_single(struct agx_device *dev, struct drm_asahi_submit *submit)
301*61046927SAndroid Build Coastguard Worker {
302*61046927SAndroid Build Coastguard Worker    int ret = dev->ops.submit(dev, submit, 0);
303*61046927SAndroid Build Coastguard Worker 
304*61046927SAndroid Build Coastguard Worker    /* XXX: don't trap */
305*61046927SAndroid Build Coastguard Worker    if (ret) {
306*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "DRM_IOCTL_ASAHI_SUBMIT failed: %m\n");
307*61046927SAndroid Build Coastguard Worker       assert(0);
308*61046927SAndroid Build Coastguard Worker    }
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
311*61046927SAndroid Build Coastguard Worker }
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker /*
314*61046927SAndroid Build Coastguard Worker  * The kernel/firmware jointly impose a limit on commands per submit ioctl, but
315*61046927SAndroid Build Coastguard Worker  * we can build up arbitrarily large command buffers. We handle this here by
316*61046927SAndroid Build Coastguard Worker  * looping the ioctl, submitting slices of the command buffers that are within
317*61046927SAndroid Build Coastguard Worker  * bounds.
318*61046927SAndroid Build Coastguard Worker  */
319*61046927SAndroid Build Coastguard Worker static VkResult
queue_submit_looped(struct agx_device * dev,struct drm_asahi_submit * submit)320*61046927SAndroid Build Coastguard Worker queue_submit_looped(struct agx_device *dev, struct drm_asahi_submit *submit)
321*61046927SAndroid Build Coastguard Worker {
322*61046927SAndroid Build Coastguard Worker    struct drm_asahi_command *cmds = (void *)submit->commands;
323*61046927SAndroid Build Coastguard Worker    unsigned commands_remaining = submit->command_count;
324*61046927SAndroid Build Coastguard Worker    unsigned submitted_vdm = 0, submitted_cdm = 0;
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker    while (commands_remaining) {
327*61046927SAndroid Build Coastguard Worker       bool first = commands_remaining == submit->command_count;
328*61046927SAndroid Build Coastguard Worker       bool last = commands_remaining <= MAX_COMMANDS_PER_SUBMIT;
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker       unsigned count = MIN2(commands_remaining, MAX_COMMANDS_PER_SUBMIT);
331*61046927SAndroid Build Coastguard Worker       commands_remaining -= count;
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker       assert(!last || commands_remaining == 0);
334*61046927SAndroid Build Coastguard Worker       assert(count > 0);
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker       /* We need to fix up the barriers since barriers are ioctl-relative */
337*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < count; ++i) {
338*61046927SAndroid Build Coastguard Worker          assert(cmds[i].barriers[0] >= submitted_vdm);
339*61046927SAndroid Build Coastguard Worker          assert(cmds[i].barriers[1] >= submitted_cdm);
340*61046927SAndroid Build Coastguard Worker 
341*61046927SAndroid Build Coastguard Worker          cmds[i].barriers[0] -= submitted_vdm;
342*61046927SAndroid Build Coastguard Worker          cmds[i].barriers[1] -= submitted_cdm;
343*61046927SAndroid Build Coastguard Worker       }
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker       /* We can't signal the out-syncobjs until all prior work finishes. Since
346*61046927SAndroid Build Coastguard Worker        * only the last ioctl will signal, make sure it waits on prior ioctls.
347*61046927SAndroid Build Coastguard Worker        *
348*61046927SAndroid Build Coastguard Worker        * TODO: there might be a more performant way to do this.
349*61046927SAndroid Build Coastguard Worker        */
350*61046927SAndroid Build Coastguard Worker       if (last && !first) {
351*61046927SAndroid Build Coastguard Worker          if (cmds[0].barriers[0] == DRM_ASAHI_BARRIER_NONE)
352*61046927SAndroid Build Coastguard Worker             cmds[0].barriers[0] = 0;
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker          if (cmds[0].barriers[1] == DRM_ASAHI_BARRIER_NONE)
355*61046927SAndroid Build Coastguard Worker             cmds[0].barriers[1] = 0;
356*61046927SAndroid Build Coastguard Worker       }
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker       struct drm_asahi_submit submit_ioctl = {
359*61046927SAndroid Build Coastguard Worker          .flags = submit->flags,
360*61046927SAndroid Build Coastguard Worker          .queue_id = submit->queue_id,
361*61046927SAndroid Build Coastguard Worker          .result_handle = submit->result_handle,
362*61046927SAndroid Build Coastguard Worker          .commands = (uint64_t)(uintptr_t)(cmds),
363*61046927SAndroid Build Coastguard Worker          .command_count = count,
364*61046927SAndroid Build Coastguard Worker          .in_syncs = first ? submit->in_syncs : 0,
365*61046927SAndroid Build Coastguard Worker          .in_sync_count = first ? submit->in_sync_count : 0,
366*61046927SAndroid Build Coastguard Worker          .out_syncs = last ? submit->out_syncs : 0,
367*61046927SAndroid Build Coastguard Worker          .out_sync_count = last ? submit->out_sync_count : 0,
368*61046927SAndroid Build Coastguard Worker       };
369*61046927SAndroid Build Coastguard Worker 
370*61046927SAndroid Build Coastguard Worker       VkResult result = queue_submit_single(dev, &submit_ioctl);
371*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
372*61046927SAndroid Build Coastguard Worker          return result;
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < count; ++i) {
375*61046927SAndroid Build Coastguard Worker          if (cmds[i].cmd_type == DRM_ASAHI_CMD_COMPUTE)
376*61046927SAndroid Build Coastguard Worker             submitted_cdm++;
377*61046927SAndroid Build Coastguard Worker          else if (cmds[i].cmd_type == DRM_ASAHI_CMD_RENDER)
378*61046927SAndroid Build Coastguard Worker             submitted_vdm++;
379*61046927SAndroid Build Coastguard Worker          else
380*61046927SAndroid Build Coastguard Worker             unreachable("unknown subqueue");
381*61046927SAndroid Build Coastguard Worker       }
382*61046927SAndroid Build Coastguard Worker 
383*61046927SAndroid Build Coastguard Worker       cmds += count;
384*61046927SAndroid Build Coastguard Worker    }
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
387*61046927SAndroid Build Coastguard Worker }
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker static VkResult
queue_submit(struct hk_device * dev,struct hk_queue * queue,struct vk_queue_submit * submit)390*61046927SAndroid Build Coastguard Worker queue_submit(struct hk_device *dev, struct hk_queue *queue,
391*61046927SAndroid Build Coastguard Worker              struct vk_queue_submit *submit)
392*61046927SAndroid Build Coastguard Worker {
393*61046927SAndroid Build Coastguard Worker    unsigned command_count = 0;
394*61046927SAndroid Build Coastguard Worker 
395*61046927SAndroid Build Coastguard Worker    /* Gather the number of individual commands to submit up front */
396*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < submit->command_buffer_count; ++i) {
397*61046927SAndroid Build Coastguard Worker       struct hk_cmd_buffer *cmdbuf =
398*61046927SAndroid Build Coastguard Worker          (struct hk_cmd_buffer *)submit->command_buffers[i];
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker       command_count += list_length(&cmdbuf->control_streams);
401*61046927SAndroid Build Coastguard Worker    }
402*61046927SAndroid Build Coastguard Worker 
403*61046927SAndroid Build Coastguard Worker    if (command_count == 0)
404*61046927SAndroid Build Coastguard Worker       return queue_submit_empty(dev, queue, submit);
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker    unsigned wait_count = 0;
407*61046927SAndroid Build Coastguard Worker    struct drm_asahi_sync *waits =
408*61046927SAndroid Build Coastguard Worker       alloca(submit->wait_count * sizeof(struct drm_asahi_sync));
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker    struct drm_asahi_sync *signals =
411*61046927SAndroid Build Coastguard Worker       alloca((submit->signal_count + 1) * sizeof(struct drm_asahi_sync));
412*61046927SAndroid Build Coastguard Worker 
413*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < submit->wait_count; ++i) {
414*61046927SAndroid Build Coastguard Worker       /* The kernel rejects the submission if we try to wait on the same
415*61046927SAndroid Build Coastguard Worker        * timeline semaphore at multiple points.
416*61046927SAndroid Build Coastguard Worker        *
417*61046927SAndroid Build Coastguard Worker        * TODO: Can we relax the UAPI?
418*61046927SAndroid Build Coastguard Worker        *
419*61046927SAndroid Build Coastguard Worker        * XXX: This is quadratic time.
420*61046927SAndroid Build Coastguard Worker        */
421*61046927SAndroid Build Coastguard Worker       bool skip = false;
422*61046927SAndroid Build Coastguard Worker       if (submit->waits[i].sync->flags & VK_SYNC_IS_TIMELINE) {
423*61046927SAndroid Build Coastguard Worker          uint32_t v1 = submit->waits[i].wait_value;
424*61046927SAndroid Build Coastguard Worker          for (unsigned j = 0; j < submit->wait_count; ++j) {
425*61046927SAndroid Build Coastguard Worker             uint32_t v2 = submit->waits[j].wait_value;
426*61046927SAndroid Build Coastguard Worker             if (i != j && submit->waits[i].sync == submit->waits[j].sync &&
427*61046927SAndroid Build Coastguard Worker                 (v1 < v2 || (v1 == v2 && i < j))) {
428*61046927SAndroid Build Coastguard Worker                skip = true;
429*61046927SAndroid Build Coastguard Worker                break;
430*61046927SAndroid Build Coastguard Worker             }
431*61046927SAndroid Build Coastguard Worker          }
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker          if (skip)
434*61046927SAndroid Build Coastguard Worker             continue;
435*61046927SAndroid Build Coastguard Worker       }
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker       asahi_fill_sync(&waits[wait_count++], submit->waits[i].sync,
438*61046927SAndroid Build Coastguard Worker                       submit->waits[i].wait_value);
439*61046927SAndroid Build Coastguard Worker    }
440*61046927SAndroid Build Coastguard Worker 
441*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < submit->signal_count; ++i) {
442*61046927SAndroid Build Coastguard Worker       asahi_fill_sync(&signals[i], submit->signals[i].sync,
443*61046927SAndroid Build Coastguard Worker                       submit->signals[i].signal_value);
444*61046927SAndroid Build Coastguard Worker    }
445*61046927SAndroid Build Coastguard Worker 
446*61046927SAndroid Build Coastguard Worker    /* Signal progress on the queue itself */
447*61046927SAndroid Build Coastguard Worker    signals[submit->signal_count] = (struct drm_asahi_sync){
448*61046927SAndroid Build Coastguard Worker       .sync_type = DRM_ASAHI_SYNC_TIMELINE_SYNCOBJ,
449*61046927SAndroid Build Coastguard Worker       .handle = queue->drm.syncobj,
450*61046927SAndroid Build Coastguard Worker       .timeline_value = ++queue->drm.timeline_value,
451*61046927SAndroid Build Coastguard Worker    };
452*61046927SAndroid Build Coastguard Worker 
453*61046927SAndroid Build Coastguard Worker    /* Now setup the command structs */
454*61046927SAndroid Build Coastguard Worker    struct drm_asahi_command *cmds = alloca(sizeof(*cmds) * command_count);
455*61046927SAndroid Build Coastguard Worker    union drm_asahi_cmd *cmds_inner =
456*61046927SAndroid Build Coastguard Worker       alloca(sizeof(*cmds_inner) * command_count);
457*61046927SAndroid Build Coastguard Worker 
458*61046927SAndroid Build Coastguard Worker    unsigned cmd_it = 0;
459*61046927SAndroid Build Coastguard Worker    unsigned nr_vdm = 0, nr_cdm = 0;
460*61046927SAndroid Build Coastguard Worker 
461*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < submit->command_buffer_count; ++i) {
462*61046927SAndroid Build Coastguard Worker       struct hk_cmd_buffer *cmdbuf =
463*61046927SAndroid Build Coastguard Worker          (struct hk_cmd_buffer *)submit->command_buffers[i];
464*61046927SAndroid Build Coastguard Worker 
465*61046927SAndroid Build Coastguard Worker       list_for_each_entry(struct hk_cs, cs, &cmdbuf->control_streams, node) {
466*61046927SAndroid Build Coastguard Worker          assert(cmd_it < command_count);
467*61046927SAndroid Build Coastguard Worker 
468*61046927SAndroid Build Coastguard Worker          struct drm_asahi_command cmd = {
469*61046927SAndroid Build Coastguard Worker             .cmd_buffer = (uint64_t)(uintptr_t)&cmds_inner[cmd_it],
470*61046927SAndroid Build Coastguard Worker             .result_offset = 0 /* TODO */,
471*61046927SAndroid Build Coastguard Worker             .result_size = 0 /* TODO */,
472*61046927SAndroid Build Coastguard Worker             /* Barrier on previous command */
473*61046927SAndroid Build Coastguard Worker             .barriers = {nr_vdm, nr_cdm},
474*61046927SAndroid Build Coastguard Worker          };
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker          if (cs->type == HK_CS_CDM) {
477*61046927SAndroid Build Coastguard Worker             cmd.cmd_type = DRM_ASAHI_CMD_COMPUTE;
478*61046927SAndroid Build Coastguard Worker             cmd.cmd_buffer_size = sizeof(struct drm_asahi_cmd_compute);
479*61046927SAndroid Build Coastguard Worker             nr_cdm++;
480*61046927SAndroid Build Coastguard Worker 
481*61046927SAndroid Build Coastguard Worker             asahi_fill_cdm_command(dev, cs, &cmds_inner[cmd_it].compute);
482*61046927SAndroid Build Coastguard Worker          } else {
483*61046927SAndroid Build Coastguard Worker             assert(cs->type == HK_CS_VDM);
484*61046927SAndroid Build Coastguard Worker             cmd.cmd_type = DRM_ASAHI_CMD_RENDER;
485*61046927SAndroid Build Coastguard Worker             cmd.cmd_buffer_size = sizeof(struct drm_asahi_cmd_render);
486*61046927SAndroid Build Coastguard Worker             nr_vdm++;
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker             asahi_fill_vdm_command(dev, cs, &cmds_inner[cmd_it].render);
489*61046927SAndroid Build Coastguard Worker          }
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker          cmds[cmd_it++] = cmd;
492*61046927SAndroid Build Coastguard Worker       }
493*61046927SAndroid Build Coastguard Worker    }
494*61046927SAndroid Build Coastguard Worker 
495*61046927SAndroid Build Coastguard Worker    assert(cmd_it == command_count);
496*61046927SAndroid Build Coastguard Worker 
497*61046927SAndroid Build Coastguard Worker    if (dev->dev.debug & AGX_DBG_TRACE) {
498*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < command_count; ++i) {
499*61046927SAndroid Build Coastguard Worker          if (cmds[i].cmd_type == DRM_ASAHI_CMD_COMPUTE) {
500*61046927SAndroid Build Coastguard Worker             agxdecode_drm_cmd_compute(dev->dev.agxdecode, &dev->dev.params,
501*61046927SAndroid Build Coastguard Worker                                       &cmds_inner[i].compute, true);
502*61046927SAndroid Build Coastguard Worker          } else {
503*61046927SAndroid Build Coastguard Worker             assert(cmds[i].cmd_type == DRM_ASAHI_CMD_RENDER);
504*61046927SAndroid Build Coastguard Worker             agxdecode_drm_cmd_render(dev->dev.agxdecode, &dev->dev.params,
505*61046927SAndroid Build Coastguard Worker                                      &cmds_inner[i].render, true);
506*61046927SAndroid Build Coastguard Worker          }
507*61046927SAndroid Build Coastguard Worker       }
508*61046927SAndroid Build Coastguard Worker 
509*61046927SAndroid Build Coastguard Worker       agxdecode_image_heap(dev->dev.agxdecode, dev->images.bo->va->addr,
510*61046927SAndroid Build Coastguard Worker                            dev->images.alloc);
511*61046927SAndroid Build Coastguard Worker 
512*61046927SAndroid Build Coastguard Worker       agxdecode_next_frame();
513*61046927SAndroid Build Coastguard Worker    }
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker    struct drm_asahi_submit submit_ioctl = {
516*61046927SAndroid Build Coastguard Worker       .flags = 0,
517*61046927SAndroid Build Coastguard Worker       .queue_id = queue->drm.id,
518*61046927SAndroid Build Coastguard Worker       .result_handle = 0 /* TODO */,
519*61046927SAndroid Build Coastguard Worker       .in_sync_count = wait_count,
520*61046927SAndroid Build Coastguard Worker       .out_sync_count = submit->signal_count + 1,
521*61046927SAndroid Build Coastguard Worker       .command_count = command_count,
522*61046927SAndroid Build Coastguard Worker       .in_syncs = (uint64_t)(uintptr_t)(waits),
523*61046927SAndroid Build Coastguard Worker       .out_syncs = (uint64_t)(uintptr_t)(signals),
524*61046927SAndroid Build Coastguard Worker       .commands = (uint64_t)(uintptr_t)(cmds),
525*61046927SAndroid Build Coastguard Worker    };
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker    if (command_count <= MAX_COMMANDS_PER_SUBMIT)
528*61046927SAndroid Build Coastguard Worker       return queue_submit_single(&dev->dev, &submit_ioctl);
529*61046927SAndroid Build Coastguard Worker    else
530*61046927SAndroid Build Coastguard Worker       return queue_submit_looped(&dev->dev, &submit_ioctl);
531*61046927SAndroid Build Coastguard Worker }
532*61046927SAndroid Build Coastguard Worker 
533*61046927SAndroid Build Coastguard Worker static VkResult
hk_queue_submit(struct vk_queue * vk_queue,struct vk_queue_submit * submit)534*61046927SAndroid Build Coastguard Worker hk_queue_submit(struct vk_queue *vk_queue, struct vk_queue_submit *submit)
535*61046927SAndroid Build Coastguard Worker {
536*61046927SAndroid Build Coastguard Worker    struct hk_queue *queue = container_of(vk_queue, struct hk_queue, vk);
537*61046927SAndroid Build Coastguard Worker    struct hk_device *dev = hk_queue_device(queue);
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker    if (vk_queue_is_lost(&queue->vk))
540*61046927SAndroid Build Coastguard Worker       return VK_ERROR_DEVICE_LOST;
541*61046927SAndroid Build Coastguard Worker 
542*61046927SAndroid Build Coastguard Worker    VkResult result = queue_submit(dev, queue, submit);
543*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
544*61046927SAndroid Build Coastguard Worker       return vk_queue_set_lost(&queue->vk, "Submit failed");
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
547*61046927SAndroid Build Coastguard Worker }
548*61046927SAndroid Build Coastguard Worker 
549*61046927SAndroid Build Coastguard Worker VkResult
hk_queue_init(struct hk_device * dev,struct hk_queue * queue,const VkDeviceQueueCreateInfo * pCreateInfo,uint32_t index_in_family)550*61046927SAndroid Build Coastguard Worker hk_queue_init(struct hk_device *dev, struct hk_queue *queue,
551*61046927SAndroid Build Coastguard Worker               const VkDeviceQueueCreateInfo *pCreateInfo,
552*61046927SAndroid Build Coastguard Worker               uint32_t index_in_family)
553*61046927SAndroid Build Coastguard Worker {
554*61046927SAndroid Build Coastguard Worker    struct hk_physical_device *pdev = hk_device_physical(dev);
555*61046927SAndroid Build Coastguard Worker    VkResult result;
556*61046927SAndroid Build Coastguard Worker 
557*61046927SAndroid Build Coastguard Worker    assert(pCreateInfo->queueFamilyIndex < pdev->queue_family_count);
558*61046927SAndroid Build Coastguard Worker 
559*61046927SAndroid Build Coastguard Worker    const VkDeviceQueueGlobalPriorityCreateInfoKHR *priority_info =
560*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext,
561*61046927SAndroid Build Coastguard Worker                            DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR);
562*61046927SAndroid Build Coastguard Worker    const enum VkQueueGlobalPriorityKHR global_priority =
563*61046927SAndroid Build Coastguard Worker       priority_info ? priority_info->globalPriority
564*61046927SAndroid Build Coastguard Worker                     : VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR;
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker    if (global_priority != VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR) {
567*61046927SAndroid Build Coastguard Worker       return VK_ERROR_INITIALIZATION_FAILED;
568*61046927SAndroid Build Coastguard Worker    }
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker    result = vk_queue_init(&queue->vk, &dev->vk, pCreateInfo, index_in_family);
571*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
572*61046927SAndroid Build Coastguard Worker       return result;
573*61046927SAndroid Build Coastguard Worker 
574*61046927SAndroid Build Coastguard Worker    queue->vk.driver_submit = hk_queue_submit;
575*61046927SAndroid Build Coastguard Worker 
576*61046927SAndroid Build Coastguard Worker    queue->drm.id = agx_create_command_queue(&dev->dev,
577*61046927SAndroid Build Coastguard Worker                                             DRM_ASAHI_QUEUE_CAP_RENDER |
578*61046927SAndroid Build Coastguard Worker                                                DRM_ASAHI_QUEUE_CAP_BLIT |
579*61046927SAndroid Build Coastguard Worker                                                DRM_ASAHI_QUEUE_CAP_COMPUTE,
580*61046927SAndroid Build Coastguard Worker                                             2);
581*61046927SAndroid Build Coastguard Worker 
582*61046927SAndroid Build Coastguard Worker    if (drmSyncobjCreate(dev->dev.fd, 0, &queue->drm.syncobj)) {
583*61046927SAndroid Build Coastguard Worker       mesa_loge("drmSyncobjCreate() failed %d\n", errno);
584*61046927SAndroid Build Coastguard Worker       agx_destroy_command_queue(&dev->dev, queue->drm.id);
585*61046927SAndroid Build Coastguard Worker       vk_queue_finish(&queue->vk);
586*61046927SAndroid Build Coastguard Worker 
587*61046927SAndroid Build Coastguard Worker       return vk_errorf(dev, VK_ERROR_OUT_OF_HOST_MEMORY,
588*61046927SAndroid Build Coastguard Worker                        "DRM_IOCTL_SYNCOBJ_CREATE failed: %m");
589*61046927SAndroid Build Coastguard Worker    }
590*61046927SAndroid Build Coastguard Worker 
591*61046927SAndroid Build Coastguard Worker    uint64_t initial_value = 1;
592*61046927SAndroid Build Coastguard Worker    if (drmSyncobjTimelineSignal(dev->dev.fd, &queue->drm.syncobj,
593*61046927SAndroid Build Coastguard Worker                                 &initial_value, 1)) {
594*61046927SAndroid Build Coastguard Worker       hk_queue_finish(dev, queue);
595*61046927SAndroid Build Coastguard Worker       return vk_errorf(dev, VK_ERROR_OUT_OF_HOST_MEMORY,
596*61046927SAndroid Build Coastguard Worker                        "DRM_IOCTL_TIMELINE_SYNCOBJ_SIGNAL failed: %m");
597*61046927SAndroid Build Coastguard Worker    }
598*61046927SAndroid Build Coastguard Worker 
599*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
600*61046927SAndroid Build Coastguard Worker }
601*61046927SAndroid Build Coastguard Worker 
602*61046927SAndroid Build Coastguard Worker void
hk_queue_finish(struct hk_device * dev,struct hk_queue * queue)603*61046927SAndroid Build Coastguard Worker hk_queue_finish(struct hk_device *dev, struct hk_queue *queue)
604*61046927SAndroid Build Coastguard Worker {
605*61046927SAndroid Build Coastguard Worker    drmSyncobjDestroy(dev->dev.fd, queue->drm.syncobj);
606*61046927SAndroid Build Coastguard Worker    agx_destroy_command_queue(&dev->dev, queue->drm.id);
607*61046927SAndroid Build Coastguard Worker    vk_queue_finish(&queue->vk);
608*61046927SAndroid Build Coastguard Worker }
609