1/* 2 * Copyright © 2021 Collabora Ltd. 3 * 4 * Derived from tu_cmd_buffer.c which is: 5 * Copyright © 2016 Red Hat. 6 * Copyright © 2016 Bas Nieuwenhuizen 7 * Copyright © 2015 Intel Corporation 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the next 17 * paragraph) shall be included in all copies or substantial portions of the 18 * Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 */ 28 29#include "genxml/gen_macros.h" 30 31#include "panvk_cs.h" 32#include "panvk_private.h" 33#include "panfrost-quirks.h" 34 35#include "pan_blitter.h" 36#include "pan_cs.h" 37#include "pan_encoder.h" 38 39#include "util/rounding.h" 40#include "util/u_pack_color.h" 41#include "vk_format.h" 42 43static void 44panvk_cmd_prepare_fragment_job(struct panvk_cmd_buffer *cmdbuf) 45{ 46 const struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info; 47 struct panvk_batch *batch = cmdbuf->state.batch; 48 struct panfrost_ptr job_ptr = 49 pan_pool_alloc_desc(&cmdbuf->desc_pool.base, FRAGMENT_JOB); 50 51 GENX(pan_emit_fragment_job)(fbinfo, batch->fb.desc.gpu, job_ptr.cpu), 52 batch->fragment_job = job_ptr.gpu; 53 util_dynarray_append(&batch->jobs, void *, job_ptr.cpu); 54} 55 56#if PAN_ARCH == 5 57void 58panvk_per_arch(cmd_get_polygon_list)(struct panvk_cmd_buffer *cmdbuf, 59 unsigned width, unsigned height, 60 bool has_draws) 61{ 62 struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev; 63 struct panvk_batch *batch = cmdbuf->state.batch; 64 65 if (batch->tiler.ctx.midgard.polygon_list) 66 return; 67 68 unsigned size = 69 panfrost_tiler_get_polygon_list_size(pdev, width, height, has_draws); 70 size = util_next_power_of_two(size); 71 72 /* Create the BO as invisible if we can. In the non-hierarchical tiler case, 73 * we need to write the polygon list manually because there's not WRITE_VALUE 74 * job in the chain. */ 75 bool init_polygon_list = !has_draws && (pdev->quirks & MIDGARD_NO_HIER_TILING); 76 batch->tiler.ctx.midgard.polygon_list = 77 panfrost_bo_create(pdev, size, 78 init_polygon_list ? 0 : PAN_BO_INVISIBLE, 79 "Polygon list"); 80 81 82 if (init_polygon_list) { 83 assert(batch->tiler.ctx.midgard.polygon_list->ptr.cpu); 84 uint32_t *polygon_list_body = 85 batch->tiler.ctx.midgard.polygon_list->ptr.cpu + 86 MALI_MIDGARD_TILER_MINIMUM_HEADER_SIZE; 87 polygon_list_body[0] = 0xa0000000; 88 } 89 90 batch->tiler.ctx.midgard.disable = !has_draws; 91} 92#endif 93 94#if PAN_ARCH <= 5 95static void 96panvk_copy_fb_desc(struct panvk_cmd_buffer *cmdbuf, void *src) 97{ 98 const struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info; 99 struct panvk_batch *batch = cmdbuf->state.batch; 100 uint32_t size = pan_size(FRAMEBUFFER); 101 102 if (fbinfo->zs.view.zs || fbinfo->zs.view.s) 103 size += pan_size(ZS_CRC_EXTENSION); 104 105 size += MAX2(fbinfo->rt_count, 1) * pan_size(RENDER_TARGET); 106 107 memcpy(batch->fb.desc.cpu, src, size); 108} 109#endif 110 111void 112panvk_per_arch(cmd_close_batch)(struct panvk_cmd_buffer *cmdbuf) 113{ 114 struct panvk_batch *batch = cmdbuf->state.batch; 115 116 if (!batch) 117 return; 118 119 const struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info; 120#if PAN_ARCH <= 5 121 uint32_t tmp_fbd[(pan_size(FRAMEBUFFER) + 122 pan_size(ZS_CRC_EXTENSION) + 123 (MAX_RTS * pan_size(RENDER_TARGET))) / 4]; 124#endif 125 126 assert(batch); 127 128 bool clear = fbinfo->zs.clear.z | fbinfo->zs.clear.s; 129 for (unsigned i = 0; i < fbinfo->rt_count; i++) 130 clear |= fbinfo->rts[i].clear; 131 132 if (!clear && !batch->scoreboard.first_job) { 133 if (util_dynarray_num_elements(&batch->event_ops, struct panvk_event_op) == 0) { 134 /* Content-less batch, let's drop it */ 135 vk_free(&cmdbuf->pool->alloc, batch); 136 } else { 137 /* Batch has no jobs but is needed for synchronization, let's add a 138 * NULL job so the SUBMIT ioctl doesn't choke on it. 139 */ 140 struct panfrost_ptr ptr = pan_pool_alloc_desc(&cmdbuf->desc_pool.base, 141 JOB_HEADER); 142 util_dynarray_append(&batch->jobs, void *, ptr.cpu); 143 panfrost_add_job(&cmdbuf->desc_pool.base, &batch->scoreboard, 144 MALI_JOB_TYPE_NULL, false, false, 0, 0, 145 &ptr, false); 146 list_addtail(&batch->node, &cmdbuf->batches); 147 } 148 cmdbuf->state.batch = NULL; 149 return; 150 } 151 152 struct panfrost_device *pdev = &cmdbuf->device->physical_device->pdev; 153 154 list_addtail(&batch->node, &cmdbuf->batches); 155 156 if (batch->scoreboard.first_tiler) { 157 struct panfrost_ptr preload_jobs[2]; 158 unsigned num_preload_jobs = 159 GENX(pan_preload_fb)(&cmdbuf->desc_pool.base, &batch->scoreboard, 160 &cmdbuf->state.fb.info, 161 PAN_ARCH >= 6 ? batch->tls.gpu : batch->fb.desc.gpu, 162 PAN_ARCH >= 6 ? batch->tiler.descs.gpu : 0, 163 preload_jobs); 164 for (unsigned i = 0; i < num_preload_jobs; i++) 165 util_dynarray_append(&batch->jobs, void *, preload_jobs[i].cpu); 166 } 167 168 if (batch->tlsinfo.tls.size) { 169 batch->tlsinfo.tls.ptr = 170 pan_pool_alloc_aligned(&cmdbuf->tls_pool.base, batch->tlsinfo.tls.size, 4096).gpu; 171 } 172 173 if (batch->tlsinfo.wls.size) { 174 assert(batch->wls_total_size); 175 batch->tlsinfo.wls.ptr = 176 pan_pool_alloc_aligned(&cmdbuf->tls_pool.base, batch->wls_total_size, 4096).gpu; 177 } 178 179 if ((PAN_ARCH >= 6 || !batch->fb.desc.cpu) && batch->tls.cpu) 180 GENX(pan_emit_tls)(&batch->tlsinfo, batch->tls.cpu); 181 182 if (batch->fb.desc.cpu) { 183#if PAN_ARCH == 5 184 panvk_per_arch(cmd_get_polygon_list)(cmdbuf, 185 fbinfo->width, 186 fbinfo->height, 187 false); 188 189 mali_ptr polygon_list = 190 batch->tiler.ctx.midgard.polygon_list->ptr.gpu; 191 struct panfrost_ptr writeval_job = 192 panfrost_scoreboard_initialize_tiler(&cmdbuf->desc_pool.base, 193 &batch->scoreboard, 194 polygon_list); 195 if (writeval_job.cpu) 196 util_dynarray_append(&batch->jobs, void *, writeval_job.cpu); 197#endif 198 199#if PAN_ARCH <= 5 200 void *fbd = tmp_fbd; 201#else 202 void *fbd = batch->fb.desc.cpu; 203#endif 204 205 batch->fb.desc.gpu |= 206 GENX(pan_emit_fbd)(pdev, &cmdbuf->state.fb.info, &batch->tlsinfo, 207 &batch->tiler.ctx, fbd); 208 209#if PAN_ARCH <= 5 210 panvk_copy_fb_desc(cmdbuf, tmp_fbd); 211 memcpy(batch->tiler.templ, 212 pan_section_ptr(fbd, FRAMEBUFFER, TILER), 213 pan_size(TILER_CONTEXT)); 214#endif 215 216 panvk_cmd_prepare_fragment_job(cmdbuf); 217 } 218 219 cmdbuf->state.batch = NULL; 220} 221 222void 223panvk_per_arch(CmdNextSubpass2)(VkCommandBuffer commandBuffer, 224 const VkSubpassBeginInfo *pSubpassBeginInfo, 225 const VkSubpassEndInfo *pSubpassEndInfo) 226{ 227 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 228 229 panvk_per_arch(cmd_close_batch)(cmdbuf); 230 231 cmdbuf->state.subpass++; 232 panvk_cmd_fb_info_set_subpass(cmdbuf); 233 panvk_cmd_open_batch(cmdbuf); 234} 235 236void 237panvk_per_arch(CmdNextSubpass)(VkCommandBuffer cmd, VkSubpassContents contents) 238{ 239 VkSubpassBeginInfo binfo = { 240 .sType = VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO, 241 .contents = contents 242 }; 243 VkSubpassEndInfo einfo = { 244 .sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO, 245 }; 246 247 panvk_per_arch(CmdNextSubpass2)(cmd, &binfo, &einfo); 248} 249 250void 251panvk_per_arch(cmd_alloc_fb_desc)(struct panvk_cmd_buffer *cmdbuf) 252{ 253 struct panvk_batch *batch = cmdbuf->state.batch; 254 255 if (batch->fb.desc.gpu) 256 return; 257 258 const struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info; 259 bool has_zs_ext = fbinfo->zs.view.zs || fbinfo->zs.view.s; 260 unsigned tags = MALI_FBD_TAG_IS_MFBD; 261 262 batch->fb.info = cmdbuf->state.framebuffer; 263 batch->fb.desc = 264 pan_pool_alloc_desc_aggregate(&cmdbuf->desc_pool.base, 265 PAN_DESC(FRAMEBUFFER), 266 PAN_DESC_ARRAY(has_zs_ext ? 1 : 0, ZS_CRC_EXTENSION), 267 PAN_DESC_ARRAY(MAX2(fbinfo->rt_count, 1), RENDER_TARGET)); 268 269 /* Tag the pointer */ 270 batch->fb.desc.gpu |= tags; 271 272#if PAN_ARCH >= 6 273 memset(&cmdbuf->state.fb.info.bifrost.pre_post.dcds, 0, 274 sizeof(cmdbuf->state.fb.info.bifrost.pre_post.dcds)); 275#endif 276} 277 278void 279panvk_per_arch(cmd_alloc_tls_desc)(struct panvk_cmd_buffer *cmdbuf, bool gfx) 280{ 281 struct panvk_batch *batch = cmdbuf->state.batch; 282 283 assert(batch); 284 if (batch->tls.gpu) 285 return; 286 287 if (PAN_ARCH == 5 && gfx) { 288 panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf); 289 batch->tls = batch->fb.desc; 290 batch->tls.gpu &= ~63ULL; 291 } else { 292 batch->tls = 293 pan_pool_alloc_desc(&cmdbuf->desc_pool.base, LOCAL_STORAGE); 294 } 295} 296 297static void 298panvk_cmd_upload_sysval(struct panvk_cmd_buffer *cmdbuf, 299 unsigned id, union panvk_sysval_data *data) 300{ 301 switch (PAN_SYSVAL_TYPE(id)) { 302 case PAN_SYSVAL_VIEWPORT_SCALE: 303 panvk_sysval_upload_viewport_scale(&cmdbuf->state.viewport, data); 304 break; 305 case PAN_SYSVAL_VIEWPORT_OFFSET: 306 panvk_sysval_upload_viewport_offset(&cmdbuf->state.viewport, data); 307 break; 308 case PAN_SYSVAL_VERTEX_INSTANCE_OFFSETS: 309 /* TODO: support base_{vertex,instance} */ 310 data->u32[0] = data->u32[1] = data->u32[2] = 0; 311 break; 312 case PAN_SYSVAL_BLEND_CONSTANTS: 313 memcpy(data->f32, cmdbuf->state.blend.constants, sizeof(data->f32)); 314 break; 315 default: 316 unreachable("Invalid static sysval"); 317 } 318} 319 320static void 321panvk_cmd_prepare_sysvals(struct panvk_cmd_buffer *cmdbuf, 322 struct panvk_cmd_bind_point_state *bind_point_state) 323{ 324 struct panvk_descriptor_state *desc_state = &bind_point_state->desc_state; 325 const struct panvk_pipeline *pipeline = bind_point_state->pipeline; 326 327 if (!pipeline->num_sysvals) 328 return; 329 330 for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sysvals); i++) { 331 unsigned sysval_count = pipeline->sysvals[i].ids.sysval_count; 332 if (!sysval_count || pipeline->sysvals[i].ubo || 333 (desc_state->sysvals[i] && 334 !(cmdbuf->state.dirty & pipeline->sysvals[i].dirty_mask))) 335 continue; 336 337 struct panfrost_ptr sysvals = 338 pan_pool_alloc_aligned(&cmdbuf->desc_pool.base, sysval_count * 16, 16); 339 union panvk_sysval_data *data = sysvals.cpu; 340 341 for (unsigned s = 0; s < pipeline->sysvals[i].ids.sysval_count; s++) { 342 panvk_cmd_upload_sysval(cmdbuf, pipeline->sysvals[i].ids.sysvals[s], 343 &data[s]); 344 } 345 346 desc_state->sysvals[i] = sysvals.gpu; 347 } 348} 349 350static void 351panvk_cmd_prepare_ubos(struct panvk_cmd_buffer *cmdbuf, 352 struct panvk_cmd_bind_point_state *bind_point_state) 353{ 354 struct panvk_descriptor_state *desc_state = &bind_point_state->desc_state; 355 const struct panvk_pipeline *pipeline = bind_point_state->pipeline; 356 357 if (!pipeline->num_ubos || desc_state->ubos) 358 return; 359 360 panvk_cmd_prepare_sysvals(cmdbuf, bind_point_state); 361 362 struct panfrost_ptr ubos = 363 pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base, 364 pipeline->num_ubos, 365 UNIFORM_BUFFER); 366 367 panvk_per_arch(emit_ubos)(pipeline, desc_state, ubos.cpu); 368 369 desc_state->ubos = ubos.gpu; 370} 371 372static void 373panvk_cmd_prepare_textures(struct panvk_cmd_buffer *cmdbuf, 374 struct panvk_cmd_bind_point_state *bind_point_state) 375{ 376 struct panvk_descriptor_state *desc_state = &bind_point_state->desc_state; 377 const struct panvk_pipeline *pipeline = bind_point_state->pipeline; 378 unsigned num_textures = pipeline->layout->num_textures; 379 380 if (!num_textures || desc_state->textures) 381 return; 382 383 unsigned tex_entry_size = PAN_ARCH >= 6 ? 384 pan_size(TEXTURE) : 385 sizeof(mali_ptr); 386 struct panfrost_ptr textures = 387 pan_pool_alloc_aligned(&cmdbuf->desc_pool.base, 388 num_textures * tex_entry_size, 389 tex_entry_size); 390 391 void *texture = textures.cpu; 392 393 for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sets); i++) { 394 if (!desc_state->sets[i].set) continue; 395 396 memcpy(texture, 397 desc_state->sets[i].set->textures, 398 desc_state->sets[i].set->layout->num_textures * 399 tex_entry_size); 400 401 texture += desc_state->sets[i].set->layout->num_textures * 402 tex_entry_size; 403 } 404 405 desc_state->textures = textures.gpu; 406} 407 408static void 409panvk_cmd_prepare_samplers(struct panvk_cmd_buffer *cmdbuf, 410 struct panvk_cmd_bind_point_state *bind_point_state) 411{ 412 struct panvk_descriptor_state *desc_state = &bind_point_state->desc_state; 413 const struct panvk_pipeline *pipeline = bind_point_state->pipeline; 414 unsigned num_samplers = pipeline->layout->num_samplers; 415 416 if (!num_samplers || desc_state->samplers) 417 return; 418 419 struct panfrost_ptr samplers = 420 pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base, 421 num_samplers, 422 SAMPLER); 423 424 void *sampler = samplers.cpu; 425 426 for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sets); i++) { 427 if (!desc_state->sets[i].set) continue; 428 429 memcpy(sampler, 430 desc_state->sets[i].set->samplers, 431 desc_state->sets[i].set->layout->num_samplers * 432 pan_size(SAMPLER)); 433 434 sampler += desc_state->sets[i].set->layout->num_samplers; 435 } 436 437 desc_state->samplers = samplers.gpu; 438} 439 440static void 441panvk_draw_prepare_fs_rsd(struct panvk_cmd_buffer *cmdbuf, 442 struct panvk_draw_info *draw) 443{ 444 const struct panvk_pipeline *pipeline = 445 panvk_cmd_get_pipeline(cmdbuf, GRAPHICS); 446 447 if (!pipeline->fs.dynamic_rsd) { 448 draw->fs_rsd = pipeline->rsds[MESA_SHADER_FRAGMENT]; 449 return; 450 } 451 452 if (!cmdbuf->state.fs_rsd) { 453 struct panfrost_ptr rsd = 454 pan_pool_alloc_desc_aggregate(&cmdbuf->desc_pool.base, 455 PAN_DESC(RENDERER_STATE), 456 PAN_DESC_ARRAY(pipeline->blend.state.rt_count, 457 BLEND)); 458 459 struct mali_renderer_state_packed rsd_dyn; 460 struct mali_renderer_state_packed *rsd_templ = 461 (struct mali_renderer_state_packed *)&pipeline->fs.rsd_template; 462 463 STATIC_ASSERT(sizeof(pipeline->fs.rsd_template) >= sizeof(*rsd_templ)); 464 465 panvk_per_arch(emit_dyn_fs_rsd)(pipeline, &cmdbuf->state, &rsd_dyn); 466 pan_merge(rsd_dyn, (*rsd_templ), RENDERER_STATE); 467 memcpy(rsd.cpu, &rsd_dyn, sizeof(rsd_dyn)); 468 469 void *bd = rsd.cpu + pan_size(RENDERER_STATE); 470 for (unsigned i = 0; i < pipeline->blend.state.rt_count; i++) { 471 if (pipeline->blend.constant[i].index != ~0) { 472 struct mali_blend_packed bd_dyn; 473 struct mali_blend_packed *bd_templ = 474 (struct mali_blend_packed *)&pipeline->blend.bd_template[i]; 475 476 STATIC_ASSERT(sizeof(pipeline->blend.bd_template[0]) >= sizeof(*bd_templ)); 477 panvk_per_arch(emit_blend_constant)(cmdbuf->device, pipeline, i, 478 cmdbuf->state.blend.constants, 479 &bd_dyn); 480 pan_merge(bd_dyn, (*bd_templ), BLEND); 481 memcpy(bd, &bd_dyn, sizeof(bd_dyn)); 482 } 483 bd += pan_size(BLEND); 484 } 485 486 cmdbuf->state.fs_rsd = rsd.gpu; 487 } 488 489 draw->fs_rsd = cmdbuf->state.fs_rsd; 490} 491 492#if PAN_ARCH >= 6 493void 494panvk_per_arch(cmd_get_tiler_context)(struct panvk_cmd_buffer *cmdbuf, 495 unsigned width, unsigned height) 496{ 497 struct panvk_batch *batch = cmdbuf->state.batch; 498 499 if (batch->tiler.descs.cpu) 500 return; 501 502 batch->tiler.descs = 503 pan_pool_alloc_desc_aggregate(&cmdbuf->desc_pool.base, 504 PAN_DESC(TILER_CONTEXT), 505 PAN_DESC(TILER_HEAP)); 506 STATIC_ASSERT(sizeof(batch->tiler.templ) >= 507 pan_size(TILER_CONTEXT) + pan_size(TILER_HEAP)); 508 509 struct panfrost_ptr desc = { 510 .gpu = batch->tiler.descs.gpu, 511 .cpu = batch->tiler.templ, 512 }; 513 514 panvk_per_arch(emit_tiler_context)(cmdbuf->device, width, height, &desc); 515 memcpy(batch->tiler.descs.cpu, batch->tiler.templ, 516 pan_size(TILER_CONTEXT) + pan_size(TILER_HEAP)); 517 batch->tiler.ctx.bifrost = batch->tiler.descs.gpu; 518} 519#endif 520 521void 522panvk_per_arch(cmd_prepare_tiler_context)(struct panvk_cmd_buffer *cmdbuf) 523{ 524 const struct pan_fb_info *fbinfo = &cmdbuf->state.fb.info; 525 526#if PAN_ARCH == 5 527 panvk_per_arch(cmd_get_polygon_list)(cmdbuf, 528 fbinfo->width, 529 fbinfo->height, 530 true); 531#else 532 panvk_per_arch(cmd_get_tiler_context)(cmdbuf, 533 fbinfo->width, 534 fbinfo->height); 535#endif 536} 537 538static void 539panvk_draw_prepare_tiler_context(struct panvk_cmd_buffer *cmdbuf, 540 struct panvk_draw_info *draw) 541{ 542 struct panvk_batch *batch = cmdbuf->state.batch; 543 544 panvk_per_arch(cmd_prepare_tiler_context)(cmdbuf); 545 draw->tiler_ctx = &batch->tiler.ctx; 546} 547 548static void 549panvk_draw_prepare_varyings(struct panvk_cmd_buffer *cmdbuf, 550 struct panvk_draw_info *draw) 551{ 552 const struct panvk_pipeline *pipeline = panvk_cmd_get_pipeline(cmdbuf, GRAPHICS); 553 struct panvk_varyings_info *varyings = &cmdbuf->state.varyings; 554 555 panvk_varyings_alloc(varyings, &cmdbuf->varying_pool.base, 556 draw->vertex_count); 557 558 unsigned buf_count = panvk_varyings_buf_count(varyings); 559 struct panfrost_ptr bufs = 560 pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base, 561 buf_count, ATTRIBUTE_BUFFER); 562 563 panvk_per_arch(emit_varying_bufs)(varyings, bufs.cpu); 564 if (BITSET_TEST(varyings->active, VARYING_SLOT_POS)) { 565 draw->position = varyings->buf[varyings->varying[VARYING_SLOT_POS].buf].address + 566 varyings->varying[VARYING_SLOT_POS].offset; 567 } 568 569 if (BITSET_TEST(varyings->active, VARYING_SLOT_PSIZ)) { 570 draw->psiz = varyings->buf[varyings->varying[VARYING_SLOT_PSIZ].buf].address + 571 varyings->varying[VARYING_SLOT_POS].offset; 572 } else if (pipeline->ia.topology == MALI_DRAW_MODE_LINES || 573 pipeline->ia.topology == MALI_DRAW_MODE_LINE_STRIP || 574 pipeline->ia.topology == MALI_DRAW_MODE_LINE_LOOP) { 575 draw->line_width = pipeline->dynamic_state_mask & PANVK_DYNAMIC_LINE_WIDTH ? 576 cmdbuf->state.rast.line_width : pipeline->rast.line_width; 577 } else { 578 draw->line_width = 1.0f; 579 } 580 draw->varying_bufs = bufs.gpu; 581 582 for (unsigned s = 0; s < MESA_SHADER_STAGES; s++) { 583 if (!varyings->stage[s].count) continue; 584 585 struct panfrost_ptr attribs = 586 pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base, 587 varyings->stage[s].count, 588 ATTRIBUTE); 589 590 panvk_per_arch(emit_varyings)(cmdbuf->device, varyings, s, attribs.cpu); 591 draw->stages[s].varyings = attribs.gpu; 592 } 593} 594 595static void 596panvk_draw_prepare_attributes(struct panvk_cmd_buffer *cmdbuf, 597 struct panvk_draw_info *draw) 598{ 599 const struct panvk_pipeline *pipeline = panvk_cmd_get_pipeline(cmdbuf, GRAPHICS); 600 601 /* TODO: images */ 602 if (!pipeline->attribs.buf_count) 603 return; 604 605 if (cmdbuf->state.vb.attribs) { 606 draw->stages[MESA_SHADER_VERTEX].attributes = cmdbuf->state.vb.attribs; 607 draw->attribute_bufs = cmdbuf->state.vb.attrib_bufs; 608 return; 609 } 610 611 unsigned buf_count = pipeline->attribs.buf_count + 612 (PAN_ARCH >= 6 ? 1 : 0); 613 struct panfrost_ptr bufs = 614 pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base, 615 buf_count * 2, ATTRIBUTE_BUFFER); 616 617 panvk_per_arch(emit_attrib_bufs)(&pipeline->attribs, 618 cmdbuf->state.vb.bufs, 619 cmdbuf->state.vb.count, 620 draw, bufs.cpu); 621 cmdbuf->state.vb.attrib_bufs = bufs.gpu; 622 623 struct panfrost_ptr attribs = 624 pan_pool_alloc_desc_array(&cmdbuf->desc_pool.base, 625 pipeline->attribs.attrib_count, 626 ATTRIBUTE); 627 628 panvk_per_arch(emit_attribs)(cmdbuf->device, &pipeline->attribs, 629 cmdbuf->state.vb.bufs, cmdbuf->state.vb.count, 630 attribs.cpu); 631 cmdbuf->state.vb.attribs = attribs.gpu; 632 draw->stages[MESA_SHADER_VERTEX].attributes = cmdbuf->state.vb.attribs; 633 draw->attribute_bufs = cmdbuf->state.vb.attrib_bufs; 634} 635 636static void 637panvk_draw_prepare_viewport(struct panvk_cmd_buffer *cmdbuf, 638 struct panvk_draw_info *draw) 639{ 640 const struct panvk_pipeline *pipeline = panvk_cmd_get_pipeline(cmdbuf, GRAPHICS); 641 642 if (pipeline->vpd) { 643 draw->viewport = pipeline->vpd; 644 } else if (cmdbuf->state.vpd) { 645 draw->viewport = cmdbuf->state.vpd; 646 } else { 647 struct panfrost_ptr vp = 648 pan_pool_alloc_desc(&cmdbuf->desc_pool.base, VIEWPORT); 649 650 const VkViewport *viewport = 651 pipeline->dynamic_state_mask & PANVK_DYNAMIC_VIEWPORT ? 652 &cmdbuf->state.viewport : &pipeline->viewport; 653 const VkRect2D *scissor = 654 pipeline->dynamic_state_mask & PANVK_DYNAMIC_SCISSOR ? 655 &cmdbuf->state.scissor : &pipeline->scissor; 656 657 panvk_per_arch(emit_viewport)(viewport, scissor, vp.cpu); 658 draw->viewport = cmdbuf->state.vpd = vp.gpu; 659 } 660} 661 662static void 663panvk_draw_prepare_vertex_job(struct panvk_cmd_buffer *cmdbuf, 664 struct panvk_draw_info *draw) 665{ 666 const struct panvk_pipeline *pipeline = panvk_cmd_get_pipeline(cmdbuf, GRAPHICS); 667 struct panvk_batch *batch = cmdbuf->state.batch; 668 struct panfrost_ptr ptr = 669 pan_pool_alloc_desc(&cmdbuf->desc_pool.base, COMPUTE_JOB); 670 671 util_dynarray_append(&batch->jobs, void *, ptr.cpu); 672 draw->jobs.vertex = ptr; 673 panvk_per_arch(emit_vertex_job)(pipeline, draw, ptr.cpu); 674} 675 676static void 677panvk_draw_prepare_tiler_job(struct panvk_cmd_buffer *cmdbuf, 678 struct panvk_draw_info *draw) 679{ 680 const struct panvk_pipeline *pipeline = panvk_cmd_get_pipeline(cmdbuf, GRAPHICS); 681 struct panvk_batch *batch = cmdbuf->state.batch; 682 struct panfrost_ptr ptr = 683 pan_pool_alloc_desc(&cmdbuf->desc_pool.base, TILER_JOB); 684 685 util_dynarray_append(&batch->jobs, void *, ptr.cpu); 686 draw->jobs.tiler = ptr; 687 panvk_per_arch(emit_tiler_job)(pipeline, draw, ptr.cpu); 688} 689 690void 691panvk_per_arch(CmdDraw)(VkCommandBuffer commandBuffer, 692 uint32_t vertexCount, 693 uint32_t instanceCount, 694 uint32_t firstVertex, 695 uint32_t firstInstance) 696{ 697 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 698 699 struct panvk_batch *batch = cmdbuf->state.batch; 700 struct panvk_cmd_bind_point_state *bind_point_state = 701 panvk_cmd_get_bind_point_state(cmdbuf, GRAPHICS); 702 const struct panvk_pipeline *pipeline = 703 panvk_cmd_get_pipeline(cmdbuf, GRAPHICS); 704 705 /* There are only 16 bits in the descriptor for the job ID, make sure all 706 * the 3 (2 in Bifrost) jobs in this draw are in the same batch. 707 */ 708 if (batch->scoreboard.job_index >= (UINT16_MAX - 3)) { 709 panvk_per_arch(cmd_close_batch)(cmdbuf); 710 panvk_cmd_preload_fb_after_batch_split(cmdbuf); 711 batch = panvk_cmd_open_batch(cmdbuf); 712 } 713 714 if (pipeline->fs.required) 715 panvk_per_arch(cmd_alloc_fb_desc)(cmdbuf); 716 717 panvk_per_arch(cmd_alloc_tls_desc)(cmdbuf, true); 718 panvk_cmd_prepare_ubos(cmdbuf, bind_point_state); 719 panvk_cmd_prepare_textures(cmdbuf, bind_point_state); 720 panvk_cmd_prepare_samplers(cmdbuf, bind_point_state); 721 722 /* TODO: indexed draws */ 723 struct panvk_descriptor_state *desc_state = 724 panvk_cmd_get_desc_state(cmdbuf, GRAPHICS); 725 726 struct panvk_draw_info draw = { 727 .first_vertex = firstVertex, 728 .vertex_count = vertexCount, 729 .first_instance = firstInstance, 730 .instance_count = instanceCount, 731 .padded_vertex_count = panfrost_padded_vertex_count(vertexCount), 732 .offset_start = firstVertex, 733 .tls = batch->tls.gpu, 734 .fb = batch->fb.desc.gpu, 735 .ubos = desc_state->ubos, 736 .textures = desc_state->textures, 737 .samplers = desc_state->samplers, 738 }; 739 740 STATIC_ASSERT(sizeof(draw.invocation) >= sizeof(struct mali_invocation_packed)); 741 panfrost_pack_work_groups_compute((struct mali_invocation_packed *)&draw.invocation, 742 1, vertexCount, instanceCount, 1, 1, 1, true, false); 743 panvk_draw_prepare_fs_rsd(cmdbuf, &draw); 744 panvk_draw_prepare_varyings(cmdbuf, &draw); 745 panvk_draw_prepare_attributes(cmdbuf, &draw); 746 panvk_draw_prepare_viewport(cmdbuf, &draw); 747 panvk_draw_prepare_tiler_context(cmdbuf, &draw); 748 panvk_draw_prepare_vertex_job(cmdbuf, &draw); 749 panvk_draw_prepare_tiler_job(cmdbuf, &draw); 750 batch->tlsinfo.tls.size = MAX2(pipeline->tls_size, batch->tlsinfo.tls.size); 751 assert(!pipeline->wls_size); 752 753 unsigned vjob_id = 754 panfrost_add_job(&cmdbuf->desc_pool.base, &batch->scoreboard, 755 MALI_JOB_TYPE_VERTEX, false, false, 0, 0, 756 &draw.jobs.vertex, false); 757 758 if (pipeline->fs.required) { 759 panfrost_add_job(&cmdbuf->desc_pool.base, &batch->scoreboard, 760 MALI_JOB_TYPE_TILER, false, false, vjob_id, 0, 761 &draw.jobs.tiler, false); 762 } 763 764 /* Clear the dirty flags all at once */ 765 cmdbuf->state.dirty = 0; 766} 767 768VkResult 769panvk_per_arch(EndCommandBuffer)(VkCommandBuffer commandBuffer) 770{ 771 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 772 773 panvk_per_arch(cmd_close_batch)(cmdbuf); 774 cmdbuf->status = PANVK_CMD_BUFFER_STATUS_EXECUTABLE; 775 776 return cmdbuf->record_result; 777} 778 779void 780panvk_per_arch(CmdEndRenderPass2)(VkCommandBuffer commandBuffer, 781 const VkSubpassEndInfoKHR *pSubpassEndInfo) 782{ 783 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 784 785 panvk_per_arch(cmd_close_batch)(cmdbuf); 786 vk_free(&cmdbuf->pool->alloc, cmdbuf->state.clear); 787 cmdbuf->state.batch = NULL; 788 cmdbuf->state.pass = NULL; 789 cmdbuf->state.subpass = NULL; 790 cmdbuf->state.framebuffer = NULL; 791 cmdbuf->state.clear = NULL; 792} 793 794void 795panvk_per_arch(CmdEndRenderPass)(VkCommandBuffer cmd) 796{ 797 VkSubpassEndInfoKHR einfo = { 798 .sType = VK_STRUCTURE_TYPE_SUBPASS_END_INFO, 799 }; 800 801 panvk_per_arch(CmdEndRenderPass2)(cmd, &einfo); 802} 803 804 805void 806panvk_per_arch(CmdPipelineBarrier)(VkCommandBuffer commandBuffer, 807 VkPipelineStageFlags srcStageMask, 808 VkPipelineStageFlags destStageMask, 809 VkDependencyFlags dependencyFlags, 810 uint32_t memoryBarrierCount, 811 const VkMemoryBarrier *pMemoryBarriers, 812 uint32_t bufferMemoryBarrierCount, 813 const VkBufferMemoryBarrier *pBufferMemoryBarriers, 814 uint32_t imageMemoryBarrierCount, 815 const VkImageMemoryBarrier *pImageMemoryBarriers) 816{ 817 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 818 819 /* Caches are flushed/invalidated at batch boundaries for now, nothing to do 820 * for memory barriers assuming we implement barriers with the creation of a 821 * new batch. 822 * FIXME: We can probably do better with a CacheFlush job that has the 823 * barrier flag set to true. 824 */ 825 if (cmdbuf->state.batch) { 826 panvk_per_arch(cmd_close_batch)(cmdbuf); 827 panvk_cmd_preload_fb_after_batch_split(cmdbuf); 828 panvk_cmd_open_batch(cmdbuf); 829 } 830} 831 832static void 833panvk_add_set_event_operation(struct panvk_cmd_buffer *cmdbuf, 834 struct panvk_event *event, 835 enum panvk_event_op_type type) 836{ 837 struct panvk_event_op op = { 838 .type = type, 839 .event = event, 840 }; 841 842 if (cmdbuf->state.batch == NULL) { 843 /* No open batch, let's create a new one so this operation happens in 844 * the right order. 845 */ 846 panvk_cmd_open_batch(cmdbuf); 847 util_dynarray_append(&cmdbuf->state.batch->event_ops, 848 struct panvk_event_op, 849 op); 850 panvk_per_arch(cmd_close_batch)(cmdbuf); 851 } else { 852 /* Let's close the current batch so the operation executes before any 853 * future commands. 854 */ 855 util_dynarray_append(&cmdbuf->state.batch->event_ops, 856 struct panvk_event_op, 857 op); 858 panvk_per_arch(cmd_close_batch)(cmdbuf); 859 panvk_cmd_preload_fb_after_batch_split(cmdbuf); 860 panvk_cmd_open_batch(cmdbuf); 861 } 862} 863 864static void 865panvk_add_wait_event_operation(struct panvk_cmd_buffer *cmdbuf, 866 struct panvk_event *event) 867{ 868 struct panvk_event_op op = { 869 .type = PANVK_EVENT_OP_WAIT, 870 .event = event, 871 }; 872 873 if (cmdbuf->state.batch == NULL) { 874 /* No open batch, let's create a new one and have it wait for this event. */ 875 panvk_cmd_open_batch(cmdbuf); 876 util_dynarray_append(&cmdbuf->state.batch->event_ops, 877 struct panvk_event_op, 878 op); 879 } else { 880 /* Let's close the current batch so any future commands wait on the 881 * event signal operation. 882 */ 883 if (cmdbuf->state.batch->fragment_job || 884 cmdbuf->state.batch->scoreboard.first_job) { 885 panvk_per_arch(cmd_close_batch)(cmdbuf); 886 panvk_cmd_preload_fb_after_batch_split(cmdbuf); 887 panvk_cmd_open_batch(cmdbuf); 888 } 889 util_dynarray_append(&cmdbuf->state.batch->event_ops, 890 struct panvk_event_op, 891 op); 892 } 893} 894 895void 896panvk_per_arch(CmdSetEvent)(VkCommandBuffer commandBuffer, 897 VkEvent _event, 898 VkPipelineStageFlags stageMask) 899{ 900 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 901 VK_FROM_HANDLE(panvk_event, event, _event); 902 903 /* vkCmdSetEvent cannot be called inside a render pass */ 904 assert(cmdbuf->state.pass == NULL); 905 906 panvk_add_set_event_operation(cmdbuf, event, PANVK_EVENT_OP_SET); 907} 908 909void 910panvk_per_arch(CmdResetEvent)(VkCommandBuffer commandBuffer, 911 VkEvent _event, 912 VkPipelineStageFlags stageMask) 913{ 914 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 915 VK_FROM_HANDLE(panvk_event, event, _event); 916 917 /* vkCmdResetEvent cannot be called inside a render pass */ 918 assert(cmdbuf->state.pass == NULL); 919 920 panvk_add_set_event_operation(cmdbuf, event, PANVK_EVENT_OP_RESET); 921} 922 923void 924panvk_per_arch(CmdWaitEvents)(VkCommandBuffer commandBuffer, 925 uint32_t eventCount, 926 const VkEvent *pEvents, 927 VkPipelineStageFlags srcStageMask, 928 VkPipelineStageFlags dstStageMask, 929 uint32_t memoryBarrierCount, 930 const VkMemoryBarrier *pMemoryBarriers, 931 uint32_t bufferMemoryBarrierCount, 932 const VkBufferMemoryBarrier *pBufferMemoryBarriers, 933 uint32_t imageMemoryBarrierCount, 934 const VkImageMemoryBarrier *pImageMemoryBarriers) 935{ 936 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 937 938 assert(eventCount > 0); 939 940 for (uint32_t i = 0; i < eventCount; i++) { 941 VK_FROM_HANDLE(panvk_event, event, pEvents[i]); 942 panvk_add_wait_event_operation(cmdbuf, event); 943 } 944} 945 946static VkResult 947panvk_reset_cmdbuf(struct panvk_cmd_buffer *cmdbuf) 948{ 949 vk_command_buffer_reset(&cmdbuf->vk); 950 951 cmdbuf->record_result = VK_SUCCESS; 952 953 list_for_each_entry_safe(struct panvk_batch, batch, &cmdbuf->batches, node) { 954 list_del(&batch->node); 955 util_dynarray_fini(&batch->jobs); 956#if PAN_ARCH <= 5 957 panfrost_bo_unreference(batch->tiler.ctx.midgard.polygon_list); 958#endif 959 960 util_dynarray_fini(&batch->event_ops); 961 962 vk_free(&cmdbuf->pool->alloc, batch); 963 } 964 965 panvk_pool_reset(&cmdbuf->desc_pool); 966 panvk_pool_reset(&cmdbuf->tls_pool); 967 panvk_pool_reset(&cmdbuf->varying_pool); 968 cmdbuf->status = PANVK_CMD_BUFFER_STATUS_INITIAL; 969 970 for (unsigned i = 0; i < MAX_BIND_POINTS; i++) 971 memset(&cmdbuf->bind_points[i].desc_state.sets, 0, sizeof(cmdbuf->bind_points[0].desc_state.sets)); 972 973 return cmdbuf->record_result; 974} 975 976static void 977panvk_destroy_cmdbuf(struct panvk_cmd_buffer *cmdbuf) 978{ 979 struct panvk_device *device = cmdbuf->device; 980 981 list_del(&cmdbuf->pool_link); 982 983 list_for_each_entry_safe(struct panvk_batch, batch, &cmdbuf->batches, node) { 984 list_del(&batch->node); 985 util_dynarray_fini(&batch->jobs); 986#if PAN_ARCH <= 5 987 panfrost_bo_unreference(batch->tiler.ctx.midgard.polygon_list); 988#endif 989 990 util_dynarray_fini(&batch->event_ops); 991 992 vk_free(&cmdbuf->pool->alloc, batch); 993 } 994 995 panvk_pool_cleanup(&cmdbuf->desc_pool); 996 panvk_pool_cleanup(&cmdbuf->tls_pool); 997 panvk_pool_cleanup(&cmdbuf->varying_pool); 998 vk_command_buffer_finish(&cmdbuf->vk); 999 vk_free(&device->vk.alloc, cmdbuf); 1000} 1001 1002static VkResult 1003panvk_create_cmdbuf(struct panvk_device *device, 1004 struct panvk_cmd_pool *pool, 1005 VkCommandBufferLevel level, 1006 struct panvk_cmd_buffer **cmdbuf_out) 1007{ 1008 struct panvk_cmd_buffer *cmdbuf; 1009 1010 cmdbuf = vk_zalloc(&device->vk.alloc, sizeof(*cmdbuf), 1011 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1012 if (!cmdbuf) 1013 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1014 1015 VkResult result = vk_command_buffer_init(&cmdbuf->vk, &device->vk); 1016 if (result != VK_SUCCESS) { 1017 vk_free(&device->vk.alloc, cmdbuf); 1018 return result; 1019 } 1020 1021 cmdbuf->device = device; 1022 cmdbuf->level = level; 1023 cmdbuf->pool = pool; 1024 1025 if (pool) { 1026 list_addtail(&cmdbuf->pool_link, &pool->active_cmd_buffers); 1027 cmdbuf->queue_family_index = pool->queue_family_index; 1028 } else { 1029 /* Init the pool_link so we can safely call list_del when we destroy 1030 * the command buffer 1031 */ 1032 list_inithead(&cmdbuf->pool_link); 1033 cmdbuf->queue_family_index = PANVK_QUEUE_GENERAL; 1034 } 1035 1036 panvk_pool_init(&cmdbuf->desc_pool, &device->physical_device->pdev, 1037 pool ? &pool->desc_bo_pool : NULL, 0, 64 * 1024, 1038 "Command buffer descriptor pool", true); 1039 panvk_pool_init(&cmdbuf->tls_pool, &device->physical_device->pdev, 1040 pool ? &pool->tls_bo_pool : NULL, 1041 PAN_BO_INVISIBLE, 64 * 1024, "TLS pool", false); 1042 panvk_pool_init(&cmdbuf->varying_pool, &device->physical_device->pdev, 1043 pool ? &pool->varying_bo_pool : NULL, 1044 PAN_BO_INVISIBLE, 64 * 1024, "Varyings pool", false); 1045 list_inithead(&cmdbuf->batches); 1046 cmdbuf->status = PANVK_CMD_BUFFER_STATUS_INITIAL; 1047 *cmdbuf_out = cmdbuf; 1048 return VK_SUCCESS; 1049} 1050 1051VkResult 1052panvk_per_arch(AllocateCommandBuffers)(VkDevice _device, 1053 const VkCommandBufferAllocateInfo *pAllocateInfo, 1054 VkCommandBuffer *pCommandBuffers) 1055{ 1056 VK_FROM_HANDLE(panvk_device, device, _device); 1057 VK_FROM_HANDLE(panvk_cmd_pool, pool, pAllocateInfo->commandPool); 1058 1059 VkResult result = VK_SUCCESS; 1060 unsigned i; 1061 1062 for (i = 0; i < pAllocateInfo->commandBufferCount; i++) { 1063 struct panvk_cmd_buffer *cmdbuf = NULL; 1064 1065 if (!list_is_empty(&pool->free_cmd_buffers)) { 1066 cmdbuf = list_first_entry( 1067 &pool->free_cmd_buffers, struct panvk_cmd_buffer, pool_link); 1068 1069 list_del(&cmdbuf->pool_link); 1070 list_addtail(&cmdbuf->pool_link, &pool->active_cmd_buffers); 1071 1072 cmdbuf->level = pAllocateInfo->level; 1073 vk_command_buffer_finish(&cmdbuf->vk); 1074 result = vk_command_buffer_init(&cmdbuf->vk, &device->vk); 1075 } else { 1076 result = panvk_create_cmdbuf(device, pool, pAllocateInfo->level, &cmdbuf); 1077 } 1078 1079 if (result != VK_SUCCESS) 1080 goto err_free_cmd_bufs; 1081 1082 pCommandBuffers[i] = panvk_cmd_buffer_to_handle(cmdbuf); 1083 } 1084 1085 return VK_SUCCESS; 1086 1087err_free_cmd_bufs: 1088 panvk_per_arch(FreeCommandBuffers)(_device, pAllocateInfo->commandPool, i, 1089 pCommandBuffers); 1090 for (unsigned j = 0; j < i; j++) 1091 pCommandBuffers[j] = VK_NULL_HANDLE; 1092 1093 return result; 1094} 1095 1096void 1097panvk_per_arch(FreeCommandBuffers)(VkDevice device, 1098 VkCommandPool commandPool, 1099 uint32_t commandBufferCount, 1100 const VkCommandBuffer *pCommandBuffers) 1101{ 1102 for (uint32_t i = 0; i < commandBufferCount; i++) { 1103 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, pCommandBuffers[i]); 1104 1105 if (cmdbuf) { 1106 if (cmdbuf->pool) { 1107 list_del(&cmdbuf->pool_link); 1108 panvk_reset_cmdbuf(cmdbuf); 1109 list_addtail(&cmdbuf->pool_link, 1110 &cmdbuf->pool->free_cmd_buffers); 1111 } else 1112 panvk_destroy_cmdbuf(cmdbuf); 1113 } 1114 } 1115} 1116 1117VkResult 1118panvk_per_arch(ResetCommandBuffer)(VkCommandBuffer commandBuffer, 1119 VkCommandBufferResetFlags flags) 1120{ 1121 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 1122 1123 return panvk_reset_cmdbuf(cmdbuf); 1124} 1125 1126VkResult 1127panvk_per_arch(BeginCommandBuffer)(VkCommandBuffer commandBuffer, 1128 const VkCommandBufferBeginInfo *pBeginInfo) 1129{ 1130 VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer); 1131 VkResult result = VK_SUCCESS; 1132 1133 if (cmdbuf->status != PANVK_CMD_BUFFER_STATUS_INITIAL) { 1134 /* If the command buffer has already been reset with 1135 * vkResetCommandBuffer, no need to do it again. 1136 */ 1137 result = panvk_reset_cmdbuf(cmdbuf); 1138 if (result != VK_SUCCESS) 1139 return result; 1140 } 1141 1142 memset(&cmdbuf->state, 0, sizeof(cmdbuf->state)); 1143 1144 cmdbuf->status = PANVK_CMD_BUFFER_STATUS_RECORDING; 1145 1146 return VK_SUCCESS; 1147} 1148 1149void 1150panvk_per_arch(DestroyCommandPool)(VkDevice _device, 1151 VkCommandPool commandPool, 1152 const VkAllocationCallbacks *pAllocator) 1153{ 1154 VK_FROM_HANDLE(panvk_device, device, _device); 1155 VK_FROM_HANDLE(panvk_cmd_pool, pool, commandPool); 1156 1157 list_for_each_entry_safe(struct panvk_cmd_buffer, cmdbuf, 1158 &pool->active_cmd_buffers, pool_link) 1159 panvk_destroy_cmdbuf(cmdbuf); 1160 1161 list_for_each_entry_safe(struct panvk_cmd_buffer, cmdbuf, 1162 &pool->free_cmd_buffers, pool_link) 1163 panvk_destroy_cmdbuf(cmdbuf); 1164 1165 panvk_bo_pool_cleanup(&pool->desc_bo_pool); 1166 panvk_bo_pool_cleanup(&pool->varying_bo_pool); 1167 panvk_bo_pool_cleanup(&pool->tls_bo_pool); 1168 vk_object_free(&device->vk, pAllocator, pool); 1169} 1170 1171VkResult 1172panvk_per_arch(ResetCommandPool)(VkDevice device, 1173 VkCommandPool commandPool, 1174 VkCommandPoolResetFlags flags) 1175{ 1176 VK_FROM_HANDLE(panvk_cmd_pool, pool, commandPool); 1177 VkResult result; 1178 1179 list_for_each_entry(struct panvk_cmd_buffer, cmdbuf, &pool->active_cmd_buffers, 1180 pool_link) 1181 { 1182 result = panvk_reset_cmdbuf(cmdbuf); 1183 if (result != VK_SUCCESS) 1184 return result; 1185 } 1186 1187 return VK_SUCCESS; 1188} 1189 1190void 1191panvk_per_arch(TrimCommandPool)(VkDevice device, 1192 VkCommandPool commandPool, 1193 VkCommandPoolTrimFlags flags) 1194{ 1195 VK_FROM_HANDLE(panvk_cmd_pool, pool, commandPool); 1196 1197 if (!pool) 1198 return; 1199 1200 list_for_each_entry_safe(struct panvk_cmd_buffer, cmdbuf, 1201 &pool->free_cmd_buffers, pool_link) 1202 panvk_destroy_cmdbuf(cmdbuf); 1203} 1204