1/* 2 * Copyright 2019 Google LLC 3 * SPDX-License-Identifier: MIT 4 * 5 * based in part on anv and radv which are: 6 * Copyright © 2015 Intel Corporation 7 * Copyright © 2016 Red Hat. 8 * Copyright © 2016 Bas Nieuwenhuizen 9 */ 10 11#include "vn_command_buffer.h" 12 13#include "venus-protocol/vn_protocol_driver_command_buffer.h" 14#include "venus-protocol/vn_protocol_driver_command_pool.h" 15 16#include "vn_device.h" 17#include "vn_image.h" 18#include "vn_render_pass.h" 19 20#define VN_CMD_ENQUEUE(cmd_name, commandBuffer, ...) \ 21 do { \ 22 struct vn_command_buffer *_cmd = \ 23 vn_command_buffer_from_handle(commandBuffer); \ 24 size_t _cmd_size = vn_sizeof_##cmd_name(commandBuffer, ##__VA_ARGS__); \ 25 \ 26 if (vn_cs_encoder_reserve(&_cmd->cs, _cmd_size)) \ 27 vn_encode_##cmd_name(&_cmd->cs, 0, commandBuffer, ##__VA_ARGS__); \ 28 else \ 29 _cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; \ 30 } while (0) 31 32static bool 33vn_image_memory_barrier_has_present_src( 34 const VkImageMemoryBarrier *img_barriers, uint32_t count) 35{ 36 for (uint32_t i = 0; i < count; i++) { 37 if (img_barriers[i].oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR || 38 img_barriers[i].newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) 39 return true; 40 } 41 return false; 42} 43 44static VkImageMemoryBarrier * 45vn_cmd_get_image_memory_barriers(struct vn_command_buffer *cmd, 46 uint32_t count) 47{ 48 /* avoid shrinking in case of non efficient reallocation implementation */ 49 if (count > cmd->builder.image_barrier_count) { 50 size_t size = sizeof(VkImageMemoryBarrier) * count; 51 VkImageMemoryBarrier *img_barriers = 52 vk_realloc(&cmd->allocator, cmd->builder.image_barriers, size, 53 VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 54 if (!img_barriers) 55 return NULL; 56 57 /* update upon successful reallocation */ 58 cmd->builder.image_barrier_count = count; 59 cmd->builder.image_barriers = img_barriers; 60 } 61 62 return cmd->builder.image_barriers; 63} 64 65/* About VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, the spec says 66 * 67 * VK_IMAGE_LAYOUT_PRESENT_SRC_KHR must only be used for presenting a 68 * presentable image for display. A swapchain's image must be transitioned 69 * to this layout before calling vkQueuePresentKHR, and must be 70 * transitioned away from this layout after calling vkAcquireNextImageKHR. 71 * 72 * That allows us to treat the layout internally as 73 * 74 * - VK_IMAGE_LAYOUT_GENERAL 75 * - VK_QUEUE_FAMILY_FOREIGN_EXT has the ownership, if the image is not a 76 * prime blit source 77 * 78 * while staying performant. 79 * 80 * About queue family ownerships, the spec says 81 * 82 * A queue family can take ownership of an image subresource or buffer 83 * range of a resource created with VK_SHARING_MODE_EXCLUSIVE, without an 84 * ownership transfer, in the same way as for a resource that was just 85 * created; however, taking ownership in this way has the effect that the 86 * contents of the image subresource or buffer range are undefined. 87 * 88 * It is unclear if that is applicable to external resources, which supposedly 89 * have the same semantics 90 * 91 * Binding a resource to a memory object shared between multiple Vulkan 92 * instances or other APIs does not change the ownership of the underlying 93 * memory. The first entity to access the resource implicitly acquires 94 * ownership. Accessing a resource backed by memory that is owned by a 95 * particular instance or API has the same semantics as accessing a 96 * VK_SHARING_MODE_EXCLUSIVE resource[...] 97 * 98 * We should get the spec clarified, or get rid of this completely broken code 99 * (TODO). 100 * 101 * Assuming a queue family can acquire the ownership implicitly when the 102 * contents are not needed, we do not need to worry about 103 * VK_IMAGE_LAYOUT_UNDEFINED. We can use VK_IMAGE_LAYOUT_PRESENT_SRC_KHR as 104 * the sole signal to trigger queue family ownership transfers. 105 * 106 * When the image has VK_SHARING_MODE_CONCURRENT, we can, and are required to, 107 * use VK_QUEUE_FAMILY_IGNORED as the other queue family whether we are 108 * transitioning to or from VK_IMAGE_LAYOUT_PRESENT_SRC_KHR. 109 * 110 * When the image has VK_SHARING_MODE_EXCLUSIVE, we have to work out who the 111 * other queue family is. It is easier when the barrier does not also define 112 * a queue family ownership transfer (i.e., srcQueueFamilyIndex equals to 113 * dstQueueFamilyIndex). The other queue family must be the queue family the 114 * command buffer was allocated for. 115 * 116 * When the barrier also defines a queue family ownership transfer, it is 117 * submitted both to the source queue family to release the ownership and to 118 * the destination queue family to acquire the ownership. Depending on 119 * whether the barrier transitions to or from VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 120 * we are only interested in the ownership release or acquire respectively and 121 * should be careful to avoid double releases/acquires. 122 * 123 * I haven't followed all transition paths mentally to verify the correctness. 124 * I likely also violate some VUs or miss some cases below. They are 125 * hopefully fixable and are left as TODOs. 126 */ 127static void 128vn_cmd_fix_image_memory_barrier(const struct vn_command_buffer *cmd, 129 const VkImageMemoryBarrier *src_barrier, 130 VkImageMemoryBarrier *out_barrier) 131{ 132 const struct vn_image *img = vn_image_from_handle(src_barrier->image); 133 134 *out_barrier = *src_barrier; 135 136 /* no fix needed */ 137 if (out_barrier->oldLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && 138 out_barrier->newLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) 139 return; 140 141 assert(img->wsi.is_wsi); 142 143 if (VN_PRESENT_SRC_INTERNAL_LAYOUT == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) 144 return; 145 146 /* prime blit src or no layout transition */ 147 if (img->wsi.is_prime_blit_src || 148 out_barrier->oldLayout == out_barrier->newLayout) { 149 if (out_barrier->oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) 150 out_barrier->oldLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; 151 if (out_barrier->newLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) 152 out_barrier->newLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; 153 return; 154 } 155 156 if (out_barrier->oldLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { 157 out_barrier->oldLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; 158 159 /* no availability operation needed */ 160 out_barrier->srcAccessMask = 0; 161 162 const uint32_t dst_qfi = out_barrier->dstQueueFamilyIndex; 163 if (img->sharing_mode == VK_SHARING_MODE_CONCURRENT) { 164 out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT; 165 out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 166 } else if (dst_qfi == out_barrier->srcQueueFamilyIndex || 167 dst_qfi == cmd->queue_family_index) { 168 out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT; 169 out_barrier->dstQueueFamilyIndex = cmd->queue_family_index; 170 } else { 171 /* The barrier also defines a queue family ownership transfer, and 172 * this is the one that gets submitted to the source queue family to 173 * release the ownership. Skip both the transfer and the transition. 174 */ 175 out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 176 out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 177 out_barrier->newLayout = out_barrier->oldLayout; 178 } 179 } else { 180 out_barrier->newLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; 181 182 /* no visibility operation needed */ 183 out_barrier->dstAccessMask = 0; 184 185 const uint32_t src_qfi = out_barrier->srcQueueFamilyIndex; 186 if (img->sharing_mode == VK_SHARING_MODE_CONCURRENT) { 187 out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 188 out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT; 189 } else if (src_qfi == out_barrier->dstQueueFamilyIndex || 190 src_qfi == cmd->queue_family_index) { 191 out_barrier->srcQueueFamilyIndex = cmd->queue_family_index; 192 out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT; 193 } else { 194 /* The barrier also defines a queue family ownership transfer, and 195 * this is the one that gets submitted to the destination queue 196 * family to acquire the ownership. Skip both the transfer and the 197 * transition. 198 */ 199 out_barrier->srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 200 out_barrier->dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; 201 out_barrier->oldLayout = out_barrier->newLayout; 202 } 203 } 204} 205 206static const VkImageMemoryBarrier * 207vn_cmd_wait_events_fix_image_memory_barriers( 208 struct vn_command_buffer *cmd, 209 const VkImageMemoryBarrier *src_barriers, 210 uint32_t count, 211 uint32_t *out_transfer_count) 212{ 213 *out_transfer_count = 0; 214 215 if (cmd->builder.render_pass || 216 !vn_image_memory_barrier_has_present_src(src_barriers, count)) 217 return src_barriers; 218 219 VkImageMemoryBarrier *img_barriers = 220 vn_cmd_get_image_memory_barriers(cmd, count * 2); 221 if (!img_barriers) { 222 cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; 223 return src_barriers; 224 } 225 226 /* vkCmdWaitEvents cannot be used for queue family ownership transfers. 227 * Nothing appears to be said about the submission order of image memory 228 * barriers in the same array. We take the liberty to move queue family 229 * ownership transfers to the tail. 230 */ 231 VkImageMemoryBarrier *transfer_barriers = img_barriers + count; 232 uint32_t transfer_count = 0; 233 uint32_t valid_count = 0; 234 for (uint32_t i = 0; i < count; i++) { 235 VkImageMemoryBarrier *img_barrier = &img_barriers[valid_count]; 236 vn_cmd_fix_image_memory_barrier(cmd, &src_barriers[i], img_barrier); 237 238 if (VN_PRESENT_SRC_INTERNAL_LAYOUT == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { 239 valid_count++; 240 continue; 241 } 242 243 if (img_barrier->srcQueueFamilyIndex == 244 img_barrier->dstQueueFamilyIndex) { 245 valid_count++; 246 } else { 247 transfer_barriers[transfer_count++] = *img_barrier; 248 } 249 } 250 251 assert(valid_count + transfer_count == count); 252 if (transfer_count) { 253 /* copy back to the tail */ 254 memcpy(&img_barriers[valid_count], transfer_barriers, 255 sizeof(*transfer_barriers) * transfer_count); 256 *out_transfer_count = transfer_count; 257 } 258 259 return img_barriers; 260} 261 262static const VkImageMemoryBarrier * 263vn_cmd_pipeline_barrier_fix_image_memory_barriers( 264 struct vn_command_buffer *cmd, 265 const VkImageMemoryBarrier *src_barriers, 266 uint32_t count) 267{ 268 if (cmd->builder.render_pass || 269 !vn_image_memory_barrier_has_present_src(src_barriers, count)) 270 return src_barriers; 271 272 VkImageMemoryBarrier *img_barriers = 273 vn_cmd_get_image_memory_barriers(cmd, count); 274 if (!img_barriers) { 275 cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; 276 return src_barriers; 277 } 278 279 for (uint32_t i = 0; i < count; i++) { 280 vn_cmd_fix_image_memory_barrier(cmd, &src_barriers[i], 281 &img_barriers[i]); 282 } 283 284 return img_barriers; 285} 286 287static void 288vn_cmd_encode_memory_barriers(struct vn_command_buffer *cmd, 289 VkPipelineStageFlags src_stage_mask, 290 VkPipelineStageFlags dst_stage_mask, 291 uint32_t buf_barrier_count, 292 const VkBufferMemoryBarrier *buf_barriers, 293 uint32_t img_barrier_count, 294 const VkImageMemoryBarrier *img_barriers) 295{ 296 const VkCommandBuffer cmd_handle = vn_command_buffer_to_handle(cmd); 297 298 VN_CMD_ENQUEUE(vkCmdPipelineBarrier, cmd_handle, src_stage_mask, 299 dst_stage_mask, 0, 0, NULL, buf_barrier_count, buf_barriers, 300 img_barrier_count, img_barriers); 301} 302 303static void 304vn_present_src_attachment_to_image_memory_barrier( 305 const struct vn_image *img, 306 const struct vn_present_src_attachment *att, 307 VkImageMemoryBarrier *img_barrier) 308{ 309 *img_barrier = (VkImageMemoryBarrier) 310 { 311 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 312 .srcAccessMask = att->src_access_mask, 313 .dstAccessMask = att->dst_access_mask, 314 .oldLayout = att->acquire ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR 315 : VN_PRESENT_SRC_INTERNAL_LAYOUT, 316 .newLayout = att->acquire ? VN_PRESENT_SRC_INTERNAL_LAYOUT 317 : VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 318 .image = vn_image_to_handle((struct vn_image *)img), 319 .subresourceRange = { 320 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 321 .levelCount = 1, 322 .layerCount = 1, 323 }, 324 }; 325} 326 327static void 328vn_cmd_transfer_present_src_images( 329 struct vn_command_buffer *cmd, 330 const struct vn_image *const *images, 331 const struct vn_present_src_attachment *atts, 332 uint32_t count) 333{ 334 VkImageMemoryBarrier *img_barriers = 335 vn_cmd_get_image_memory_barriers(cmd, count); 336 if (!img_barriers) { 337 cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; 338 return; 339 } 340 341 VkPipelineStageFlags src_stage_mask = 0; 342 VkPipelineStageFlags dst_stage_mask = 0; 343 for (uint32_t i = 0; i < count; i++) { 344 src_stage_mask |= atts[i].src_stage_mask; 345 dst_stage_mask |= atts[i].dst_stage_mask; 346 347 vn_present_src_attachment_to_image_memory_barrier(images[i], &atts[i], 348 &img_barriers[i]); 349 vn_cmd_fix_image_memory_barrier(cmd, &img_barriers[i], 350 &img_barriers[i]); 351 } 352 353 if (VN_PRESENT_SRC_INTERNAL_LAYOUT == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) 354 return; 355 356 vn_cmd_encode_memory_barriers(cmd, src_stage_mask, dst_stage_mask, 0, NULL, 357 count, img_barriers); 358} 359 360static void 361vn_cmd_begin_render_pass(struct vn_command_buffer *cmd, 362 const struct vn_render_pass *pass, 363 const struct vn_framebuffer *fb, 364 const VkRenderPassBeginInfo *begin_info) 365{ 366 cmd->builder.render_pass = pass; 367 cmd->builder.framebuffer = fb; 368 369 if (!pass->present_src_count || 370 cmd->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) 371 return; 372 373 /* find fb attachments */ 374 const VkImageView *views; 375 ASSERTED uint32_t view_count; 376 if (fb->image_view_count) { 377 views = fb->image_views; 378 view_count = fb->image_view_count; 379 } else { 380 const VkRenderPassAttachmentBeginInfo *imageless_info = 381 vk_find_struct_const(begin_info->pNext, 382 RENDER_PASS_ATTACHMENT_BEGIN_INFO); 383 assert(imageless_info); 384 views = imageless_info->pAttachments; 385 view_count = imageless_info->attachmentCount; 386 } 387 388 const struct vn_image **images = 389 vk_alloc(&cmd->allocator, sizeof(*images) * pass->present_src_count, 390 VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 391 if (!images) { 392 cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; 393 return; 394 } 395 396 for (uint32_t i = 0; i < pass->present_src_count; i++) { 397 const uint32_t index = pass->present_src_attachments[i].index; 398 assert(index < view_count); 399 images[i] = vn_image_view_from_handle(views[index])->image; 400 } 401 402 if (pass->acquire_count) { 403 vn_cmd_transfer_present_src_images( 404 cmd, images, pass->present_src_attachments, pass->acquire_count); 405 } 406 407 cmd->builder.present_src_images = images; 408} 409 410static void 411vn_cmd_end_render_pass(struct vn_command_buffer *cmd) 412{ 413 const struct vn_render_pass *pass = cmd->builder.render_pass; 414 415 cmd->builder.render_pass = NULL; 416 cmd->builder.framebuffer = NULL; 417 418 if (!pass->present_src_count || !cmd->builder.present_src_images) 419 return; 420 421 const struct vn_image **images = cmd->builder.present_src_images; 422 cmd->builder.present_src_images = NULL; 423 424 if (pass->release_count) { 425 vn_cmd_transfer_present_src_images( 426 cmd, images + pass->acquire_count, 427 pass->present_src_attachments + pass->acquire_count, 428 pass->release_count); 429 } 430 431 vk_free(&cmd->allocator, images); 432} 433 434/* command pool commands */ 435 436VkResult 437vn_CreateCommandPool(VkDevice device, 438 const VkCommandPoolCreateInfo *pCreateInfo, 439 const VkAllocationCallbacks *pAllocator, 440 VkCommandPool *pCommandPool) 441{ 442 VN_TRACE_FUNC(); 443 struct vn_device *dev = vn_device_from_handle(device); 444 const VkAllocationCallbacks *alloc = 445 pAllocator ? pAllocator : &dev->base.base.alloc; 446 447 struct vn_command_pool *pool = 448 vk_zalloc(alloc, sizeof(*pool), VN_DEFAULT_ALIGN, 449 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 450 if (!pool) 451 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 452 453 vn_object_base_init(&pool->base, VK_OBJECT_TYPE_COMMAND_POOL, &dev->base); 454 455 pool->allocator = *alloc; 456 pool->queue_family_index = pCreateInfo->queueFamilyIndex; 457 list_inithead(&pool->command_buffers); 458 459 VkCommandPool pool_handle = vn_command_pool_to_handle(pool); 460 vn_async_vkCreateCommandPool(dev->instance, device, pCreateInfo, NULL, 461 &pool_handle); 462 463 *pCommandPool = pool_handle; 464 465 return VK_SUCCESS; 466} 467 468void 469vn_DestroyCommandPool(VkDevice device, 470 VkCommandPool commandPool, 471 const VkAllocationCallbacks *pAllocator) 472{ 473 VN_TRACE_FUNC(); 474 struct vn_device *dev = vn_device_from_handle(device); 475 struct vn_command_pool *pool = vn_command_pool_from_handle(commandPool); 476 const VkAllocationCallbacks *alloc; 477 478 if (!pool) 479 return; 480 481 alloc = pAllocator ? pAllocator : &pool->allocator; 482 483 /* We must emit vkDestroyCommandPool before freeing the command buffers in 484 * pool->command_buffers. Otherwise, another thread might reuse their 485 * object ids while they still refer to the command buffers in the 486 * renderer. 487 */ 488 vn_async_vkDestroyCommandPool(dev->instance, device, commandPool, NULL); 489 490 list_for_each_entry_safe(struct vn_command_buffer, cmd, 491 &pool->command_buffers, head) { 492 vn_cs_encoder_fini(&cmd->cs); 493 vn_object_base_fini(&cmd->base); 494 vk_free(alloc, cmd); 495 } 496 497 vn_object_base_fini(&pool->base); 498 vk_free(alloc, pool); 499} 500 501VkResult 502vn_ResetCommandPool(VkDevice device, 503 VkCommandPool commandPool, 504 VkCommandPoolResetFlags flags) 505{ 506 VN_TRACE_FUNC(); 507 struct vn_device *dev = vn_device_from_handle(device); 508 struct vn_command_pool *pool = vn_command_pool_from_handle(commandPool); 509 510 list_for_each_entry_safe(struct vn_command_buffer, cmd, 511 &pool->command_buffers, head) { 512 vn_cs_encoder_reset(&cmd->cs); 513 cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL; 514 } 515 516 vn_async_vkResetCommandPool(dev->instance, device, commandPool, flags); 517 518 return VK_SUCCESS; 519} 520 521void 522vn_TrimCommandPool(VkDevice device, 523 VkCommandPool commandPool, 524 VkCommandPoolTrimFlags flags) 525{ 526 VN_TRACE_FUNC(); 527 struct vn_device *dev = vn_device_from_handle(device); 528 529 vn_async_vkTrimCommandPool(dev->instance, device, commandPool, flags); 530} 531 532/* command buffer commands */ 533 534VkResult 535vn_AllocateCommandBuffers(VkDevice device, 536 const VkCommandBufferAllocateInfo *pAllocateInfo, 537 VkCommandBuffer *pCommandBuffers) 538{ 539 VN_TRACE_FUNC(); 540 struct vn_device *dev = vn_device_from_handle(device); 541 struct vn_command_pool *pool = 542 vn_command_pool_from_handle(pAllocateInfo->commandPool); 543 const VkAllocationCallbacks *alloc = &pool->allocator; 544 545 for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++) { 546 struct vn_command_buffer *cmd = 547 vk_zalloc(alloc, sizeof(*cmd), VN_DEFAULT_ALIGN, 548 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 549 if (!cmd) { 550 for (uint32_t j = 0; j < i; j++) { 551 cmd = vn_command_buffer_from_handle(pCommandBuffers[j]); 552 vn_cs_encoder_fini(&cmd->cs); 553 list_del(&cmd->head); 554 vn_object_base_fini(&cmd->base); 555 vk_free(alloc, cmd); 556 } 557 memset(pCommandBuffers, 0, 558 sizeof(*pCommandBuffers) * pAllocateInfo->commandBufferCount); 559 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 560 } 561 562 vn_object_base_init(&cmd->base, VK_OBJECT_TYPE_COMMAND_BUFFER, 563 &dev->base); 564 cmd->device = dev; 565 cmd->allocator = pool->allocator; 566 cmd->level = pAllocateInfo->level; 567 cmd->queue_family_index = pool->queue_family_index; 568 569 list_addtail(&cmd->head, &pool->command_buffers); 570 571 cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL; 572 vn_cs_encoder_init(&cmd->cs, dev->instance, 573 VN_CS_ENCODER_STORAGE_SHMEM_POOL, 16 * 1024); 574 575 VkCommandBuffer cmd_handle = vn_command_buffer_to_handle(cmd); 576 pCommandBuffers[i] = cmd_handle; 577 } 578 579 vn_async_vkAllocateCommandBuffers(dev->instance, device, pAllocateInfo, 580 pCommandBuffers); 581 582 return VK_SUCCESS; 583} 584 585void 586vn_FreeCommandBuffers(VkDevice device, 587 VkCommandPool commandPool, 588 uint32_t commandBufferCount, 589 const VkCommandBuffer *pCommandBuffers) 590{ 591 VN_TRACE_FUNC(); 592 struct vn_device *dev = vn_device_from_handle(device); 593 struct vn_command_pool *pool = vn_command_pool_from_handle(commandPool); 594 const VkAllocationCallbacks *alloc = &pool->allocator; 595 596 vn_async_vkFreeCommandBuffers(dev->instance, device, commandPool, 597 commandBufferCount, pCommandBuffers); 598 599 for (uint32_t i = 0; i < commandBufferCount; i++) { 600 struct vn_command_buffer *cmd = 601 vn_command_buffer_from_handle(pCommandBuffers[i]); 602 603 if (!cmd) 604 continue; 605 606 if (cmd->builder.image_barriers) 607 vk_free(alloc, cmd->builder.image_barriers); 608 609 vn_cs_encoder_fini(&cmd->cs); 610 list_del(&cmd->head); 611 612 vn_object_base_fini(&cmd->base); 613 vk_free(alloc, cmd); 614 } 615} 616 617VkResult 618vn_ResetCommandBuffer(VkCommandBuffer commandBuffer, 619 VkCommandBufferResetFlags flags) 620{ 621 VN_TRACE_FUNC(); 622 struct vn_command_buffer *cmd = 623 vn_command_buffer_from_handle(commandBuffer); 624 625 vn_cs_encoder_reset(&cmd->cs); 626 cmd->state = VN_COMMAND_BUFFER_STATE_INITIAL; 627 cmd->draw_cmd_batched = 0; 628 629 vn_async_vkResetCommandBuffer(cmd->device->instance, commandBuffer, flags); 630 631 return VK_SUCCESS; 632} 633 634struct vn_command_buffer_begin_info { 635 VkCommandBufferBeginInfo begin; 636 VkCommandBufferInheritanceInfo inheritance; 637 VkCommandBufferInheritanceConditionalRenderingInfoEXT conditional_rendering; 638 639 bool has_inherited_pass; 640}; 641 642static const VkCommandBufferBeginInfo * 643vn_fix_command_buffer_begin_info(struct vn_command_buffer *cmd, 644 const VkCommandBufferBeginInfo *begin_info, 645 struct vn_command_buffer_begin_info *local) 646{ 647 local->has_inherited_pass = false; 648 649 if (!begin_info->pInheritanceInfo) 650 return begin_info; 651 652 const bool is_cmd_secondary = 653 cmd->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY; 654 const bool has_continue = 655 begin_info->flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT; 656 const bool has_renderpass = 657 is_cmd_secondary && 658 begin_info->pInheritanceInfo->renderPass != VK_NULL_HANDLE; 659 660 /* Can early-return if dynamic rendering is used and no structures need to 661 * be dropped from the pNext chain of VkCommandBufferInheritanceInfo. 662 */ 663 if (is_cmd_secondary && has_continue && !has_renderpass) 664 return begin_info; 665 666 local->begin = *begin_info; 667 668 if (!is_cmd_secondary) { 669 local->begin.pInheritanceInfo = NULL; 670 return &local->begin; 671 } 672 673 local->inheritance = *begin_info->pInheritanceInfo; 674 local->begin.pInheritanceInfo = &local->inheritance; 675 676 if (!has_continue) { 677 local->inheritance.framebuffer = VK_NULL_HANDLE; 678 local->inheritance.renderPass = VK_NULL_HANDLE; 679 local->inheritance.subpass = 0; 680 } else { 681 /* With early-returns above, it must be an inherited pass. */ 682 local->has_inherited_pass = true; 683 } 684 685 /* Per spec, about VkCommandBufferInheritanceRenderingInfo: 686 * 687 * If VkCommandBufferInheritanceInfo::renderPass is not VK_NULL_HANDLE, or 688 * VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT is not specified in 689 * VkCommandBufferBeginInfo::flags, parameters of this structure are 690 * ignored. 691 */ 692 VkBaseOutStructure *head = NULL; 693 VkBaseOutStructure *tail = NULL; 694 vk_foreach_struct_const(src, local->inheritance.pNext) { 695 void *pnext = NULL; 696 switch (src->sType) { 697 case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_CONDITIONAL_RENDERING_INFO_EXT: 698 memcpy( 699 &local->conditional_rendering, src, 700 sizeof(VkCommandBufferInheritanceConditionalRenderingInfoEXT)); 701 pnext = &local->conditional_rendering; 702 break; 703 case VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO: 704 default: 705 break; 706 } 707 708 if (pnext) { 709 if (!head) 710 head = pnext; 711 else 712 tail->pNext = pnext; 713 714 tail = pnext; 715 } 716 } 717 local->inheritance.pNext = head; 718 719 return &local->begin; 720} 721 722VkResult 723vn_BeginCommandBuffer(VkCommandBuffer commandBuffer, 724 const VkCommandBufferBeginInfo *pBeginInfo) 725{ 726 VN_TRACE_FUNC(); 727 struct vn_command_buffer *cmd = 728 vn_command_buffer_from_handle(commandBuffer); 729 struct vn_instance *instance = cmd->device->instance; 730 size_t cmd_size; 731 732 vn_cs_encoder_reset(&cmd->cs); 733 cmd->draw_cmd_batched = 0; 734 735 struct vn_command_buffer_begin_info local_begin_info; 736 pBeginInfo = 737 vn_fix_command_buffer_begin_info(cmd, pBeginInfo, &local_begin_info); 738 739 cmd_size = vn_sizeof_vkBeginCommandBuffer(commandBuffer, pBeginInfo); 740 if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size)) { 741 cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; 742 return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 743 } 744 745 vn_encode_vkBeginCommandBuffer(&cmd->cs, 0, commandBuffer, pBeginInfo); 746 747 cmd->state = VN_COMMAND_BUFFER_STATE_RECORDING; 748 749 if (local_begin_info.has_inherited_pass) { 750 const VkCommandBufferInheritanceInfo *inheritance_info = 751 pBeginInfo->pInheritanceInfo; 752 vn_cmd_begin_render_pass( 753 cmd, vn_render_pass_from_handle(inheritance_info->renderPass), 754 vn_framebuffer_from_handle(inheritance_info->framebuffer), NULL); 755 } 756 757 return VK_SUCCESS; 758} 759 760static void 761vn_cmd_submit(struct vn_command_buffer *cmd) 762{ 763 struct vn_instance *instance = cmd->device->instance; 764 765 if (cmd->state != VN_COMMAND_BUFFER_STATE_RECORDING) 766 return; 767 768 vn_cs_encoder_commit(&cmd->cs); 769 if (vn_cs_encoder_get_fatal(&cmd->cs)) { 770 cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; 771 vn_cs_encoder_reset(&cmd->cs); 772 return; 773 } 774 775 if (unlikely(!instance->renderer->info.supports_blob_id_0)) 776 vn_instance_wait_roundtrip(instance, cmd->cs.current_buffer_roundtrip); 777 778 if (vn_instance_ring_submit(instance, &cmd->cs) != VK_SUCCESS) { 779 cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; 780 return; 781 } 782 783 vn_cs_encoder_reset(&cmd->cs); 784 cmd->draw_cmd_batched = 0; 785} 786 787static inline void 788vn_cmd_count_draw_and_submit_on_batch_limit(struct vn_command_buffer *cmd) 789{ 790 if (++cmd->draw_cmd_batched >= vn_env.draw_cmd_batch_limit) 791 vn_cmd_submit(cmd); 792} 793 794VkResult 795vn_EndCommandBuffer(VkCommandBuffer commandBuffer) 796{ 797 VN_TRACE_FUNC(); 798 struct vn_command_buffer *cmd = 799 vn_command_buffer_from_handle(commandBuffer); 800 struct vn_instance *instance = cmd->device->instance; 801 size_t cmd_size; 802 803 if (cmd->state != VN_COMMAND_BUFFER_STATE_RECORDING) 804 return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 805 806 cmd_size = vn_sizeof_vkEndCommandBuffer(commandBuffer); 807 if (!vn_cs_encoder_reserve(&cmd->cs, cmd_size)) { 808 cmd->state = VN_COMMAND_BUFFER_STATE_INVALID; 809 return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 810 } 811 812 vn_encode_vkEndCommandBuffer(&cmd->cs, 0, commandBuffer); 813 814 vn_cmd_submit(cmd); 815 if (cmd->state == VN_COMMAND_BUFFER_STATE_INVALID) 816 return vn_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 817 818 cmd->state = VN_COMMAND_BUFFER_STATE_EXECUTABLE; 819 820 return VK_SUCCESS; 821} 822 823void 824vn_CmdBindPipeline(VkCommandBuffer commandBuffer, 825 VkPipelineBindPoint pipelineBindPoint, 826 VkPipeline pipeline) 827{ 828 VN_CMD_ENQUEUE(vkCmdBindPipeline, commandBuffer, pipelineBindPoint, 829 pipeline); 830} 831 832void 833vn_CmdSetViewport(VkCommandBuffer commandBuffer, 834 uint32_t firstViewport, 835 uint32_t viewportCount, 836 const VkViewport *pViewports) 837{ 838 VN_CMD_ENQUEUE(vkCmdSetViewport, commandBuffer, firstViewport, 839 viewportCount, pViewports); 840} 841 842void 843vn_CmdSetScissor(VkCommandBuffer commandBuffer, 844 uint32_t firstScissor, 845 uint32_t scissorCount, 846 const VkRect2D *pScissors) 847{ 848 VN_CMD_ENQUEUE(vkCmdSetScissor, commandBuffer, firstScissor, scissorCount, 849 pScissors); 850} 851 852void 853vn_CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) 854{ 855 VN_CMD_ENQUEUE(vkCmdSetLineWidth, commandBuffer, lineWidth); 856} 857 858void 859vn_CmdSetDepthBias(VkCommandBuffer commandBuffer, 860 float depthBiasConstantFactor, 861 float depthBiasClamp, 862 float depthBiasSlopeFactor) 863{ 864 VN_CMD_ENQUEUE(vkCmdSetDepthBias, commandBuffer, depthBiasConstantFactor, 865 depthBiasClamp, depthBiasSlopeFactor); 866} 867 868void 869vn_CmdSetBlendConstants(VkCommandBuffer commandBuffer, 870 const float blendConstants[4]) 871{ 872 VN_CMD_ENQUEUE(vkCmdSetBlendConstants, commandBuffer, blendConstants); 873} 874 875void 876vn_CmdSetDepthBounds(VkCommandBuffer commandBuffer, 877 float minDepthBounds, 878 float maxDepthBounds) 879{ 880 VN_CMD_ENQUEUE(vkCmdSetDepthBounds, commandBuffer, minDepthBounds, 881 maxDepthBounds); 882} 883 884void 885vn_CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, 886 VkStencilFaceFlags faceMask, 887 uint32_t compareMask) 888{ 889 VN_CMD_ENQUEUE(vkCmdSetStencilCompareMask, commandBuffer, faceMask, 890 compareMask); 891} 892 893void 894vn_CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, 895 VkStencilFaceFlags faceMask, 896 uint32_t writeMask) 897{ 898 VN_CMD_ENQUEUE(vkCmdSetStencilWriteMask, commandBuffer, faceMask, 899 writeMask); 900} 901 902void 903vn_CmdSetStencilReference(VkCommandBuffer commandBuffer, 904 VkStencilFaceFlags faceMask, 905 uint32_t reference) 906{ 907 VN_CMD_ENQUEUE(vkCmdSetStencilReference, commandBuffer, faceMask, 908 reference); 909} 910 911void 912vn_CmdBindDescriptorSets(VkCommandBuffer commandBuffer, 913 VkPipelineBindPoint pipelineBindPoint, 914 VkPipelineLayout layout, 915 uint32_t firstSet, 916 uint32_t descriptorSetCount, 917 const VkDescriptorSet *pDescriptorSets, 918 uint32_t dynamicOffsetCount, 919 const uint32_t *pDynamicOffsets) 920{ 921 VN_CMD_ENQUEUE(vkCmdBindDescriptorSets, commandBuffer, pipelineBindPoint, 922 layout, firstSet, descriptorSetCount, pDescriptorSets, 923 dynamicOffsetCount, pDynamicOffsets); 924} 925 926void 927vn_CmdBindIndexBuffer(VkCommandBuffer commandBuffer, 928 VkBuffer buffer, 929 VkDeviceSize offset, 930 VkIndexType indexType) 931{ 932 VN_CMD_ENQUEUE(vkCmdBindIndexBuffer, commandBuffer, buffer, offset, 933 indexType); 934} 935 936void 937vn_CmdBindVertexBuffers(VkCommandBuffer commandBuffer, 938 uint32_t firstBinding, 939 uint32_t bindingCount, 940 const VkBuffer *pBuffers, 941 const VkDeviceSize *pOffsets) 942{ 943 VN_CMD_ENQUEUE(vkCmdBindVertexBuffers, commandBuffer, firstBinding, 944 bindingCount, pBuffers, pOffsets); 945} 946 947void 948vn_CmdDraw(VkCommandBuffer commandBuffer, 949 uint32_t vertexCount, 950 uint32_t instanceCount, 951 uint32_t firstVertex, 952 uint32_t firstInstance) 953{ 954 VN_CMD_ENQUEUE(vkCmdDraw, commandBuffer, vertexCount, instanceCount, 955 firstVertex, firstInstance); 956 957 vn_cmd_count_draw_and_submit_on_batch_limit( 958 vn_command_buffer_from_handle(commandBuffer)); 959} 960 961void 962vn_CmdBeginRendering(VkCommandBuffer commandBuffer, 963 const VkRenderingInfo *pRenderingInfo) 964{ 965 VN_CMD_ENQUEUE(vkCmdBeginRendering, commandBuffer, pRenderingInfo); 966} 967 968void 969vn_CmdEndRendering(VkCommandBuffer commandBuffer) 970{ 971 VN_CMD_ENQUEUE(vkCmdEndRendering, commandBuffer); 972} 973 974void 975vn_CmdDrawIndexed(VkCommandBuffer commandBuffer, 976 uint32_t indexCount, 977 uint32_t instanceCount, 978 uint32_t firstIndex, 979 int32_t vertexOffset, 980 uint32_t firstInstance) 981{ 982 VN_CMD_ENQUEUE(vkCmdDrawIndexed, commandBuffer, indexCount, instanceCount, 983 firstIndex, vertexOffset, firstInstance); 984 985 vn_cmd_count_draw_and_submit_on_batch_limit( 986 vn_command_buffer_from_handle(commandBuffer)); 987} 988 989void 990vn_CmdDrawIndirect(VkCommandBuffer commandBuffer, 991 VkBuffer buffer, 992 VkDeviceSize offset, 993 uint32_t drawCount, 994 uint32_t stride) 995{ 996 VN_CMD_ENQUEUE(vkCmdDrawIndirect, commandBuffer, buffer, offset, drawCount, 997 stride); 998 999 vn_cmd_count_draw_and_submit_on_batch_limit( 1000 vn_command_buffer_from_handle(commandBuffer)); 1001} 1002 1003void 1004vn_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, 1005 VkBuffer buffer, 1006 VkDeviceSize offset, 1007 uint32_t drawCount, 1008 uint32_t stride) 1009{ 1010 VN_CMD_ENQUEUE(vkCmdDrawIndexedIndirect, commandBuffer, buffer, offset, 1011 drawCount, stride); 1012 1013 vn_cmd_count_draw_and_submit_on_batch_limit( 1014 vn_command_buffer_from_handle(commandBuffer)); 1015} 1016 1017void 1018vn_CmdDrawIndirectCount(VkCommandBuffer commandBuffer, 1019 VkBuffer buffer, 1020 VkDeviceSize offset, 1021 VkBuffer countBuffer, 1022 VkDeviceSize countBufferOffset, 1023 uint32_t maxDrawCount, 1024 uint32_t stride) 1025{ 1026 VN_CMD_ENQUEUE(vkCmdDrawIndirectCount, commandBuffer, buffer, offset, 1027 countBuffer, countBufferOffset, maxDrawCount, stride); 1028 1029 vn_cmd_count_draw_and_submit_on_batch_limit( 1030 vn_command_buffer_from_handle(commandBuffer)); 1031} 1032 1033void 1034vn_CmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, 1035 VkBuffer buffer, 1036 VkDeviceSize offset, 1037 VkBuffer countBuffer, 1038 VkDeviceSize countBufferOffset, 1039 uint32_t maxDrawCount, 1040 uint32_t stride) 1041{ 1042 VN_CMD_ENQUEUE(vkCmdDrawIndexedIndirectCount, commandBuffer, buffer, 1043 offset, countBuffer, countBufferOffset, maxDrawCount, 1044 stride); 1045 1046 vn_cmd_count_draw_and_submit_on_batch_limit( 1047 vn_command_buffer_from_handle(commandBuffer)); 1048} 1049 1050void 1051vn_CmdDispatch(VkCommandBuffer commandBuffer, 1052 uint32_t groupCountX, 1053 uint32_t groupCountY, 1054 uint32_t groupCountZ) 1055{ 1056 VN_CMD_ENQUEUE(vkCmdDispatch, commandBuffer, groupCountX, groupCountY, 1057 groupCountZ); 1058} 1059 1060void 1061vn_CmdDispatchIndirect(VkCommandBuffer commandBuffer, 1062 VkBuffer buffer, 1063 VkDeviceSize offset) 1064{ 1065 VN_CMD_ENQUEUE(vkCmdDispatchIndirect, commandBuffer, buffer, offset); 1066} 1067 1068void 1069vn_CmdCopyBuffer(VkCommandBuffer commandBuffer, 1070 VkBuffer srcBuffer, 1071 VkBuffer dstBuffer, 1072 uint32_t regionCount, 1073 const VkBufferCopy *pRegions) 1074{ 1075 VN_CMD_ENQUEUE(vkCmdCopyBuffer, commandBuffer, srcBuffer, dstBuffer, 1076 regionCount, pRegions); 1077} 1078 1079void 1080vn_CmdCopyBuffer2(VkCommandBuffer commandBuffer, 1081 const VkCopyBufferInfo2 *pCopyBufferInfo) 1082{ 1083 VN_CMD_ENQUEUE(vkCmdCopyBuffer2, commandBuffer, pCopyBufferInfo); 1084} 1085 1086void 1087vn_CmdCopyImage(VkCommandBuffer commandBuffer, 1088 VkImage srcImage, 1089 VkImageLayout srcImageLayout, 1090 VkImage dstImage, 1091 VkImageLayout dstImageLayout, 1092 uint32_t regionCount, 1093 const VkImageCopy *pRegions) 1094{ 1095 VN_CMD_ENQUEUE(vkCmdCopyImage, commandBuffer, srcImage, srcImageLayout, 1096 dstImage, dstImageLayout, regionCount, pRegions); 1097} 1098 1099void 1100vn_CmdCopyImage2(VkCommandBuffer commandBuffer, 1101 const VkCopyImageInfo2 *pCopyImageInfo) 1102{ 1103 VN_CMD_ENQUEUE(vkCmdCopyImage2, commandBuffer, pCopyImageInfo); 1104} 1105 1106void 1107vn_CmdBlitImage(VkCommandBuffer commandBuffer, 1108 VkImage srcImage, 1109 VkImageLayout srcImageLayout, 1110 VkImage dstImage, 1111 VkImageLayout dstImageLayout, 1112 uint32_t regionCount, 1113 const VkImageBlit *pRegions, 1114 VkFilter filter) 1115{ 1116 VN_CMD_ENQUEUE(vkCmdBlitImage, commandBuffer, srcImage, srcImageLayout, 1117 dstImage, dstImageLayout, regionCount, pRegions, filter); 1118} 1119 1120void 1121vn_CmdBlitImage2(VkCommandBuffer commandBuffer, 1122 const VkBlitImageInfo2 *pBlitImageInfo) 1123{ 1124 VN_CMD_ENQUEUE(vkCmdBlitImage2, commandBuffer, pBlitImageInfo); 1125} 1126 1127void 1128vn_CmdCopyBufferToImage(VkCommandBuffer commandBuffer, 1129 VkBuffer srcBuffer, 1130 VkImage dstImage, 1131 VkImageLayout dstImageLayout, 1132 uint32_t regionCount, 1133 const VkBufferImageCopy *pRegions) 1134{ 1135 VN_CMD_ENQUEUE(vkCmdCopyBufferToImage, commandBuffer, srcBuffer, dstImage, 1136 dstImageLayout, regionCount, pRegions); 1137} 1138 1139void 1140vn_CmdCopyBufferToImage2( 1141 VkCommandBuffer commandBuffer, 1142 const VkCopyBufferToImageInfo2 *pCopyBufferToImageInfo) 1143{ 1144 VN_CMD_ENQUEUE(vkCmdCopyBufferToImage2, commandBuffer, 1145 pCopyBufferToImageInfo); 1146} 1147 1148static bool 1149vn_needs_prime_blit(VkImage src_image, VkImageLayout src_image_layout) 1150{ 1151 if (src_image_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && 1152 VN_PRESENT_SRC_INTERNAL_LAYOUT != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) { 1153 1154 /* sanity check */ 1155 ASSERTED const struct vn_image *img = vn_image_from_handle(src_image); 1156 assert(img->wsi.is_wsi && img->wsi.is_prime_blit_src); 1157 return true; 1158 } 1159 1160 return false; 1161} 1162 1163static void 1164vn_transition_prime_layout(struct vn_command_buffer *cmd, VkBuffer dst_buffer) 1165{ 1166 const VkBufferMemoryBarrier buf_barrier = { 1167 .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 1168 .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, 1169 .srcQueueFamilyIndex = cmd->queue_family_index, 1170 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT, 1171 .buffer = dst_buffer, 1172 .size = VK_WHOLE_SIZE, 1173 }; 1174 vn_cmd_encode_memory_barriers(cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, 1175 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 1, 1176 &buf_barrier, 0, NULL); 1177} 1178 1179void 1180vn_CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, 1181 VkImage srcImage, 1182 VkImageLayout srcImageLayout, 1183 VkBuffer dstBuffer, 1184 uint32_t regionCount, 1185 const VkBufferImageCopy *pRegions) 1186{ 1187 struct vn_command_buffer *cmd = 1188 vn_command_buffer_from_handle(commandBuffer); 1189 1190 bool prime_blit = vn_needs_prime_blit(srcImage, srcImageLayout); 1191 if (prime_blit) 1192 srcImageLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; 1193 1194 VN_CMD_ENQUEUE(vkCmdCopyImageToBuffer, commandBuffer, srcImage, 1195 srcImageLayout, dstBuffer, regionCount, pRegions); 1196 1197 if (prime_blit) 1198 vn_transition_prime_layout(cmd, dstBuffer); 1199} 1200 1201void 1202vn_CmdCopyImageToBuffer2( 1203 VkCommandBuffer commandBuffer, 1204 const VkCopyImageToBufferInfo2 *pCopyImageToBufferInfo) 1205{ 1206 struct vn_command_buffer *cmd = 1207 vn_command_buffer_from_handle(commandBuffer); 1208 struct VkCopyImageToBufferInfo2 copy_info = *pCopyImageToBufferInfo; 1209 1210 bool prime_blit = 1211 vn_needs_prime_blit(copy_info.srcImage, copy_info.srcImageLayout); 1212 if (prime_blit) 1213 copy_info.srcImageLayout = VN_PRESENT_SRC_INTERNAL_LAYOUT; 1214 1215 VN_CMD_ENQUEUE(vkCmdCopyImageToBuffer2, commandBuffer, ©_info); 1216 1217 if (prime_blit) 1218 vn_transition_prime_layout(cmd, copy_info.dstBuffer); 1219} 1220 1221void 1222vn_CmdUpdateBuffer(VkCommandBuffer commandBuffer, 1223 VkBuffer dstBuffer, 1224 VkDeviceSize dstOffset, 1225 VkDeviceSize dataSize, 1226 const void *pData) 1227{ 1228 VN_CMD_ENQUEUE(vkCmdUpdateBuffer, commandBuffer, dstBuffer, dstOffset, 1229 dataSize, pData); 1230} 1231 1232void 1233vn_CmdFillBuffer(VkCommandBuffer commandBuffer, 1234 VkBuffer dstBuffer, 1235 VkDeviceSize dstOffset, 1236 VkDeviceSize size, 1237 uint32_t data) 1238{ 1239 VN_CMD_ENQUEUE(vkCmdFillBuffer, commandBuffer, dstBuffer, dstOffset, size, 1240 data); 1241} 1242 1243void 1244vn_CmdClearColorImage(VkCommandBuffer commandBuffer, 1245 VkImage image, 1246 VkImageLayout imageLayout, 1247 const VkClearColorValue *pColor, 1248 uint32_t rangeCount, 1249 const VkImageSubresourceRange *pRanges) 1250{ 1251 VN_CMD_ENQUEUE(vkCmdClearColorImage, commandBuffer, image, imageLayout, 1252 pColor, rangeCount, pRanges); 1253} 1254 1255void 1256vn_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, 1257 VkImage image, 1258 VkImageLayout imageLayout, 1259 const VkClearDepthStencilValue *pDepthStencil, 1260 uint32_t rangeCount, 1261 const VkImageSubresourceRange *pRanges) 1262{ 1263 VN_CMD_ENQUEUE(vkCmdClearDepthStencilImage, commandBuffer, image, 1264 imageLayout, pDepthStencil, rangeCount, pRanges); 1265} 1266 1267void 1268vn_CmdClearAttachments(VkCommandBuffer commandBuffer, 1269 uint32_t attachmentCount, 1270 const VkClearAttachment *pAttachments, 1271 uint32_t rectCount, 1272 const VkClearRect *pRects) 1273{ 1274 VN_CMD_ENQUEUE(vkCmdClearAttachments, commandBuffer, attachmentCount, 1275 pAttachments, rectCount, pRects); 1276} 1277 1278void 1279vn_CmdResolveImage(VkCommandBuffer commandBuffer, 1280 VkImage srcImage, 1281 VkImageLayout srcImageLayout, 1282 VkImage dstImage, 1283 VkImageLayout dstImageLayout, 1284 uint32_t regionCount, 1285 const VkImageResolve *pRegions) 1286{ 1287 VN_CMD_ENQUEUE(vkCmdResolveImage, commandBuffer, srcImage, srcImageLayout, 1288 dstImage, dstImageLayout, regionCount, pRegions); 1289} 1290 1291void 1292vn_CmdResolveImage2(VkCommandBuffer commandBuffer, 1293 const VkResolveImageInfo2 *pResolveImageInfo) 1294{ 1295 VN_CMD_ENQUEUE(vkCmdResolveImage2, commandBuffer, pResolveImageInfo); 1296} 1297 1298void 1299vn_CmdSetEvent(VkCommandBuffer commandBuffer, 1300 VkEvent event, 1301 VkPipelineStageFlags stageMask) 1302{ 1303 VN_CMD_ENQUEUE(vkCmdSetEvent, commandBuffer, event, stageMask); 1304 1305 vn_feedback_event_cmd_record(commandBuffer, event, stageMask, 1306 VK_EVENT_SET); 1307} 1308 1309void 1310vn_CmdResetEvent(VkCommandBuffer commandBuffer, 1311 VkEvent event, 1312 VkPipelineStageFlags stageMask) 1313{ 1314 VN_CMD_ENQUEUE(vkCmdResetEvent, commandBuffer, event, stageMask); 1315 1316 vn_feedback_event_cmd_record(commandBuffer, event, stageMask, 1317 VK_EVENT_RESET); 1318} 1319 1320void 1321vn_CmdWaitEvents(VkCommandBuffer commandBuffer, 1322 uint32_t eventCount, 1323 const VkEvent *pEvents, 1324 VkPipelineStageFlags srcStageMask, 1325 VkPipelineStageFlags dstStageMask, 1326 uint32_t memoryBarrierCount, 1327 const VkMemoryBarrier *pMemoryBarriers, 1328 uint32_t bufferMemoryBarrierCount, 1329 const VkBufferMemoryBarrier *pBufferMemoryBarriers, 1330 uint32_t imageMemoryBarrierCount, 1331 const VkImageMemoryBarrier *pImageMemoryBarriers) 1332{ 1333 struct vn_command_buffer *cmd = 1334 vn_command_buffer_from_handle(commandBuffer); 1335 uint32_t transfer_count; 1336 1337 pImageMemoryBarriers = vn_cmd_wait_events_fix_image_memory_barriers( 1338 cmd, pImageMemoryBarriers, imageMemoryBarrierCount, &transfer_count); 1339 imageMemoryBarrierCount -= transfer_count; 1340 1341 VN_CMD_ENQUEUE(vkCmdWaitEvents, commandBuffer, eventCount, pEvents, 1342 srcStageMask, dstStageMask, memoryBarrierCount, 1343 pMemoryBarriers, bufferMemoryBarrierCount, 1344 pBufferMemoryBarriers, imageMemoryBarrierCount, 1345 pImageMemoryBarriers); 1346 1347 if (transfer_count) { 1348 pImageMemoryBarriers += imageMemoryBarrierCount; 1349 vn_cmd_encode_memory_barriers(cmd, srcStageMask, dstStageMask, 0, NULL, 1350 transfer_count, pImageMemoryBarriers); 1351 } 1352} 1353 1354void 1355vn_CmdPipelineBarrier(VkCommandBuffer commandBuffer, 1356 VkPipelineStageFlags srcStageMask, 1357 VkPipelineStageFlags dstStageMask, 1358 VkDependencyFlags dependencyFlags, 1359 uint32_t memoryBarrierCount, 1360 const VkMemoryBarrier *pMemoryBarriers, 1361 uint32_t bufferMemoryBarrierCount, 1362 const VkBufferMemoryBarrier *pBufferMemoryBarriers, 1363 uint32_t imageMemoryBarrierCount, 1364 const VkImageMemoryBarrier *pImageMemoryBarriers) 1365{ 1366 struct vn_command_buffer *cmd = 1367 vn_command_buffer_from_handle(commandBuffer); 1368 1369 pImageMemoryBarriers = vn_cmd_pipeline_barrier_fix_image_memory_barriers( 1370 cmd, pImageMemoryBarriers, imageMemoryBarrierCount); 1371 1372 VN_CMD_ENQUEUE(vkCmdPipelineBarrier, commandBuffer, srcStageMask, 1373 dstStageMask, dependencyFlags, memoryBarrierCount, 1374 pMemoryBarriers, bufferMemoryBarrierCount, 1375 pBufferMemoryBarriers, imageMemoryBarrierCount, 1376 pImageMemoryBarriers); 1377} 1378 1379void 1380vn_CmdBeginQuery(VkCommandBuffer commandBuffer, 1381 VkQueryPool queryPool, 1382 uint32_t query, 1383 VkQueryControlFlags flags) 1384{ 1385 VN_CMD_ENQUEUE(vkCmdBeginQuery, commandBuffer, queryPool, query, flags); 1386} 1387 1388void 1389vn_CmdEndQuery(VkCommandBuffer commandBuffer, 1390 VkQueryPool queryPool, 1391 uint32_t query) 1392{ 1393 VN_CMD_ENQUEUE(vkCmdEndQuery, commandBuffer, queryPool, query); 1394} 1395 1396void 1397vn_CmdResetQueryPool(VkCommandBuffer commandBuffer, 1398 VkQueryPool queryPool, 1399 uint32_t firstQuery, 1400 uint32_t queryCount) 1401{ 1402 VN_CMD_ENQUEUE(vkCmdResetQueryPool, commandBuffer, queryPool, firstQuery, 1403 queryCount); 1404} 1405 1406void 1407vn_CmdWriteTimestamp(VkCommandBuffer commandBuffer, 1408 VkPipelineStageFlagBits pipelineStage, 1409 VkQueryPool queryPool, 1410 uint32_t query) 1411{ 1412 VN_CMD_ENQUEUE(vkCmdWriteTimestamp, commandBuffer, pipelineStage, 1413 queryPool, query); 1414} 1415 1416void 1417vn_CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, 1418 VkQueryPool queryPool, 1419 uint32_t firstQuery, 1420 uint32_t queryCount, 1421 VkBuffer dstBuffer, 1422 VkDeviceSize dstOffset, 1423 VkDeviceSize stride, 1424 VkQueryResultFlags flags) 1425{ 1426 VN_CMD_ENQUEUE(vkCmdCopyQueryPoolResults, commandBuffer, queryPool, 1427 firstQuery, queryCount, dstBuffer, dstOffset, stride, 1428 flags); 1429} 1430 1431void 1432vn_CmdPushConstants(VkCommandBuffer commandBuffer, 1433 VkPipelineLayout layout, 1434 VkShaderStageFlags stageFlags, 1435 uint32_t offset, 1436 uint32_t size, 1437 const void *pValues) 1438{ 1439 VN_CMD_ENQUEUE(vkCmdPushConstants, commandBuffer, layout, stageFlags, 1440 offset, size, pValues); 1441} 1442 1443void 1444vn_CmdBeginRenderPass(VkCommandBuffer commandBuffer, 1445 const VkRenderPassBeginInfo *pRenderPassBegin, 1446 VkSubpassContents contents) 1447{ 1448 struct vn_command_buffer *cmd = 1449 vn_command_buffer_from_handle(commandBuffer); 1450 1451 vn_cmd_begin_render_pass( 1452 cmd, vn_render_pass_from_handle(pRenderPassBegin->renderPass), 1453 vn_framebuffer_from_handle(pRenderPassBegin->framebuffer), 1454 pRenderPassBegin); 1455 1456 VN_CMD_ENQUEUE(vkCmdBeginRenderPass, commandBuffer, pRenderPassBegin, 1457 contents); 1458} 1459 1460void 1461vn_CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) 1462{ 1463 VN_CMD_ENQUEUE(vkCmdNextSubpass, commandBuffer, contents); 1464} 1465 1466void 1467vn_CmdEndRenderPass(VkCommandBuffer commandBuffer) 1468{ 1469 struct vn_command_buffer *cmd = 1470 vn_command_buffer_from_handle(commandBuffer); 1471 1472 VN_CMD_ENQUEUE(vkCmdEndRenderPass, commandBuffer); 1473 1474 vn_cmd_end_render_pass(cmd); 1475} 1476 1477void 1478vn_CmdBeginRenderPass2(VkCommandBuffer commandBuffer, 1479 const VkRenderPassBeginInfo *pRenderPassBegin, 1480 const VkSubpassBeginInfo *pSubpassBeginInfo) 1481{ 1482 struct vn_command_buffer *cmd = 1483 vn_command_buffer_from_handle(commandBuffer); 1484 1485 vn_cmd_begin_render_pass( 1486 cmd, vn_render_pass_from_handle(pRenderPassBegin->renderPass), 1487 vn_framebuffer_from_handle(pRenderPassBegin->framebuffer), 1488 pRenderPassBegin); 1489 1490 VN_CMD_ENQUEUE(vkCmdBeginRenderPass2, commandBuffer, pRenderPassBegin, 1491 pSubpassBeginInfo); 1492} 1493 1494void 1495vn_CmdNextSubpass2(VkCommandBuffer commandBuffer, 1496 const VkSubpassBeginInfo *pSubpassBeginInfo, 1497 const VkSubpassEndInfo *pSubpassEndInfo) 1498{ 1499 VN_CMD_ENQUEUE(vkCmdNextSubpass2, commandBuffer, pSubpassBeginInfo, 1500 pSubpassEndInfo); 1501} 1502 1503void 1504vn_CmdEndRenderPass2(VkCommandBuffer commandBuffer, 1505 const VkSubpassEndInfo *pSubpassEndInfo) 1506{ 1507 struct vn_command_buffer *cmd = 1508 vn_command_buffer_from_handle(commandBuffer); 1509 1510 VN_CMD_ENQUEUE(vkCmdEndRenderPass2, commandBuffer, pSubpassEndInfo); 1511 1512 vn_cmd_end_render_pass(cmd); 1513} 1514 1515void 1516vn_CmdExecuteCommands(VkCommandBuffer commandBuffer, 1517 uint32_t commandBufferCount, 1518 const VkCommandBuffer *pCommandBuffers) 1519{ 1520 VN_CMD_ENQUEUE(vkCmdExecuteCommands, commandBuffer, commandBufferCount, 1521 pCommandBuffers); 1522} 1523 1524void 1525vn_CmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t deviceMask) 1526{ 1527 VN_CMD_ENQUEUE(vkCmdSetDeviceMask, commandBuffer, deviceMask); 1528} 1529 1530void 1531vn_CmdDispatchBase(VkCommandBuffer commandBuffer, 1532 uint32_t baseGroupX, 1533 uint32_t baseGroupY, 1534 uint32_t baseGroupZ, 1535 uint32_t groupCountX, 1536 uint32_t groupCountY, 1537 uint32_t groupCountZ) 1538{ 1539 VN_CMD_ENQUEUE(vkCmdDispatchBase, commandBuffer, baseGroupX, baseGroupY, 1540 baseGroupZ, groupCountX, groupCountY, groupCountZ); 1541} 1542 1543void 1544vn_CmdSetLineStippleEXT(VkCommandBuffer commandBuffer, 1545 uint32_t lineStippleFactor, 1546 uint16_t lineStipplePattern) 1547{ 1548 VN_CMD_ENQUEUE(vkCmdSetLineStippleEXT, commandBuffer, lineStippleFactor, 1549 lineStipplePattern); 1550} 1551 1552void 1553vn_CmdBeginQueryIndexedEXT(VkCommandBuffer commandBuffer, 1554 VkQueryPool queryPool, 1555 uint32_t query, 1556 VkQueryControlFlags flags, 1557 uint32_t index) 1558{ 1559 VN_CMD_ENQUEUE(vkCmdBeginQueryIndexedEXT, commandBuffer, queryPool, query, 1560 flags, index); 1561} 1562 1563void 1564vn_CmdEndQueryIndexedEXT(VkCommandBuffer commandBuffer, 1565 VkQueryPool queryPool, 1566 uint32_t query, 1567 uint32_t index) 1568{ 1569 VN_CMD_ENQUEUE(vkCmdEndQueryIndexedEXT, commandBuffer, queryPool, query, 1570 index); 1571} 1572 1573void 1574vn_CmdBindTransformFeedbackBuffersEXT(VkCommandBuffer commandBuffer, 1575 uint32_t firstBinding, 1576 uint32_t bindingCount, 1577 const VkBuffer *pBuffers, 1578 const VkDeviceSize *pOffsets, 1579 const VkDeviceSize *pSizes) 1580{ 1581 VN_CMD_ENQUEUE(vkCmdBindTransformFeedbackBuffersEXT, commandBuffer, 1582 firstBinding, bindingCount, pBuffers, pOffsets, pSizes); 1583} 1584 1585void 1586vn_CmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer, 1587 uint32_t firstCounterBuffer, 1588 uint32_t counterBufferCount, 1589 const VkBuffer *pCounterBuffers, 1590 const VkDeviceSize *pCounterBufferOffsets) 1591{ 1592 VN_CMD_ENQUEUE(vkCmdBeginTransformFeedbackEXT, commandBuffer, 1593 firstCounterBuffer, counterBufferCount, pCounterBuffers, 1594 pCounterBufferOffsets); 1595} 1596 1597void 1598vn_CmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer, 1599 uint32_t firstCounterBuffer, 1600 uint32_t counterBufferCount, 1601 const VkBuffer *pCounterBuffers, 1602 const VkDeviceSize *pCounterBufferOffsets) 1603{ 1604 VN_CMD_ENQUEUE(vkCmdEndTransformFeedbackEXT, commandBuffer, 1605 firstCounterBuffer, counterBufferCount, pCounterBuffers, 1606 pCounterBufferOffsets); 1607} 1608 1609void 1610vn_CmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, 1611 uint32_t instanceCount, 1612 uint32_t firstInstance, 1613 VkBuffer counterBuffer, 1614 VkDeviceSize counterBufferOffset, 1615 uint32_t counterOffset, 1616 uint32_t vertexStride) 1617{ 1618 VN_CMD_ENQUEUE(vkCmdDrawIndirectByteCountEXT, commandBuffer, instanceCount, 1619 firstInstance, counterBuffer, counterBufferOffset, 1620 counterOffset, vertexStride); 1621 1622 vn_cmd_count_draw_and_submit_on_batch_limit( 1623 vn_command_buffer_from_handle(commandBuffer)); 1624} 1625 1626void 1627vn_CmdBindVertexBuffers2(VkCommandBuffer commandBuffer, 1628 uint32_t firstBinding, 1629 uint32_t bindingCount, 1630 const VkBuffer *pBuffers, 1631 const VkDeviceSize *pOffsets, 1632 const VkDeviceSize *pSizes, 1633 const VkDeviceSize *pStrides) 1634{ 1635 VN_CMD_ENQUEUE(vkCmdBindVertexBuffers2, commandBuffer, firstBinding, 1636 bindingCount, pBuffers, pOffsets, pSizes, pStrides); 1637} 1638 1639void 1640vn_CmdSetCullMode(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode) 1641{ 1642 VN_CMD_ENQUEUE(vkCmdSetCullMode, commandBuffer, cullMode); 1643} 1644 1645void 1646vn_CmdSetDepthBoundsTestEnable(VkCommandBuffer commandBuffer, 1647 VkBool32 depthBoundsTestEnable) 1648{ 1649 VN_CMD_ENQUEUE(vkCmdSetDepthBoundsTestEnable, commandBuffer, 1650 depthBoundsTestEnable); 1651} 1652 1653void 1654vn_CmdSetDepthCompareOp(VkCommandBuffer commandBuffer, 1655 VkCompareOp depthCompareOp) 1656{ 1657 VN_CMD_ENQUEUE(vkCmdSetDepthCompareOp, commandBuffer, depthCompareOp); 1658} 1659 1660void 1661vn_CmdSetDepthTestEnable(VkCommandBuffer commandBuffer, 1662 VkBool32 depthTestEnable) 1663{ 1664 VN_CMD_ENQUEUE(vkCmdSetDepthTestEnable, commandBuffer, depthTestEnable); 1665} 1666 1667void 1668vn_CmdSetDepthWriteEnable(VkCommandBuffer commandBuffer, 1669 VkBool32 depthWriteEnable) 1670{ 1671 VN_CMD_ENQUEUE(vkCmdSetDepthWriteEnable, commandBuffer, depthWriteEnable); 1672} 1673 1674void 1675vn_CmdSetFrontFace(VkCommandBuffer commandBuffer, VkFrontFace frontFace) 1676{ 1677 VN_CMD_ENQUEUE(vkCmdSetFrontFace, commandBuffer, frontFace); 1678} 1679 1680void 1681vn_CmdSetPrimitiveTopology(VkCommandBuffer commandBuffer, 1682 VkPrimitiveTopology primitiveTopology) 1683{ 1684 VN_CMD_ENQUEUE(vkCmdSetPrimitiveTopology, commandBuffer, 1685 primitiveTopology); 1686} 1687 1688void 1689vn_CmdSetScissorWithCount(VkCommandBuffer commandBuffer, 1690 uint32_t scissorCount, 1691 const VkRect2D *pScissors) 1692{ 1693 VN_CMD_ENQUEUE(vkCmdSetScissorWithCount, commandBuffer, scissorCount, 1694 pScissors); 1695} 1696 1697void 1698vn_CmdSetStencilOp(VkCommandBuffer commandBuffer, 1699 VkStencilFaceFlags faceMask, 1700 VkStencilOp failOp, 1701 VkStencilOp passOp, 1702 VkStencilOp depthFailOp, 1703 VkCompareOp compareOp) 1704{ 1705 VN_CMD_ENQUEUE(vkCmdSetStencilOp, commandBuffer, faceMask, failOp, passOp, 1706 depthFailOp, compareOp); 1707} 1708 1709void 1710vn_CmdSetStencilTestEnable(VkCommandBuffer commandBuffer, 1711 VkBool32 stencilTestEnable) 1712{ 1713 VN_CMD_ENQUEUE(vkCmdSetStencilTestEnable, commandBuffer, 1714 stencilTestEnable); 1715} 1716 1717void 1718vn_CmdSetViewportWithCount(VkCommandBuffer commandBuffer, 1719 uint32_t viewportCount, 1720 const VkViewport *pViewports) 1721{ 1722 VN_CMD_ENQUEUE(vkCmdSetViewportWithCount, commandBuffer, viewportCount, 1723 pViewports); 1724} 1725 1726void 1727vn_CmdSetDepthBiasEnable(VkCommandBuffer commandBuffer, 1728 VkBool32 depthBiasEnable) 1729{ 1730 VN_CMD_ENQUEUE(vkCmdSetDepthBiasEnable, commandBuffer, depthBiasEnable); 1731} 1732 1733void 1734vn_CmdSetLogicOpEXT(VkCommandBuffer commandBuffer, VkLogicOp logicOp) 1735{ 1736 VN_CMD_ENQUEUE(vkCmdSetLogicOpEXT, commandBuffer, logicOp); 1737} 1738 1739void 1740vn_CmdSetPatchControlPointsEXT(VkCommandBuffer commandBuffer, 1741 uint32_t patchControlPoints) 1742{ 1743 VN_CMD_ENQUEUE(vkCmdSetPatchControlPointsEXT, commandBuffer, 1744 patchControlPoints); 1745} 1746 1747void 1748vn_CmdSetPrimitiveRestartEnable(VkCommandBuffer commandBuffer, 1749 VkBool32 primitiveRestartEnable) 1750{ 1751 VN_CMD_ENQUEUE(vkCmdSetPrimitiveRestartEnable, commandBuffer, 1752 primitiveRestartEnable); 1753} 1754 1755void 1756vn_CmdSetRasterizerDiscardEnable(VkCommandBuffer commandBuffer, 1757 VkBool32 rasterizerDiscardEnable) 1758{ 1759 VN_CMD_ENQUEUE(vkCmdSetRasterizerDiscardEnable, commandBuffer, 1760 rasterizerDiscardEnable); 1761} 1762 1763void 1764vn_CmdBeginConditionalRenderingEXT( 1765 VkCommandBuffer commandBuffer, 1766 const VkConditionalRenderingBeginInfoEXT *pConditionalRenderingBegin) 1767{ 1768 VN_CMD_ENQUEUE(vkCmdBeginConditionalRenderingEXT, commandBuffer, 1769 pConditionalRenderingBegin); 1770} 1771 1772void 1773vn_CmdEndConditionalRenderingEXT(VkCommandBuffer commandBuffer) 1774{ 1775 VN_CMD_ENQUEUE(vkCmdEndConditionalRenderingEXT, commandBuffer); 1776} 1777