2 * Copyright © 2019 Google LLC
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
27 * Initialize a command stream.
30 tu_cs_init(struct tu_cs
*cs
)
32 cs
->start
= cs
->cur
= cs
->end
= NULL
;
34 cs
->entry_count
= cs
->entry_capacity
= 0;
37 cs
->bo_count
= cs
->bo_capacity
= 0;
42 * Finish and release all resources owned by a command stream.
45 tu_cs_finish(struct tu_device
*dev
, struct tu_cs
*cs
)
47 for (uint32_t i
= 0; i
< cs
->bo_count
; ++i
) {
48 tu_bo_finish(dev
, cs
->bos
[i
]);
57 * Begin (or continue) command packet emission. This will reserve space from
58 * the command stream for at least \a reserve_size uint32_t values.
61 tu_cs_begin(struct tu_device
*dev
, struct tu_cs
*cs
, uint32_t reserve_size
)
65 if (cs
->end
- cs
->cur
< reserve_size
) {
66 if (cs
->bo_count
== cs
->bo_capacity
) {
67 uint32_t new_capacity
= MAX2(4, 2 * cs
->bo_capacity
);
68 struct tu_bo
**new_bos
=
69 realloc(cs
->bos
, new_capacity
* sizeof(struct tu_bo
*));
73 cs
->bo_capacity
= new_capacity
;
77 uint32_t new_size
= MAX2(16384, reserve_size
* sizeof(uint32_t));
79 new_size
= MAX2(new_size
, cs
->bos
[cs
->bo_count
- 1]->size
* 2);
81 struct tu_bo
*new_bo
= malloc(sizeof(struct tu_bo
));
85 VkResult result
= tu_bo_init_new(dev
, new_bo
, new_size
);
86 if (result
!= VK_SUCCESS
) {
91 result
= tu_bo_map(dev
, new_bo
);
92 if (result
!= VK_SUCCESS
) {
93 tu_bo_finish(dev
, new_bo
);
98 cs
->bos
[cs
->bo_count
] = new_bo
;
101 cs
->start
= cs
->cur
= (uint32_t *) new_bo
->map
;
102 cs
->end
= cs
->start
+ new_bo
->size
/ sizeof(uint32_t);
110 * End command packet emission by adding an IB entry for the command packets
111 * emitted since the last call to tu_cs_begin.
114 tu_cs_end(struct tu_cs
*cs
)
116 if (cs
->start
== cs
->cur
)
119 if (cs
->entry_capacity
== cs
->entry_count
) {
120 uint32_t new_capacity
= MAX2(cs
->entry_capacity
* 2, 4);
121 struct tu_cs_entry
*new_entries
=
122 realloc(cs
->entries
, new_capacity
* sizeof(struct tu_cs_entry
));
126 cs
->entries
= new_entries
;
127 cs
->entry_capacity
= new_capacity
;
130 assert(cs
->bo_count
);
132 struct tu_cs_entry entry
;
133 entry
.bo
= cs
->bos
[cs
->bo_count
- 1];
134 entry
.size
= (cs
->cur
- cs
->start
) * sizeof(uint32_t);
135 entry
.offset
= (cs
->start
- (uint32_t *) entry
.bo
->map
) * sizeof(uint32_t);
137 cs
->entries
[cs
->entry_count
] = entry
;
144 * Reset a command stream to its initial state. This discards all comand
145 * packets in \a cs, but does not necessarily release all resources.
148 tu_cs_reset(struct tu_device
*dev
, struct tu_cs
*cs
)
150 for (uint32_t i
= 0; i
+ 1 < cs
->bo_count
; ++i
) {
151 tu_bo_finish(dev
, cs
->bos
[i
]);
156 cs
->bos
[0] = cs
->bos
[cs
->bo_count
- 1];
159 cs
->start
= cs
->cur
= (uint32_t *) cs
->bos
[0]->map
;
160 cs
->end
= cs
->start
+ cs
->bos
[0]->size
/ sizeof(uint32_t);
167 * Reserve space from a command stream for \a size uint32_t values.
170 tu_cs_check_space(struct tu_device
*dev
, struct tu_cs
*cs
, size_t size
)
172 if (cs
->end
- cs
->cur
>= size
)
175 VkResult result
= tu_cs_end(cs
);
176 if (result
!= VK_SUCCESS
)
179 return tu_cs_begin(dev
, cs
, size
);