xref: /aosp_15_r20/external/mesa3d/src/freedreno/vulkan/tu_cs.cc (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2019 Google LLC
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include "tu_cs.h"
7*61046927SAndroid Build Coastguard Worker 
8*61046927SAndroid Build Coastguard Worker #include "tu_device.h"
9*61046927SAndroid Build Coastguard Worker #include "tu_rmv.h"
10*61046927SAndroid Build Coastguard Worker #include "tu_suballoc.h"
11*61046927SAndroid Build Coastguard Worker 
12*61046927SAndroid Build Coastguard Worker /**
13*61046927SAndroid Build Coastguard Worker  * Initialize a command stream.
14*61046927SAndroid Build Coastguard Worker  */
15*61046927SAndroid Build Coastguard Worker void
tu_cs_init(struct tu_cs * cs,struct tu_device * device,enum tu_cs_mode mode,uint32_t initial_size,const char * name)16*61046927SAndroid Build Coastguard Worker tu_cs_init(struct tu_cs *cs,
17*61046927SAndroid Build Coastguard Worker            struct tu_device *device,
18*61046927SAndroid Build Coastguard Worker            enum tu_cs_mode mode,
19*61046927SAndroid Build Coastguard Worker            uint32_t initial_size, const char *name)
20*61046927SAndroid Build Coastguard Worker {
21*61046927SAndroid Build Coastguard Worker    assert(mode != TU_CS_MODE_EXTERNAL);
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker    memset(cs, 0, sizeof(*cs));
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker    cs->device = device;
26*61046927SAndroid Build Coastguard Worker    cs->mode = mode;
27*61046927SAndroid Build Coastguard Worker    cs->next_bo_size = initial_size;
28*61046927SAndroid Build Coastguard Worker    cs->name = name;
29*61046927SAndroid Build Coastguard Worker }
30*61046927SAndroid Build Coastguard Worker 
31*61046927SAndroid Build Coastguard Worker /**
32*61046927SAndroid Build Coastguard Worker  * Initialize a command stream as a wrapper to an external buffer.
33*61046927SAndroid Build Coastguard Worker  */
34*61046927SAndroid Build Coastguard Worker void
tu_cs_init_external(struct tu_cs * cs,struct tu_device * device,uint32_t * start,uint32_t * end,uint64_t iova,bool writeable)35*61046927SAndroid Build Coastguard Worker tu_cs_init_external(struct tu_cs *cs, struct tu_device *device,
36*61046927SAndroid Build Coastguard Worker                     uint32_t *start, uint32_t *end, uint64_t iova,
37*61046927SAndroid Build Coastguard Worker                     bool writeable)
38*61046927SAndroid Build Coastguard Worker {
39*61046927SAndroid Build Coastguard Worker    memset(cs, 0, sizeof(*cs));
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker    cs->device = device;
42*61046927SAndroid Build Coastguard Worker    cs->mode = TU_CS_MODE_EXTERNAL;
43*61046927SAndroid Build Coastguard Worker    cs->start = cs->reserved_end = cs->cur = start;
44*61046927SAndroid Build Coastguard Worker    cs->end = end;
45*61046927SAndroid Build Coastguard Worker    cs->external_iova = iova;
46*61046927SAndroid Build Coastguard Worker    cs->writeable = writeable;
47*61046927SAndroid Build Coastguard Worker }
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker /**
50*61046927SAndroid Build Coastguard Worker  * Initialize a sub-command stream as a wrapper to an externally sub-allocated
51*61046927SAndroid Build Coastguard Worker  * buffer.
52*61046927SAndroid Build Coastguard Worker  */
53*61046927SAndroid Build Coastguard Worker void
tu_cs_init_suballoc(struct tu_cs * cs,struct tu_device * device,struct tu_suballoc_bo * suballoc_bo)54*61046927SAndroid Build Coastguard Worker tu_cs_init_suballoc(struct tu_cs *cs, struct tu_device *device,
55*61046927SAndroid Build Coastguard Worker                     struct tu_suballoc_bo *suballoc_bo)
56*61046927SAndroid Build Coastguard Worker {
57*61046927SAndroid Build Coastguard Worker    uint32_t *start = (uint32_t *) tu_suballoc_bo_map(suballoc_bo);
58*61046927SAndroid Build Coastguard Worker    uint32_t *end = start + (suballoc_bo->size >> 2);
59*61046927SAndroid Build Coastguard Worker 
60*61046927SAndroid Build Coastguard Worker    memset(cs, 0, sizeof(*cs));
61*61046927SAndroid Build Coastguard Worker    cs->device = device;
62*61046927SAndroid Build Coastguard Worker    cs->mode = TU_CS_MODE_SUB_STREAM;
63*61046927SAndroid Build Coastguard Worker    cs->start = cs->reserved_end = cs->cur = start;
64*61046927SAndroid Build Coastguard Worker    cs->end = end;
65*61046927SAndroid Build Coastguard Worker    cs->refcount_bo = tu_bo_get_ref(suballoc_bo->bo);
66*61046927SAndroid Build Coastguard Worker }
67*61046927SAndroid Build Coastguard Worker 
68*61046927SAndroid Build Coastguard Worker /**
69*61046927SAndroid Build Coastguard Worker  * Finish and release all resources owned by a command stream.
70*61046927SAndroid Build Coastguard Worker  */
71*61046927SAndroid Build Coastguard Worker void
tu_cs_finish(struct tu_cs * cs)72*61046927SAndroid Build Coastguard Worker tu_cs_finish(struct tu_cs *cs)
73*61046927SAndroid Build Coastguard Worker {
74*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < cs->read_only.bo_count; ++i) {
75*61046927SAndroid Build Coastguard Worker       TU_RMV(resource_destroy, cs->device, cs->read_only.bos[i]);
76*61046927SAndroid Build Coastguard Worker       tu_bo_finish(cs->device, cs->read_only.bos[i]);
77*61046927SAndroid Build Coastguard Worker    }
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < cs->read_write.bo_count; ++i) {
80*61046927SAndroid Build Coastguard Worker       TU_RMV(resource_destroy, cs->device, cs->read_write.bos[i]);
81*61046927SAndroid Build Coastguard Worker       tu_bo_finish(cs->device, cs->read_write.bos[i]);
82*61046927SAndroid Build Coastguard Worker    }
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    if (cs->refcount_bo)
85*61046927SAndroid Build Coastguard Worker       tu_bo_finish(cs->device, cs->refcount_bo);
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker    free(cs->entries);
88*61046927SAndroid Build Coastguard Worker    free(cs->read_only.bos);
89*61046927SAndroid Build Coastguard Worker    free(cs->read_write.bos);
90*61046927SAndroid Build Coastguard Worker }
91*61046927SAndroid Build Coastguard Worker 
92*61046927SAndroid Build Coastguard Worker static struct tu_bo *
tu_cs_current_bo(const struct tu_cs * cs)93*61046927SAndroid Build Coastguard Worker tu_cs_current_bo(const struct tu_cs *cs)
94*61046927SAndroid Build Coastguard Worker {
95*61046927SAndroid Build Coastguard Worker    if (cs->refcount_bo) {
96*61046927SAndroid Build Coastguard Worker       return cs->refcount_bo;
97*61046927SAndroid Build Coastguard Worker    } else {
98*61046927SAndroid Build Coastguard Worker       const struct tu_bo_array *bos = cs->writeable ? &cs->read_write : &cs->read_only;
99*61046927SAndroid Build Coastguard Worker       assert(bos->bo_count);
100*61046927SAndroid Build Coastguard Worker       return bos->bos[bos->bo_count - 1];
101*61046927SAndroid Build Coastguard Worker    }
102*61046927SAndroid Build Coastguard Worker }
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker /**
105*61046927SAndroid Build Coastguard Worker  * Get the offset of the command packets emitted since the last call to
106*61046927SAndroid Build Coastguard Worker  * tu_cs_add_entry.
107*61046927SAndroid Build Coastguard Worker  */
108*61046927SAndroid Build Coastguard Worker static uint32_t
tu_cs_get_offset(const struct tu_cs * cs)109*61046927SAndroid Build Coastguard Worker tu_cs_get_offset(const struct tu_cs *cs)
110*61046927SAndroid Build Coastguard Worker {
111*61046927SAndroid Build Coastguard Worker    const struct tu_bo_array *bos = cs->writeable ? &cs->read_write : &cs->read_only;
112*61046927SAndroid Build Coastguard Worker    return (cs->refcount_bo || bos->bo_count != 0) ? cs->start - (uint32_t *) tu_cs_current_bo(cs)->map : 0;
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker /* Get the iova for the next dword to be emitted. Useful after
116*61046927SAndroid Build Coastguard Worker  * tu_cs_reserve_space() to create a patch point that can be overwritten on
117*61046927SAndroid Build Coastguard Worker  * the GPU.
118*61046927SAndroid Build Coastguard Worker  */
119*61046927SAndroid Build Coastguard Worker uint64_t
tu_cs_get_cur_iova(const struct tu_cs * cs)120*61046927SAndroid Build Coastguard Worker tu_cs_get_cur_iova(const struct tu_cs *cs)
121*61046927SAndroid Build Coastguard Worker {
122*61046927SAndroid Build Coastguard Worker    if (cs->mode == TU_CS_MODE_EXTERNAL)
123*61046927SAndroid Build Coastguard Worker       return cs->external_iova + ((char *) cs->cur - (char *) cs->start);
124*61046927SAndroid Build Coastguard Worker    return tu_cs_current_bo(cs)->iova + ((char *) cs->cur - (char *) tu_cs_current_bo(cs)->map);
125*61046927SAndroid Build Coastguard Worker }
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker /*
128*61046927SAndroid Build Coastguard Worker  * Allocate and add a BO to a command stream.  Following command packets will
129*61046927SAndroid Build Coastguard Worker  * be emitted to the new BO.
130*61046927SAndroid Build Coastguard Worker  */
131*61046927SAndroid Build Coastguard Worker static VkResult
tu_cs_add_bo(struct tu_cs * cs,uint32_t size)132*61046927SAndroid Build Coastguard Worker tu_cs_add_bo(struct tu_cs *cs, uint32_t size)
133*61046927SAndroid Build Coastguard Worker {
134*61046927SAndroid Build Coastguard Worker    /* no BO for TU_CS_MODE_EXTERNAL */
135*61046927SAndroid Build Coastguard Worker    assert(cs->mode != TU_CS_MODE_EXTERNAL);
136*61046927SAndroid Build Coastguard Worker    /* No adding more BOs if suballocating from a suballoc_bo. */
137*61046927SAndroid Build Coastguard Worker    assert(!cs->refcount_bo);
138*61046927SAndroid Build Coastguard Worker 
139*61046927SAndroid Build Coastguard Worker    /* no dangling command packet */
140*61046927SAndroid Build Coastguard Worker    assert(tu_cs_is_empty(cs));
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker    struct tu_bo_array *bos = cs->writeable ? &cs->read_write : &cs->read_only;
143*61046927SAndroid Build Coastguard Worker 
144*61046927SAndroid Build Coastguard Worker    /* grow cs->bos if needed */
145*61046927SAndroid Build Coastguard Worker    if (bos->bo_count == bos->bo_capacity) {
146*61046927SAndroid Build Coastguard Worker       uint32_t new_capacity = MAX2(4, 2 * bos->bo_capacity);
147*61046927SAndroid Build Coastguard Worker       struct tu_bo **new_bos = (struct tu_bo **)
148*61046927SAndroid Build Coastguard Worker          realloc(bos->bos, new_capacity * sizeof(struct tu_bo *));
149*61046927SAndroid Build Coastguard Worker       if (!new_bos)
150*61046927SAndroid Build Coastguard Worker          return VK_ERROR_OUT_OF_HOST_MEMORY;
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker       bos->bo_capacity = new_capacity;
153*61046927SAndroid Build Coastguard Worker       bos->bos = new_bos;
154*61046927SAndroid Build Coastguard Worker    }
155*61046927SAndroid Build Coastguard Worker 
156*61046927SAndroid Build Coastguard Worker    struct tu_bo *new_bo;
157*61046927SAndroid Build Coastguard Worker 
158*61046927SAndroid Build Coastguard Worker    VkResult result =
159*61046927SAndroid Build Coastguard Worker       tu_bo_init_new(cs->device, NULL, &new_bo, size * sizeof(uint32_t),
160*61046927SAndroid Build Coastguard Worker                      (enum tu_bo_alloc_flags)(COND(!cs->writeable,
161*61046927SAndroid Build Coastguard Worker                                                    TU_BO_ALLOC_GPU_READ_ONLY) |
162*61046927SAndroid Build Coastguard Worker                                               TU_BO_ALLOC_ALLOW_DUMP),
163*61046927SAndroid Build Coastguard Worker                      cs->name);
164*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
165*61046927SAndroid Build Coastguard Worker       return result;
166*61046927SAndroid Build Coastguard Worker    }
167*61046927SAndroid Build Coastguard Worker 
168*61046927SAndroid Build Coastguard Worker    result = tu_bo_map(cs->device, new_bo, NULL);
169*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
170*61046927SAndroid Build Coastguard Worker       tu_bo_finish(cs->device, new_bo);
171*61046927SAndroid Build Coastguard Worker       return result;
172*61046927SAndroid Build Coastguard Worker    }
173*61046927SAndroid Build Coastguard Worker 
174*61046927SAndroid Build Coastguard Worker    TU_RMV(cmd_buffer_bo_create, cs->device, new_bo);
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker    bos->bos[bos->bo_count++] = new_bo;
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker    cs->start = cs->cur = cs->reserved_end = (uint32_t *) new_bo->map;
179*61046927SAndroid Build Coastguard Worker    cs->end = cs->start + new_bo->size / sizeof(uint32_t);
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
182*61046927SAndroid Build Coastguard Worker }
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker /**
185*61046927SAndroid Build Coastguard Worker  * Reserve an IB entry.
186*61046927SAndroid Build Coastguard Worker  */
187*61046927SAndroid Build Coastguard Worker static VkResult
tu_cs_reserve_entry(struct tu_cs * cs)188*61046927SAndroid Build Coastguard Worker tu_cs_reserve_entry(struct tu_cs *cs)
189*61046927SAndroid Build Coastguard Worker {
190*61046927SAndroid Build Coastguard Worker    /* entries are only for TU_CS_MODE_GROW */
191*61046927SAndroid Build Coastguard Worker    assert(cs->mode == TU_CS_MODE_GROW);
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker    /* grow cs->entries if needed */
194*61046927SAndroid Build Coastguard Worker    if (cs->entry_count == cs->entry_capacity) {
195*61046927SAndroid Build Coastguard Worker       uint32_t new_capacity = MAX2(4, cs->entry_capacity * 2);
196*61046927SAndroid Build Coastguard Worker       struct tu_cs_entry *new_entries = (struct tu_cs_entry *)
197*61046927SAndroid Build Coastguard Worker          realloc(cs->entries, new_capacity * sizeof(struct tu_cs_entry));
198*61046927SAndroid Build Coastguard Worker       if (!new_entries)
199*61046927SAndroid Build Coastguard Worker          return VK_ERROR_OUT_OF_HOST_MEMORY;
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker       cs->entry_capacity = new_capacity;
202*61046927SAndroid Build Coastguard Worker       cs->entries = new_entries;
203*61046927SAndroid Build Coastguard Worker    }
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
206*61046927SAndroid Build Coastguard Worker }
207*61046927SAndroid Build Coastguard Worker 
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker /**
210*61046927SAndroid Build Coastguard Worker  * Add an IB entry for the command packets emitted since the last call to this
211*61046927SAndroid Build Coastguard Worker  * function.
212*61046927SAndroid Build Coastguard Worker  */
213*61046927SAndroid Build Coastguard Worker static void
tu_cs_add_entry(struct tu_cs * cs)214*61046927SAndroid Build Coastguard Worker tu_cs_add_entry(struct tu_cs *cs)
215*61046927SAndroid Build Coastguard Worker {
216*61046927SAndroid Build Coastguard Worker    /* entries are only for TU_CS_MODE_GROW */
217*61046927SAndroid Build Coastguard Worker    assert(cs->mode == TU_CS_MODE_GROW);
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    /* disallow empty entry */
220*61046927SAndroid Build Coastguard Worker    assert(!tu_cs_is_empty(cs));
221*61046927SAndroid Build Coastguard Worker 
222*61046927SAndroid Build Coastguard Worker    /*
223*61046927SAndroid Build Coastguard Worker     * because we disallow empty entry, tu_cs_add_bo and tu_cs_reserve_entry
224*61046927SAndroid Build Coastguard Worker     * must both have been called
225*61046927SAndroid Build Coastguard Worker     */
226*61046927SAndroid Build Coastguard Worker    assert(cs->writeable ? cs->read_write.bo_count : cs->read_only.bo_count);
227*61046927SAndroid Build Coastguard Worker    assert(cs->entry_count < cs->entry_capacity);
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker    /* add an entry for [cs->start, cs->cur] */
230*61046927SAndroid Build Coastguard Worker    cs->entries[cs->entry_count++] = (struct tu_cs_entry) {
231*61046927SAndroid Build Coastguard Worker       .bo = tu_cs_current_bo(cs),
232*61046927SAndroid Build Coastguard Worker       .size = tu_cs_get_size(cs) * sizeof(uint32_t),
233*61046927SAndroid Build Coastguard Worker       .offset = tu_cs_get_offset(cs) * sizeof(uint32_t),
234*61046927SAndroid Build Coastguard Worker    };
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker    cs->start = cs->cur;
237*61046927SAndroid Build Coastguard Worker }
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker /**
240*61046927SAndroid Build Coastguard Worker  * same behavior as tu_cs_emit_call but without the indirect
241*61046927SAndroid Build Coastguard Worker  */
242*61046927SAndroid Build Coastguard Worker VkResult
tu_cs_add_entries(struct tu_cs * cs,struct tu_cs * target)243*61046927SAndroid Build Coastguard Worker tu_cs_add_entries(struct tu_cs *cs, struct tu_cs *target)
244*61046927SAndroid Build Coastguard Worker {
245*61046927SAndroid Build Coastguard Worker    VkResult result;
246*61046927SAndroid Build Coastguard Worker 
247*61046927SAndroid Build Coastguard Worker    assert(cs->mode == TU_CS_MODE_GROW);
248*61046927SAndroid Build Coastguard Worker    assert(target->mode == TU_CS_MODE_GROW);
249*61046927SAndroid Build Coastguard Worker 
250*61046927SAndroid Build Coastguard Worker    if (!tu_cs_is_empty(cs))
251*61046927SAndroid Build Coastguard Worker       tu_cs_add_entry(cs);
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < target->entry_count; i++) {
254*61046927SAndroid Build Coastguard Worker       result = tu_cs_reserve_entry(cs);
255*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
256*61046927SAndroid Build Coastguard Worker          return result;
257*61046927SAndroid Build Coastguard Worker       cs->entries[cs->entry_count++] = target->entries[i];
258*61046927SAndroid Build Coastguard Worker    }
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
261*61046927SAndroid Build Coastguard Worker }
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker /**
264*61046927SAndroid Build Coastguard Worker  * Begin (or continue) command packet emission.  This does nothing but sanity
265*61046927SAndroid Build Coastguard Worker  * checks currently.  \a cs must not be in TU_CS_MODE_SUB_STREAM mode.
266*61046927SAndroid Build Coastguard Worker  */
267*61046927SAndroid Build Coastguard Worker void
tu_cs_begin(struct tu_cs * cs)268*61046927SAndroid Build Coastguard Worker tu_cs_begin(struct tu_cs *cs)
269*61046927SAndroid Build Coastguard Worker {
270*61046927SAndroid Build Coastguard Worker    assert(cs->mode != TU_CS_MODE_SUB_STREAM);
271*61046927SAndroid Build Coastguard Worker    assert(tu_cs_is_empty(cs));
272*61046927SAndroid Build Coastguard Worker }
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker /**
275*61046927SAndroid Build Coastguard Worker  * End command packet emission.  This adds an IB entry when \a cs is in
276*61046927SAndroid Build Coastguard Worker  * TU_CS_MODE_GROW mode.
277*61046927SAndroid Build Coastguard Worker  */
278*61046927SAndroid Build Coastguard Worker void
tu_cs_end(struct tu_cs * cs)279*61046927SAndroid Build Coastguard Worker tu_cs_end(struct tu_cs *cs)
280*61046927SAndroid Build Coastguard Worker {
281*61046927SAndroid Build Coastguard Worker    assert(cs->mode != TU_CS_MODE_SUB_STREAM);
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker    if (cs->mode == TU_CS_MODE_GROW && !tu_cs_is_empty(cs))
284*61046927SAndroid Build Coastguard Worker       tu_cs_add_entry(cs);
285*61046927SAndroid Build Coastguard Worker }
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker void
tu_cs_set_writeable(struct tu_cs * cs,bool writeable)288*61046927SAndroid Build Coastguard Worker tu_cs_set_writeable(struct tu_cs *cs, bool writeable)
289*61046927SAndroid Build Coastguard Worker {
290*61046927SAndroid Build Coastguard Worker    assert(cs->mode == TU_CS_MODE_GROW || cs->mode == TU_CS_MODE_SUB_STREAM);
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker    if (cs->writeable != writeable) {
293*61046927SAndroid Build Coastguard Worker       if (cs->mode == TU_CS_MODE_GROW && !tu_cs_is_empty(cs))
294*61046927SAndroid Build Coastguard Worker          tu_cs_add_entry(cs);
295*61046927SAndroid Build Coastguard Worker       struct tu_bo_array *old_bos = cs->writeable ? &cs->read_write : &cs->read_only;
296*61046927SAndroid Build Coastguard Worker       struct tu_bo_array *new_bos = writeable ? &cs->read_write : &cs->read_only;
297*61046927SAndroid Build Coastguard Worker 
298*61046927SAndroid Build Coastguard Worker       old_bos->start = cs->start;
299*61046927SAndroid Build Coastguard Worker       cs->start = cs->cur = cs->reserved_end = new_bos->start;
300*61046927SAndroid Build Coastguard Worker       if (new_bos->bo_count) {
301*61046927SAndroid Build Coastguard Worker          struct tu_bo *bo = new_bos->bos[new_bos->bo_count - 1];
302*61046927SAndroid Build Coastguard Worker          cs->end = (uint32_t *)bo->map + bo->size / sizeof(uint32_t);
303*61046927SAndroid Build Coastguard Worker       } else {
304*61046927SAndroid Build Coastguard Worker          cs->end = NULL;
305*61046927SAndroid Build Coastguard Worker       }
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker       cs->writeable = writeable;
308*61046927SAndroid Build Coastguard Worker    }
309*61046927SAndroid Build Coastguard Worker }
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker /**
312*61046927SAndroid Build Coastguard Worker  * Begin command packet emission to a sub-stream.  \a cs must be in
313*61046927SAndroid Build Coastguard Worker  * TU_CS_MODE_SUB_STREAM mode.
314*61046927SAndroid Build Coastguard Worker  *
315*61046927SAndroid Build Coastguard Worker  * Return \a sub_cs which is in TU_CS_MODE_EXTERNAL mode.  tu_cs_begin and
316*61046927SAndroid Build Coastguard Worker  * tu_cs_reserve_space are implied and \a sub_cs is ready for command packet
317*61046927SAndroid Build Coastguard Worker  * emission.
318*61046927SAndroid Build Coastguard Worker  */
319*61046927SAndroid Build Coastguard Worker VkResult
tu_cs_begin_sub_stream_aligned(struct tu_cs * cs,uint32_t count,uint32_t size,struct tu_cs * sub_cs)320*61046927SAndroid Build Coastguard Worker tu_cs_begin_sub_stream_aligned(struct tu_cs *cs, uint32_t count,
321*61046927SAndroid Build Coastguard Worker                                uint32_t size, struct tu_cs *sub_cs)
322*61046927SAndroid Build Coastguard Worker {
323*61046927SAndroid Build Coastguard Worker    assert(cs->mode == TU_CS_MODE_SUB_STREAM);
324*61046927SAndroid Build Coastguard Worker    assert(size);
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker    VkResult result;
327*61046927SAndroid Build Coastguard Worker    if (tu_cs_get_space(cs) < count * size) {
328*61046927SAndroid Build Coastguard Worker       /* When we have to allocate a new BO, assume that the alignment of the
329*61046927SAndroid Build Coastguard Worker        * BO is sufficient.
330*61046927SAndroid Build Coastguard Worker        */
331*61046927SAndroid Build Coastguard Worker       result = tu_cs_reserve_space(cs, count * size);
332*61046927SAndroid Build Coastguard Worker    } else {
333*61046927SAndroid Build Coastguard Worker       result = tu_cs_reserve_space(cs, count * size + (size - tu_cs_get_offset(cs)) % size);
334*61046927SAndroid Build Coastguard Worker       cs->start += (size - tu_cs_get_offset(cs)) % size;
335*61046927SAndroid Build Coastguard Worker    }
336*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
337*61046927SAndroid Build Coastguard Worker       return result;
338*61046927SAndroid Build Coastguard Worker 
339*61046927SAndroid Build Coastguard Worker    cs->cur = cs->start;
340*61046927SAndroid Build Coastguard Worker 
341*61046927SAndroid Build Coastguard Worker    tu_cs_init_external(sub_cs, cs->device, cs->cur, cs->reserved_end,
342*61046927SAndroid Build Coastguard Worker                        tu_cs_get_cur_iova(cs), cs->writeable);
343*61046927SAndroid Build Coastguard Worker    tu_cs_begin(sub_cs);
344*61046927SAndroid Build Coastguard Worker    result = tu_cs_reserve_space(sub_cs, count * size);
345*61046927SAndroid Build Coastguard Worker    assert(result == VK_SUCCESS);
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
348*61046927SAndroid Build Coastguard Worker }
349*61046927SAndroid Build Coastguard Worker 
350*61046927SAndroid Build Coastguard Worker /**
351*61046927SAndroid Build Coastguard Worker  * Allocate count*size dwords, aligned to size dwords.
352*61046927SAndroid Build Coastguard Worker  * \a cs must be in TU_CS_MODE_SUB_STREAM mode.
353*61046927SAndroid Build Coastguard Worker  *
354*61046927SAndroid Build Coastguard Worker  */
355*61046927SAndroid Build Coastguard Worker VkResult
tu_cs_alloc(struct tu_cs * cs,uint32_t count,uint32_t size,struct tu_cs_memory * memory)356*61046927SAndroid Build Coastguard Worker tu_cs_alloc(struct tu_cs *cs,
357*61046927SAndroid Build Coastguard Worker             uint32_t count,
358*61046927SAndroid Build Coastguard Worker             uint32_t size,
359*61046927SAndroid Build Coastguard Worker             struct tu_cs_memory *memory)
360*61046927SAndroid Build Coastguard Worker {
361*61046927SAndroid Build Coastguard Worker    assert(cs->mode == TU_CS_MODE_SUB_STREAM);
362*61046927SAndroid Build Coastguard Worker    assert(size && size <= 1024);
363*61046927SAndroid Build Coastguard Worker 
364*61046927SAndroid Build Coastguard Worker    if (!count) {
365*61046927SAndroid Build Coastguard Worker       /* If you allocated no memory, you'd better not use the iova for anything
366*61046927SAndroid Build Coastguard Worker        * (but it's left aligned for sanity).
367*61046927SAndroid Build Coastguard Worker        */
368*61046927SAndroid Build Coastguard Worker       memory->map = NULL;
369*61046927SAndroid Build Coastguard Worker       memory->iova = 0xdead0000;
370*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
371*61046927SAndroid Build Coastguard Worker    }
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker    /* TODO: smarter way to deal with alignment? */
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker    VkResult result = tu_cs_reserve_space(cs, count * size + (size-1));
376*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
377*61046927SAndroid Build Coastguard Worker       return result;
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker    struct tu_bo *bo = tu_cs_current_bo(cs);
380*61046927SAndroid Build Coastguard Worker    size_t offset = align(tu_cs_get_offset(cs), size);
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker    memory->map = (uint32_t *) bo->map + offset;
383*61046927SAndroid Build Coastguard Worker    memory->iova = bo->iova + offset * sizeof(uint32_t);
384*61046927SAndroid Build Coastguard Worker    memory->writeable = cs->writeable;
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker    cs->start = cs->cur = (uint32_t*) bo->map + offset + count * size;
387*61046927SAndroid Build Coastguard Worker 
388*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
389*61046927SAndroid Build Coastguard Worker }
390*61046927SAndroid Build Coastguard Worker 
391*61046927SAndroid Build Coastguard Worker /**
392*61046927SAndroid Build Coastguard Worker  * End command packet emission to a sub-stream.  \a sub_cs becomes invalid
393*61046927SAndroid Build Coastguard Worker  * after this call.
394*61046927SAndroid Build Coastguard Worker  *
395*61046927SAndroid Build Coastguard Worker  * Return an IB entry for the sub-stream.  The entry has the same lifetime as
396*61046927SAndroid Build Coastguard Worker  * \a cs.
397*61046927SAndroid Build Coastguard Worker  */
398*61046927SAndroid Build Coastguard Worker struct tu_cs_entry
tu_cs_end_sub_stream(struct tu_cs * cs,struct tu_cs * sub_cs)399*61046927SAndroid Build Coastguard Worker tu_cs_end_sub_stream(struct tu_cs *cs, struct tu_cs *sub_cs)
400*61046927SAndroid Build Coastguard Worker {
401*61046927SAndroid Build Coastguard Worker    assert(cs->mode == TU_CS_MODE_SUB_STREAM);
402*61046927SAndroid Build Coastguard Worker    assert(sub_cs->start == cs->cur && sub_cs->end == cs->reserved_end);
403*61046927SAndroid Build Coastguard Worker    tu_cs_sanity_check(sub_cs);
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker    tu_cs_end(sub_cs);
406*61046927SAndroid Build Coastguard Worker 
407*61046927SAndroid Build Coastguard Worker    cs->cur = sub_cs->cur;
408*61046927SAndroid Build Coastguard Worker 
409*61046927SAndroid Build Coastguard Worker    struct tu_cs_entry entry = {
410*61046927SAndroid Build Coastguard Worker       .bo = tu_cs_current_bo(cs),
411*61046927SAndroid Build Coastguard Worker       .size = tu_cs_get_size(cs) * sizeof(uint32_t),
412*61046927SAndroid Build Coastguard Worker       .offset = tu_cs_get_offset(cs) * sizeof(uint32_t),
413*61046927SAndroid Build Coastguard Worker    };
414*61046927SAndroid Build Coastguard Worker 
415*61046927SAndroid Build Coastguard Worker    cs->start = cs->cur;
416*61046927SAndroid Build Coastguard Worker 
417*61046927SAndroid Build Coastguard Worker    return entry;
418*61046927SAndroid Build Coastguard Worker }
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker /**
421*61046927SAndroid Build Coastguard Worker  * Reserve space from a command stream for \a reserved_size uint32_t values.
422*61046927SAndroid Build Coastguard Worker  * This never fails when \a cs has mode TU_CS_MODE_EXTERNAL.
423*61046927SAndroid Build Coastguard Worker  */
424*61046927SAndroid Build Coastguard Worker VkResult
tu_cs_reserve_space(struct tu_cs * cs,uint32_t reserved_size)425*61046927SAndroid Build Coastguard Worker tu_cs_reserve_space(struct tu_cs *cs, uint32_t reserved_size)
426*61046927SAndroid Build Coastguard Worker {
427*61046927SAndroid Build Coastguard Worker    if (tu_cs_get_space(cs) < reserved_size) {
428*61046927SAndroid Build Coastguard Worker       if (cs->mode == TU_CS_MODE_EXTERNAL) {
429*61046927SAndroid Build Coastguard Worker          unreachable("cannot grow external buffer");
430*61046927SAndroid Build Coastguard Worker          return VK_ERROR_OUT_OF_HOST_MEMORY;
431*61046927SAndroid Build Coastguard Worker       }
432*61046927SAndroid Build Coastguard Worker 
433*61046927SAndroid Build Coastguard Worker       /* add an entry for the exiting command packets */
434*61046927SAndroid Build Coastguard Worker       if (!tu_cs_is_empty(cs)) {
435*61046927SAndroid Build Coastguard Worker          /* no direct command packet for TU_CS_MODE_SUB_STREAM */
436*61046927SAndroid Build Coastguard Worker          assert(cs->mode != TU_CS_MODE_SUB_STREAM);
437*61046927SAndroid Build Coastguard Worker 
438*61046927SAndroid Build Coastguard Worker          tu_cs_add_entry(cs);
439*61046927SAndroid Build Coastguard Worker       }
440*61046927SAndroid Build Coastguard Worker 
441*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < cs->cond_stack_depth; i++) {
442*61046927SAndroid Build Coastguard Worker          /* Subtract one here to account for the DWORD field itself. */
443*61046927SAndroid Build Coastguard Worker          *cs->cond_dwords[i] = cs->cur - cs->cond_dwords[i] - 1;
444*61046927SAndroid Build Coastguard Worker 
445*61046927SAndroid Build Coastguard Worker          /* space for CP_COND_REG_EXEC in next bo */
446*61046927SAndroid Build Coastguard Worker          reserved_size += 3;
447*61046927SAndroid Build Coastguard Worker       }
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker       /* switch to a new BO */
450*61046927SAndroid Build Coastguard Worker       uint32_t new_size = MAX2(cs->next_bo_size, reserved_size);
451*61046927SAndroid Build Coastguard Worker       VkResult result = tu_cs_add_bo(cs, new_size);
452*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
453*61046927SAndroid Build Coastguard Worker          return result;
454*61046927SAndroid Build Coastguard Worker 
455*61046927SAndroid Build Coastguard Worker       if (cs->cond_stack_depth) {
456*61046927SAndroid Build Coastguard Worker          cs->reserved_end = cs->cur + reserved_size;
457*61046927SAndroid Build Coastguard Worker       }
458*61046927SAndroid Build Coastguard Worker 
459*61046927SAndroid Build Coastguard Worker       /* Re-emit CP_COND_REG_EXECs */
460*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < cs->cond_stack_depth; i++) {
461*61046927SAndroid Build Coastguard Worker          tu_cs_emit_pkt7(cs, CP_COND_REG_EXEC, 2);
462*61046927SAndroid Build Coastguard Worker          tu_cs_emit(cs, cs->cond_flags[i]);
463*61046927SAndroid Build Coastguard Worker 
464*61046927SAndroid Build Coastguard Worker          cs->cond_dwords[i] = cs->cur;
465*61046927SAndroid Build Coastguard Worker 
466*61046927SAndroid Build Coastguard Worker          /* Emit dummy DWORD field here */
467*61046927SAndroid Build Coastguard Worker          tu_cs_emit(cs, RENDER_MODE_CP_COND_REG_EXEC_1_DWORDS(0));
468*61046927SAndroid Build Coastguard Worker       }
469*61046927SAndroid Build Coastguard Worker 
470*61046927SAndroid Build Coastguard Worker       /* double the size for the next bo, also there is an upper
471*61046927SAndroid Build Coastguard Worker        * bound on IB size, which appears to be 0x0fffff
472*61046927SAndroid Build Coastguard Worker        */
473*61046927SAndroid Build Coastguard Worker       new_size = MIN2(new_size << 1, 0x0fffff);
474*61046927SAndroid Build Coastguard Worker       if (cs->next_bo_size < new_size)
475*61046927SAndroid Build Coastguard Worker          cs->next_bo_size = new_size;
476*61046927SAndroid Build Coastguard Worker    }
477*61046927SAndroid Build Coastguard Worker 
478*61046927SAndroid Build Coastguard Worker    assert(tu_cs_get_space(cs) >= reserved_size);
479*61046927SAndroid Build Coastguard Worker    cs->reserved_end = cs->cur + reserved_size;
480*61046927SAndroid Build Coastguard Worker 
481*61046927SAndroid Build Coastguard Worker    if (cs->mode == TU_CS_MODE_GROW) {
482*61046927SAndroid Build Coastguard Worker       /* reserve an entry for the next call to this function or tu_cs_end */
483*61046927SAndroid Build Coastguard Worker       return tu_cs_reserve_entry(cs);
484*61046927SAndroid Build Coastguard Worker    }
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
487*61046927SAndroid Build Coastguard Worker }
488*61046927SAndroid Build Coastguard Worker 
489*61046927SAndroid Build Coastguard Worker /**
490*61046927SAndroid Build Coastguard Worker  * Reset a command stream to its initial state.  This discards all comand
491*61046927SAndroid Build Coastguard Worker  * packets in \a cs, but does not necessarily release all resources.
492*61046927SAndroid Build Coastguard Worker  */
493*61046927SAndroid Build Coastguard Worker void
tu_cs_reset(struct tu_cs * cs)494*61046927SAndroid Build Coastguard Worker tu_cs_reset(struct tu_cs *cs)
495*61046927SAndroid Build Coastguard Worker {
496*61046927SAndroid Build Coastguard Worker    if (cs->mode == TU_CS_MODE_EXTERNAL) {
497*61046927SAndroid Build Coastguard Worker       assert(!cs->read_only.bo_count && !cs->read_write.bo_count &&
498*61046927SAndroid Build Coastguard Worker              !cs->refcount_bo && !cs->entry_count);
499*61046927SAndroid Build Coastguard Worker       cs->reserved_end = cs->cur = cs->start;
500*61046927SAndroid Build Coastguard Worker       return;
501*61046927SAndroid Build Coastguard Worker    }
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i + 1 < cs->read_only.bo_count; ++i) {
504*61046927SAndroid Build Coastguard Worker       TU_RMV(resource_destroy, cs->device, cs->read_only.bos[i]);
505*61046927SAndroid Build Coastguard Worker       tu_bo_finish(cs->device, cs->read_only.bos[i]);
506*61046927SAndroid Build Coastguard Worker    }
507*61046927SAndroid Build Coastguard Worker 
508*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i + 1 < cs->read_write.bo_count; ++i) {
509*61046927SAndroid Build Coastguard Worker       TU_RMV(resource_destroy, cs->device, cs->read_write.bos[i]);
510*61046927SAndroid Build Coastguard Worker       tu_bo_finish(cs->device, cs->read_write.bos[i]);
511*61046927SAndroid Build Coastguard Worker    }
512*61046927SAndroid Build Coastguard Worker 
513*61046927SAndroid Build Coastguard Worker    cs->writeable = false;
514*61046927SAndroid Build Coastguard Worker 
515*61046927SAndroid Build Coastguard Worker    if (cs->read_only.bo_count) {
516*61046927SAndroid Build Coastguard Worker       cs->read_only.bos[0] = cs->read_only.bos[cs->read_only.bo_count - 1];
517*61046927SAndroid Build Coastguard Worker       cs->read_only.bo_count = 1;
518*61046927SAndroid Build Coastguard Worker 
519*61046927SAndroid Build Coastguard Worker       cs->start = cs->cur = cs->reserved_end = (uint32_t *) cs->read_only.bos[0]->map;
520*61046927SAndroid Build Coastguard Worker       cs->end = cs->start + cs->read_only.bos[0]->size / sizeof(uint32_t);
521*61046927SAndroid Build Coastguard Worker    }
522*61046927SAndroid Build Coastguard Worker 
523*61046927SAndroid Build Coastguard Worker    if (cs->read_write.bo_count) {
524*61046927SAndroid Build Coastguard Worker       cs->read_write.bos[0] = cs->read_write.bos[cs->read_write.bo_count - 1];
525*61046927SAndroid Build Coastguard Worker       cs->read_write.bo_count = 1;
526*61046927SAndroid Build Coastguard Worker    }
527*61046927SAndroid Build Coastguard Worker 
528*61046927SAndroid Build Coastguard Worker    cs->entry_count = 0;
529*61046927SAndroid Build Coastguard Worker }
530*61046927SAndroid Build Coastguard Worker 
531*61046927SAndroid Build Coastguard Worker uint64_t
tu_cs_emit_data_nop(struct tu_cs * cs,const uint32_t * data,uint32_t size,uint32_t align_dwords)532*61046927SAndroid Build Coastguard Worker tu_cs_emit_data_nop(struct tu_cs *cs,
533*61046927SAndroid Build Coastguard Worker                     const uint32_t *data,
534*61046927SAndroid Build Coastguard Worker                     uint32_t size,
535*61046927SAndroid Build Coastguard Worker                     uint32_t align_dwords)
536*61046927SAndroid Build Coastguard Worker {
537*61046927SAndroid Build Coastguard Worker    uint32_t total_size = size + (align_dwords - 1);
538*61046927SAndroid Build Coastguard Worker    tu_cs_emit_pkt7(cs, CP_NOP, total_size);
539*61046927SAndroid Build Coastguard Worker 
540*61046927SAndroid Build Coastguard Worker    uint64_t iova = tu_cs_get_cur_iova(cs);
541*61046927SAndroid Build Coastguard Worker    uint64_t iova_aligned = align64(iova, align_dwords * sizeof(uint32_t));
542*61046927SAndroid Build Coastguard Worker    size_t offset = (iova_aligned - iova) / sizeof(uint32_t);
543*61046927SAndroid Build Coastguard Worker    cs->cur += offset;
544*61046927SAndroid Build Coastguard Worker    memcpy(cs->cur, data, size * sizeof(uint32_t));
545*61046927SAndroid Build Coastguard Worker 
546*61046927SAndroid Build Coastguard Worker    cs->cur += total_size - offset;
547*61046927SAndroid Build Coastguard Worker 
548*61046927SAndroid Build Coastguard Worker    return iova + offset * sizeof(uint32_t);
549*61046927SAndroid Build Coastguard Worker }
550*61046927SAndroid Build Coastguard Worker 
551*61046927SAndroid Build Coastguard Worker void
tu_cs_emit_debug_string(struct tu_cs * cs,const char * string,int len)552*61046927SAndroid Build Coastguard Worker tu_cs_emit_debug_string(struct tu_cs *cs, const char *string, int len)
553*61046927SAndroid Build Coastguard Worker {
554*61046927SAndroid Build Coastguard Worker    assert(cs->mode == TU_CS_MODE_GROW);
555*61046927SAndroid Build Coastguard Worker 
556*61046927SAndroid Build Coastguard Worker    /* max packet size is 0x3fff dwords */
557*61046927SAndroid Build Coastguard Worker    len = MIN2(len, 0x3fff * 4);
558*61046927SAndroid Build Coastguard Worker 
559*61046927SAndroid Build Coastguard Worker    tu_cs_emit_pkt7(cs, CP_NOP, align(len, 4) / 4);
560*61046927SAndroid Build Coastguard Worker    const uint32_t *buf = (const uint32_t *) string;
561*61046927SAndroid Build Coastguard Worker 
562*61046927SAndroid Build Coastguard Worker    tu_cs_emit_array(cs, buf, len / 4);
563*61046927SAndroid Build Coastguard Worker    buf += len / 4;
564*61046927SAndroid Build Coastguard Worker    len = len % 4;
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker    /* copy remainder bytes without reading past end of input string */
567*61046927SAndroid Build Coastguard Worker    if (len > 0) {
568*61046927SAndroid Build Coastguard Worker       uint32_t w = 0;
569*61046927SAndroid Build Coastguard Worker       memcpy(&w, buf, len);
570*61046927SAndroid Build Coastguard Worker       tu_cs_emit(cs, w);
571*61046927SAndroid Build Coastguard Worker    }
572*61046927SAndroid Build Coastguard Worker }
573*61046927SAndroid Build Coastguard Worker 
574*61046927SAndroid Build Coastguard Worker void
tu_cs_emit_debug_magic_strv(struct tu_cs * cs,uint32_t magic,const char * fmt,va_list args)575*61046927SAndroid Build Coastguard Worker tu_cs_emit_debug_magic_strv(struct tu_cs *cs,
576*61046927SAndroid Build Coastguard Worker                             uint32_t magic,
577*61046927SAndroid Build Coastguard Worker                             const char *fmt,
578*61046927SAndroid Build Coastguard Worker                             va_list args)
579*61046927SAndroid Build Coastguard Worker {
580*61046927SAndroid Build Coastguard Worker    int fmt_len = vsnprintf(NULL, 0, fmt, args);
581*61046927SAndroid Build Coastguard Worker    int len = 4 + fmt_len + 1;
582*61046927SAndroid Build Coastguard Worker    char *string = (char *) malloc(len);
583*61046927SAndroid Build Coastguard Worker 
584*61046927SAndroid Build Coastguard Worker    /* format: <magic><formatted string>\0 */
585*61046927SAndroid Build Coastguard Worker    *(uint32_t *) string = magic;
586*61046927SAndroid Build Coastguard Worker    vsnprintf(string + 4, fmt_len + 1, fmt, args);
587*61046927SAndroid Build Coastguard Worker 
588*61046927SAndroid Build Coastguard Worker    tu_cs_emit_debug_string(cs, string, len);
589*61046927SAndroid Build Coastguard Worker    free(string);
590*61046927SAndroid Build Coastguard Worker }
591*61046927SAndroid Build Coastguard Worker 
592*61046927SAndroid Build Coastguard Worker __attribute__((format(printf, 2, 3))) void
tu_cs_emit_debug_msg(struct tu_cs * cs,const char * fmt,...)593*61046927SAndroid Build Coastguard Worker tu_cs_emit_debug_msg(struct tu_cs *cs, const char *fmt, ...)
594*61046927SAndroid Build Coastguard Worker {
595*61046927SAndroid Build Coastguard Worker    va_list args;
596*61046927SAndroid Build Coastguard Worker    va_start(args, fmt);
597*61046927SAndroid Build Coastguard Worker    tu_cs_emit_debug_magic_strv(cs, CP_NOP_MESG, fmt, args);
598*61046927SAndroid Build Coastguard Worker    va_end(args);
599*61046927SAndroid Build Coastguard Worker }
600*61046927SAndroid Build Coastguard Worker 
601*61046927SAndroid Build Coastguard Worker void
tu_cs_trace_start(struct u_trace_context * utctx,void * cs,const char * fmt,...)602*61046927SAndroid Build Coastguard Worker tu_cs_trace_start(struct u_trace_context *utctx,
603*61046927SAndroid Build Coastguard Worker                   void *cs,
604*61046927SAndroid Build Coastguard Worker                   const char *fmt,
605*61046927SAndroid Build Coastguard Worker                   ...)
606*61046927SAndroid Build Coastguard Worker {
607*61046927SAndroid Build Coastguard Worker    va_list args;
608*61046927SAndroid Build Coastguard Worker    va_start(args, fmt);
609*61046927SAndroid Build Coastguard Worker    tu_cs_emit_debug_magic_strv((struct tu_cs *) cs, CP_NOP_BEGN, fmt, args);
610*61046927SAndroid Build Coastguard Worker    va_end(args);
611*61046927SAndroid Build Coastguard Worker }
612*61046927SAndroid Build Coastguard Worker 
613*61046927SAndroid Build Coastguard Worker void
tu_cs_trace_end(struct u_trace_context * utctx,void * cs,const char * fmt,...)614*61046927SAndroid Build Coastguard Worker tu_cs_trace_end(struct u_trace_context *utctx, void *cs, const char *fmt, ...)
615*61046927SAndroid Build Coastguard Worker {
616*61046927SAndroid Build Coastguard Worker    va_list args;
617*61046927SAndroid Build Coastguard Worker    va_start(args, fmt);
618*61046927SAndroid Build Coastguard Worker    tu_cs_emit_debug_magic_strv((struct tu_cs *) cs, CP_NOP_END, fmt, args);
619*61046927SAndroid Build Coastguard Worker    va_end(args);
620*61046927SAndroid Build Coastguard Worker }
621