1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2019 Google LLC 3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 4bf215546Sopenharmony_ci */ 5bf215546Sopenharmony_ci 6bf215546Sopenharmony_ci#include "tu_cs.h" 7bf215546Sopenharmony_ci 8bf215546Sopenharmony_ci#include "tu_suballoc.h" 9bf215546Sopenharmony_ci 10bf215546Sopenharmony_ci/** 11bf215546Sopenharmony_ci * Initialize a command stream. 12bf215546Sopenharmony_ci */ 13bf215546Sopenharmony_civoid 14bf215546Sopenharmony_citu_cs_init(struct tu_cs *cs, 15bf215546Sopenharmony_ci struct tu_device *device, 16bf215546Sopenharmony_ci enum tu_cs_mode mode, 17bf215546Sopenharmony_ci uint32_t initial_size) 18bf215546Sopenharmony_ci{ 19bf215546Sopenharmony_ci assert(mode != TU_CS_MODE_EXTERNAL); 20bf215546Sopenharmony_ci 21bf215546Sopenharmony_ci memset(cs, 0, sizeof(*cs)); 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci cs->device = device; 24bf215546Sopenharmony_ci cs->mode = mode; 25bf215546Sopenharmony_ci cs->next_bo_size = initial_size; 26bf215546Sopenharmony_ci} 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/** 29bf215546Sopenharmony_ci * Initialize a command stream as a wrapper to an external buffer. 30bf215546Sopenharmony_ci */ 31bf215546Sopenharmony_civoid 32bf215546Sopenharmony_citu_cs_init_external(struct tu_cs *cs, struct tu_device *device, 33bf215546Sopenharmony_ci uint32_t *start, uint32_t *end) 34bf215546Sopenharmony_ci{ 35bf215546Sopenharmony_ci memset(cs, 0, sizeof(*cs)); 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci cs->device = device; 38bf215546Sopenharmony_ci cs->mode = TU_CS_MODE_EXTERNAL; 39bf215546Sopenharmony_ci cs->start = cs->reserved_end = cs->cur = start; 40bf215546Sopenharmony_ci cs->end = end; 41bf215546Sopenharmony_ci} 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci/** 44bf215546Sopenharmony_ci * Initialize a sub-command stream as a wrapper to an externally sub-allocated 45bf215546Sopenharmony_ci * buffer. 46bf215546Sopenharmony_ci */ 47bf215546Sopenharmony_civoid 48bf215546Sopenharmony_citu_cs_init_suballoc(struct tu_cs *cs, struct tu_device *device, 49bf215546Sopenharmony_ci struct tu_suballoc_bo *suballoc_bo) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci uint32_t *start = tu_suballoc_bo_map(suballoc_bo); 52bf215546Sopenharmony_ci uint32_t *end = start + (suballoc_bo->size >> 2); 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci memset(cs, 0, sizeof(*cs)); 55bf215546Sopenharmony_ci cs->device = device; 56bf215546Sopenharmony_ci cs->mode = TU_CS_MODE_SUB_STREAM; 57bf215546Sopenharmony_ci cs->start = cs->reserved_end = cs->cur = start; 58bf215546Sopenharmony_ci cs->end = end; 59bf215546Sopenharmony_ci cs->refcount_bo = tu_bo_get_ref(suballoc_bo->bo); 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci/** 63bf215546Sopenharmony_ci * Finish and release all resources owned by a command stream. 64bf215546Sopenharmony_ci */ 65bf215546Sopenharmony_civoid 66bf215546Sopenharmony_citu_cs_finish(struct tu_cs *cs) 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci for (uint32_t i = 0; i < cs->bo_count; ++i) { 69bf215546Sopenharmony_ci tu_bo_finish(cs->device, cs->bos[i]); 70bf215546Sopenharmony_ci } 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci if (cs->refcount_bo) 73bf215546Sopenharmony_ci tu_bo_finish(cs->device, cs->refcount_bo); 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci free(cs->entries); 76bf215546Sopenharmony_ci free(cs->bos); 77bf215546Sopenharmony_ci} 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_cistatic struct tu_bo * 80bf215546Sopenharmony_citu_cs_current_bo(const struct tu_cs *cs) 81bf215546Sopenharmony_ci{ 82bf215546Sopenharmony_ci if (cs->refcount_bo) { 83bf215546Sopenharmony_ci return cs->refcount_bo; 84bf215546Sopenharmony_ci } else { 85bf215546Sopenharmony_ci assert(cs->bo_count); 86bf215546Sopenharmony_ci return cs->bos[cs->bo_count - 1]; 87bf215546Sopenharmony_ci } 88bf215546Sopenharmony_ci} 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci/** 91bf215546Sopenharmony_ci * Get the offset of the command packets emitted since the last call to 92bf215546Sopenharmony_ci * tu_cs_add_entry. 93bf215546Sopenharmony_ci */ 94bf215546Sopenharmony_cistatic uint32_t 95bf215546Sopenharmony_citu_cs_get_offset(const struct tu_cs *cs) 96bf215546Sopenharmony_ci{ 97bf215546Sopenharmony_ci return cs->start - (uint32_t *) tu_cs_current_bo(cs)->map; 98bf215546Sopenharmony_ci} 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci/* 101bf215546Sopenharmony_ci * Allocate and add a BO to a command stream. Following command packets will 102bf215546Sopenharmony_ci * be emitted to the new BO. 103bf215546Sopenharmony_ci */ 104bf215546Sopenharmony_cistatic VkResult 105bf215546Sopenharmony_citu_cs_add_bo(struct tu_cs *cs, uint32_t size) 106bf215546Sopenharmony_ci{ 107bf215546Sopenharmony_ci /* no BO for TU_CS_MODE_EXTERNAL */ 108bf215546Sopenharmony_ci assert(cs->mode != TU_CS_MODE_EXTERNAL); 109bf215546Sopenharmony_ci /* No adding more BOs if suballocating from a suballoc_bo. */ 110bf215546Sopenharmony_ci assert(!cs->refcount_bo); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci /* no dangling command packet */ 113bf215546Sopenharmony_ci assert(tu_cs_is_empty(cs)); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci /* grow cs->bos if needed */ 116bf215546Sopenharmony_ci if (cs->bo_count == cs->bo_capacity) { 117bf215546Sopenharmony_ci uint32_t new_capacity = MAX2(4, 2 * cs->bo_capacity); 118bf215546Sopenharmony_ci struct tu_bo **new_bos = 119bf215546Sopenharmony_ci realloc(cs->bos, new_capacity * sizeof(struct tu_bo *)); 120bf215546Sopenharmony_ci if (!new_bos) 121bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci cs->bo_capacity = new_capacity; 124bf215546Sopenharmony_ci cs->bos = new_bos; 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci struct tu_bo *new_bo; 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci VkResult result = 130bf215546Sopenharmony_ci tu_bo_init_new(cs->device, &new_bo, size * sizeof(uint32_t), 131bf215546Sopenharmony_ci TU_BO_ALLOC_GPU_READ_ONLY | TU_BO_ALLOC_ALLOW_DUMP); 132bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 133bf215546Sopenharmony_ci return result; 134bf215546Sopenharmony_ci } 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci result = tu_bo_map(cs->device, new_bo); 137bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 138bf215546Sopenharmony_ci tu_bo_finish(cs->device, new_bo); 139bf215546Sopenharmony_ci return result; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci cs->bos[cs->bo_count++] = new_bo; 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci cs->start = cs->cur = cs->reserved_end = (uint32_t *) new_bo->map; 145bf215546Sopenharmony_ci cs->end = cs->start + new_bo->size / sizeof(uint32_t); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci return VK_SUCCESS; 148bf215546Sopenharmony_ci} 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci/** 151bf215546Sopenharmony_ci * Reserve an IB entry. 152bf215546Sopenharmony_ci */ 153bf215546Sopenharmony_cistatic VkResult 154bf215546Sopenharmony_citu_cs_reserve_entry(struct tu_cs *cs) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci /* entries are only for TU_CS_MODE_GROW */ 157bf215546Sopenharmony_ci assert(cs->mode == TU_CS_MODE_GROW); 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci /* grow cs->entries if needed */ 160bf215546Sopenharmony_ci if (cs->entry_count == cs->entry_capacity) { 161bf215546Sopenharmony_ci uint32_t new_capacity = MAX2(4, cs->entry_capacity * 2); 162bf215546Sopenharmony_ci struct tu_cs_entry *new_entries = 163bf215546Sopenharmony_ci realloc(cs->entries, new_capacity * sizeof(struct tu_cs_entry)); 164bf215546Sopenharmony_ci if (!new_entries) 165bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci cs->entry_capacity = new_capacity; 168bf215546Sopenharmony_ci cs->entries = new_entries; 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci return VK_SUCCESS; 172bf215546Sopenharmony_ci} 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci/** 175bf215546Sopenharmony_ci * Add an IB entry for the command packets emitted since the last call to this 176bf215546Sopenharmony_ci * function. 177bf215546Sopenharmony_ci */ 178bf215546Sopenharmony_cistatic void 179bf215546Sopenharmony_citu_cs_add_entry(struct tu_cs *cs) 180bf215546Sopenharmony_ci{ 181bf215546Sopenharmony_ci /* entries are only for TU_CS_MODE_GROW */ 182bf215546Sopenharmony_ci assert(cs->mode == TU_CS_MODE_GROW); 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci /* disallow empty entry */ 185bf215546Sopenharmony_ci assert(!tu_cs_is_empty(cs)); 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci /* 188bf215546Sopenharmony_ci * because we disallow empty entry, tu_cs_add_bo and tu_cs_reserve_entry 189bf215546Sopenharmony_ci * must both have been called 190bf215546Sopenharmony_ci */ 191bf215546Sopenharmony_ci assert(cs->bo_count); 192bf215546Sopenharmony_ci assert(cs->entry_count < cs->entry_capacity); 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci /* add an entry for [cs->start, cs->cur] */ 195bf215546Sopenharmony_ci cs->entries[cs->entry_count++] = (struct tu_cs_entry) { 196bf215546Sopenharmony_ci .bo = tu_cs_current_bo(cs), 197bf215546Sopenharmony_ci .size = tu_cs_get_size(cs) * sizeof(uint32_t), 198bf215546Sopenharmony_ci .offset = tu_cs_get_offset(cs) * sizeof(uint32_t), 199bf215546Sopenharmony_ci }; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci cs->start = cs->cur; 202bf215546Sopenharmony_ci} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci/** 205bf215546Sopenharmony_ci * same behavior as tu_cs_emit_call but without the indirect 206bf215546Sopenharmony_ci */ 207bf215546Sopenharmony_ciVkResult 208bf215546Sopenharmony_citu_cs_add_entries(struct tu_cs *cs, struct tu_cs *target) 209bf215546Sopenharmony_ci{ 210bf215546Sopenharmony_ci VkResult result; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci assert(cs->mode == TU_CS_MODE_GROW); 213bf215546Sopenharmony_ci assert(target->mode == TU_CS_MODE_GROW); 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci if (!tu_cs_is_empty(cs)) 216bf215546Sopenharmony_ci tu_cs_add_entry(cs); 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci for (unsigned i = 0; i < target->entry_count; i++) { 219bf215546Sopenharmony_ci result = tu_cs_reserve_entry(cs); 220bf215546Sopenharmony_ci if (result != VK_SUCCESS) 221bf215546Sopenharmony_ci return result; 222bf215546Sopenharmony_ci cs->entries[cs->entry_count++] = target->entries[i]; 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci return VK_SUCCESS; 226bf215546Sopenharmony_ci} 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci/** 229bf215546Sopenharmony_ci * Begin (or continue) command packet emission. This does nothing but sanity 230bf215546Sopenharmony_ci * checks currently. \a cs must not be in TU_CS_MODE_SUB_STREAM mode. 231bf215546Sopenharmony_ci */ 232bf215546Sopenharmony_civoid 233bf215546Sopenharmony_citu_cs_begin(struct tu_cs *cs) 234bf215546Sopenharmony_ci{ 235bf215546Sopenharmony_ci assert(cs->mode != TU_CS_MODE_SUB_STREAM); 236bf215546Sopenharmony_ci assert(tu_cs_is_empty(cs)); 237bf215546Sopenharmony_ci} 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci/** 240bf215546Sopenharmony_ci * End command packet emission. This adds an IB entry when \a cs is in 241bf215546Sopenharmony_ci * TU_CS_MODE_GROW mode. 242bf215546Sopenharmony_ci */ 243bf215546Sopenharmony_civoid 244bf215546Sopenharmony_citu_cs_end(struct tu_cs *cs) 245bf215546Sopenharmony_ci{ 246bf215546Sopenharmony_ci assert(cs->mode != TU_CS_MODE_SUB_STREAM); 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci if (cs->mode == TU_CS_MODE_GROW && !tu_cs_is_empty(cs)) 249bf215546Sopenharmony_ci tu_cs_add_entry(cs); 250bf215546Sopenharmony_ci} 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci/** 253bf215546Sopenharmony_ci * Begin command packet emission to a sub-stream. \a cs must be in 254bf215546Sopenharmony_ci * TU_CS_MODE_SUB_STREAM mode. 255bf215546Sopenharmony_ci * 256bf215546Sopenharmony_ci * Return \a sub_cs which is in TU_CS_MODE_EXTERNAL mode. tu_cs_begin and 257bf215546Sopenharmony_ci * tu_cs_reserve_space are implied and \a sub_cs is ready for command packet 258bf215546Sopenharmony_ci * emission. 259bf215546Sopenharmony_ci */ 260bf215546Sopenharmony_ciVkResult 261bf215546Sopenharmony_citu_cs_begin_sub_stream(struct tu_cs *cs, uint32_t size, struct tu_cs *sub_cs) 262bf215546Sopenharmony_ci{ 263bf215546Sopenharmony_ci assert(cs->mode == TU_CS_MODE_SUB_STREAM); 264bf215546Sopenharmony_ci assert(size); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci VkResult result = tu_cs_reserve_space(cs, size); 267bf215546Sopenharmony_ci if (result != VK_SUCCESS) 268bf215546Sopenharmony_ci return result; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci tu_cs_init_external(sub_cs, cs->device, cs->cur, cs->reserved_end); 271bf215546Sopenharmony_ci tu_cs_begin(sub_cs); 272bf215546Sopenharmony_ci result = tu_cs_reserve_space(sub_cs, size); 273bf215546Sopenharmony_ci assert(result == VK_SUCCESS); 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci return VK_SUCCESS; 276bf215546Sopenharmony_ci} 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci/** 279bf215546Sopenharmony_ci * Allocate count*size dwords, aligned to size dwords. 280bf215546Sopenharmony_ci * \a cs must be in TU_CS_MODE_SUB_STREAM mode. 281bf215546Sopenharmony_ci * 282bf215546Sopenharmony_ci */ 283bf215546Sopenharmony_ciVkResult 284bf215546Sopenharmony_citu_cs_alloc(struct tu_cs *cs, 285bf215546Sopenharmony_ci uint32_t count, 286bf215546Sopenharmony_ci uint32_t size, 287bf215546Sopenharmony_ci struct tu_cs_memory *memory) 288bf215546Sopenharmony_ci{ 289bf215546Sopenharmony_ci assert(cs->mode == TU_CS_MODE_SUB_STREAM); 290bf215546Sopenharmony_ci assert(size && size <= 1024); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci if (!count) 293bf215546Sopenharmony_ci return VK_SUCCESS; 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci /* TODO: smarter way to deal with alignment? */ 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci VkResult result = tu_cs_reserve_space(cs, count * size + (size-1)); 298bf215546Sopenharmony_ci if (result != VK_SUCCESS) 299bf215546Sopenharmony_ci return result; 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci struct tu_bo *bo = tu_cs_current_bo(cs); 302bf215546Sopenharmony_ci size_t offset = align(tu_cs_get_offset(cs), size); 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci memory->map = bo->map + offset * sizeof(uint32_t); 305bf215546Sopenharmony_ci memory->iova = bo->iova + offset * sizeof(uint32_t); 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci cs->start = cs->cur = (uint32_t*) bo->map + offset + count * size; 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci return VK_SUCCESS; 310bf215546Sopenharmony_ci} 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci/** 313bf215546Sopenharmony_ci * End command packet emission to a sub-stream. \a sub_cs becomes invalid 314bf215546Sopenharmony_ci * after this call. 315bf215546Sopenharmony_ci * 316bf215546Sopenharmony_ci * Return an IB entry for the sub-stream. The entry has the same lifetime as 317bf215546Sopenharmony_ci * \a cs. 318bf215546Sopenharmony_ci */ 319bf215546Sopenharmony_cistruct tu_cs_entry 320bf215546Sopenharmony_citu_cs_end_sub_stream(struct tu_cs *cs, struct tu_cs *sub_cs) 321bf215546Sopenharmony_ci{ 322bf215546Sopenharmony_ci assert(cs->mode == TU_CS_MODE_SUB_STREAM); 323bf215546Sopenharmony_ci assert(sub_cs->start == cs->cur && sub_cs->end == cs->reserved_end); 324bf215546Sopenharmony_ci tu_cs_sanity_check(sub_cs); 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci tu_cs_end(sub_cs); 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci cs->cur = sub_cs->cur; 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci struct tu_cs_entry entry = { 331bf215546Sopenharmony_ci .bo = tu_cs_current_bo(cs), 332bf215546Sopenharmony_ci .size = tu_cs_get_size(cs) * sizeof(uint32_t), 333bf215546Sopenharmony_ci .offset = tu_cs_get_offset(cs) * sizeof(uint32_t), 334bf215546Sopenharmony_ci }; 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci cs->start = cs->cur; 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci return entry; 339bf215546Sopenharmony_ci} 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci/** 342bf215546Sopenharmony_ci * Reserve space from a command stream for \a reserved_size uint32_t values. 343bf215546Sopenharmony_ci * This never fails when \a cs has mode TU_CS_MODE_EXTERNAL. 344bf215546Sopenharmony_ci */ 345bf215546Sopenharmony_ciVkResult 346bf215546Sopenharmony_citu_cs_reserve_space(struct tu_cs *cs, uint32_t reserved_size) 347bf215546Sopenharmony_ci{ 348bf215546Sopenharmony_ci if (tu_cs_get_space(cs) < reserved_size) { 349bf215546Sopenharmony_ci if (cs->mode == TU_CS_MODE_EXTERNAL) { 350bf215546Sopenharmony_ci unreachable("cannot grow external buffer"); 351bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 352bf215546Sopenharmony_ci } 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci /* add an entry for the exiting command packets */ 355bf215546Sopenharmony_ci if (!tu_cs_is_empty(cs)) { 356bf215546Sopenharmony_ci /* no direct command packet for TU_CS_MODE_SUB_STREAM */ 357bf215546Sopenharmony_ci assert(cs->mode != TU_CS_MODE_SUB_STREAM); 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci tu_cs_add_entry(cs); 360bf215546Sopenharmony_ci } 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci for (uint32_t i = 0; i < cs->cond_stack_depth; i++) { 363bf215546Sopenharmony_ci /* Subtract one here to account for the DWORD field itself. */ 364bf215546Sopenharmony_ci *cs->cond_dwords[i] = cs->cur - cs->cond_dwords[i] - 1; 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci /* space for CP_COND_REG_EXEC in next bo */ 367bf215546Sopenharmony_ci reserved_size += 3; 368bf215546Sopenharmony_ci } 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci /* switch to a new BO */ 371bf215546Sopenharmony_ci uint32_t new_size = MAX2(cs->next_bo_size, reserved_size); 372bf215546Sopenharmony_ci VkResult result = tu_cs_add_bo(cs, new_size); 373bf215546Sopenharmony_ci if (result != VK_SUCCESS) 374bf215546Sopenharmony_ci return result; 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci if (cs->cond_stack_depth) { 377bf215546Sopenharmony_ci cs->reserved_end = cs->cur + reserved_size; 378bf215546Sopenharmony_ci } 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci /* Re-emit CP_COND_REG_EXECs */ 381bf215546Sopenharmony_ci for (uint32_t i = 0; i < cs->cond_stack_depth; i++) { 382bf215546Sopenharmony_ci tu_cs_emit_pkt7(cs, CP_COND_REG_EXEC, 2); 383bf215546Sopenharmony_ci tu_cs_emit(cs, cs->cond_flags[i]); 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci cs->cond_dwords[i] = cs->cur; 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci /* Emit dummy DWORD field here */ 388bf215546Sopenharmony_ci tu_cs_emit(cs, CP_COND_REG_EXEC_1_DWORDS(0)); 389bf215546Sopenharmony_ci } 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci /* double the size for the next bo, also there is an upper 392bf215546Sopenharmony_ci * bound on IB size, which appears to be 0x0fffff 393bf215546Sopenharmony_ci */ 394bf215546Sopenharmony_ci new_size = MIN2(new_size << 1, 0x0fffff); 395bf215546Sopenharmony_ci if (cs->next_bo_size < new_size) 396bf215546Sopenharmony_ci cs->next_bo_size = new_size; 397bf215546Sopenharmony_ci } 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci assert(tu_cs_get_space(cs) >= reserved_size); 400bf215546Sopenharmony_ci cs->reserved_end = cs->cur + reserved_size; 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci if (cs->mode == TU_CS_MODE_GROW) { 403bf215546Sopenharmony_ci /* reserve an entry for the next call to this function or tu_cs_end */ 404bf215546Sopenharmony_ci return tu_cs_reserve_entry(cs); 405bf215546Sopenharmony_ci } 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci return VK_SUCCESS; 408bf215546Sopenharmony_ci} 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_ci/** 411bf215546Sopenharmony_ci * Reset a command stream to its initial state. This discards all comand 412bf215546Sopenharmony_ci * packets in \a cs, but does not necessarily release all resources. 413bf215546Sopenharmony_ci */ 414bf215546Sopenharmony_civoid 415bf215546Sopenharmony_citu_cs_reset(struct tu_cs *cs) 416bf215546Sopenharmony_ci{ 417bf215546Sopenharmony_ci if (cs->mode == TU_CS_MODE_EXTERNAL) { 418bf215546Sopenharmony_ci assert(!cs->bo_count && !cs->refcount_bo && !cs->entry_count); 419bf215546Sopenharmony_ci cs->reserved_end = cs->cur = cs->start; 420bf215546Sopenharmony_ci return; 421bf215546Sopenharmony_ci } 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci for (uint32_t i = 0; i + 1 < cs->bo_count; ++i) { 424bf215546Sopenharmony_ci tu_bo_finish(cs->device, cs->bos[i]); 425bf215546Sopenharmony_ci } 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci if (cs->bo_count) { 428bf215546Sopenharmony_ci cs->bos[0] = cs->bos[cs->bo_count - 1]; 429bf215546Sopenharmony_ci cs->bo_count = 1; 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci cs->start = cs->cur = cs->reserved_end = (uint32_t *) cs->bos[0]->map; 432bf215546Sopenharmony_ci cs->end = cs->start + cs->bos[0]->size / sizeof(uint32_t); 433bf215546Sopenharmony_ci } 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci cs->entry_count = 0; 436bf215546Sopenharmony_ci} 437