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_descriptor_set.h" 12 13#include "venus-protocol/vn_protocol_driver_descriptor_pool.h" 14#include "venus-protocol/vn_protocol_driver_descriptor_set.h" 15#include "venus-protocol/vn_protocol_driver_descriptor_set_layout.h" 16#include "venus-protocol/vn_protocol_driver_descriptor_update_template.h" 17 18#include "vn_device.h" 19 20void 21vn_descriptor_set_layout_destroy(struct vn_device *dev, 22 struct vn_descriptor_set_layout *layout) 23{ 24 VkDevice dev_handle = vn_device_to_handle(dev); 25 VkDescriptorSetLayout layout_handle = 26 vn_descriptor_set_layout_to_handle(layout); 27 const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 28 29 vn_async_vkDestroyDescriptorSetLayout(dev->instance, dev_handle, 30 layout_handle, NULL); 31 32 vn_object_base_fini(&layout->base); 33 vk_free(alloc, layout); 34} 35 36static void 37vn_descriptor_set_destroy(struct vn_device *dev, 38 struct vn_descriptor_set *set, 39 const VkAllocationCallbacks *alloc) 40{ 41 list_del(&set->head); 42 43 vn_descriptor_set_layout_unref(dev, set->layout); 44 45 vn_object_base_fini(&set->base); 46 vk_free(alloc, set); 47} 48 49/* descriptor set layout commands */ 50 51void 52vn_GetDescriptorSetLayoutSupport( 53 VkDevice device, 54 const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 55 VkDescriptorSetLayoutSupport *pSupport) 56{ 57 struct vn_device *dev = vn_device_from_handle(device); 58 59 /* TODO per-device cache */ 60 vn_call_vkGetDescriptorSetLayoutSupport(dev->instance, device, pCreateInfo, 61 pSupport); 62} 63 64static void 65vn_descriptor_set_layout_init( 66 struct vn_device *dev, 67 const VkDescriptorSetLayoutCreateInfo *create_info, 68 uint32_t last_binding, 69 struct vn_descriptor_set_layout *layout) 70{ 71 VkDevice dev_handle = vn_device_to_handle(dev); 72 VkDescriptorSetLayout layout_handle = 73 vn_descriptor_set_layout_to_handle(layout); 74 const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags = 75 vk_find_struct_const(create_info->pNext, 76 DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO); 77 78 /* 14.2.1. Descriptor Set Layout 79 * 80 * If bindingCount is zero or if this structure is not included in 81 * the pNext chain, the VkDescriptorBindingFlags for each descriptor 82 * set layout binding is considered to be zero. 83 */ 84 if (binding_flags && !binding_flags->bindingCount) 85 binding_flags = NULL; 86 87 layout->refcount = VN_REFCOUNT_INIT(1); 88 layout->last_binding = last_binding; 89 90 for (uint32_t i = 0; i < create_info->bindingCount; i++) { 91 const VkDescriptorSetLayoutBinding *binding_info = 92 &create_info->pBindings[i]; 93 struct vn_descriptor_set_layout_binding *binding = 94 &layout->bindings[binding_info->binding]; 95 96 if (binding_info->binding == last_binding) { 97 /* 14.2.1. Descriptor Set Layout 98 * 99 * VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT must only be 100 * used for the last binding in the descriptor set layout (i.e. the 101 * binding with the largest value of binding). 102 * 103 * 41. Features 104 * 105 * descriptorBindingVariableDescriptorCount indicates whether the 106 * implementation supports descriptor sets with a variable-sized last 107 * binding. If this feature is not enabled, 108 * VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT must not be 109 * used. 110 */ 111 layout->has_variable_descriptor_count = 112 binding_flags && 113 (binding_flags->pBindingFlags[i] & 114 VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT); 115 } 116 117 binding->type = binding_info->descriptorType; 118 binding->count = binding_info->descriptorCount; 119 120 switch (binding_info->descriptorType) { 121 case VK_DESCRIPTOR_TYPE_SAMPLER: 122 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 123 binding->has_immutable_samplers = binding_info->pImmutableSamplers; 124 break; 125 default: 126 break; 127 } 128 } 129 130 vn_async_vkCreateDescriptorSetLayout(dev->instance, dev_handle, 131 create_info, NULL, &layout_handle); 132} 133 134VkResult 135vn_CreateDescriptorSetLayout( 136 VkDevice device, 137 const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 138 const VkAllocationCallbacks *pAllocator, 139 VkDescriptorSetLayout *pSetLayout) 140{ 141 struct vn_device *dev = vn_device_from_handle(device); 142 /* ignore pAllocator as the layout is reference-counted */ 143 const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 144 145 uint32_t last_binding = 0; 146 VkDescriptorSetLayoutBinding *local_bindings = NULL; 147 VkDescriptorSetLayoutCreateInfo local_create_info; 148 if (pCreateInfo->bindingCount) { 149 /* the encoder does not ignore 150 * VkDescriptorSetLayoutBinding::pImmutableSamplers when it should 151 */ 152 const size_t binding_size = 153 sizeof(*pCreateInfo->pBindings) * pCreateInfo->bindingCount; 154 local_bindings = vk_alloc(alloc, binding_size, VN_DEFAULT_ALIGN, 155 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 156 if (!local_bindings) 157 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 158 159 memcpy(local_bindings, pCreateInfo->pBindings, binding_size); 160 for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) { 161 VkDescriptorSetLayoutBinding *binding = &local_bindings[i]; 162 163 if (last_binding < binding->binding) 164 last_binding = binding->binding; 165 166 switch (binding->descriptorType) { 167 case VK_DESCRIPTOR_TYPE_SAMPLER: 168 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 169 break; 170 default: 171 binding->pImmutableSamplers = NULL; 172 break; 173 } 174 } 175 176 local_create_info = *pCreateInfo; 177 local_create_info.pBindings = local_bindings; 178 pCreateInfo = &local_create_info; 179 } 180 181 const size_t layout_size = 182 offsetof(struct vn_descriptor_set_layout, bindings[last_binding + 1]); 183 /* allocated with the device scope */ 184 struct vn_descriptor_set_layout *layout = 185 vk_zalloc(alloc, layout_size, VN_DEFAULT_ALIGN, 186 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 187 if (!layout) { 188 vk_free(alloc, local_bindings); 189 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 190 } 191 192 vn_object_base_init(&layout->base, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, 193 &dev->base); 194 195 vn_descriptor_set_layout_init(dev, pCreateInfo, last_binding, layout); 196 197 vk_free(alloc, local_bindings); 198 199 *pSetLayout = vn_descriptor_set_layout_to_handle(layout); 200 201 return VK_SUCCESS; 202} 203 204void 205vn_DestroyDescriptorSetLayout(VkDevice device, 206 VkDescriptorSetLayout descriptorSetLayout, 207 const VkAllocationCallbacks *pAllocator) 208{ 209 struct vn_device *dev = vn_device_from_handle(device); 210 struct vn_descriptor_set_layout *layout = 211 vn_descriptor_set_layout_from_handle(descriptorSetLayout); 212 213 if (!layout) 214 return; 215 216 vn_descriptor_set_layout_unref(dev, layout); 217} 218 219/* descriptor pool commands */ 220 221VkResult 222vn_CreateDescriptorPool(VkDevice device, 223 const VkDescriptorPoolCreateInfo *pCreateInfo, 224 const VkAllocationCallbacks *pAllocator, 225 VkDescriptorPool *pDescriptorPool) 226{ 227 struct vn_device *dev = vn_device_from_handle(device); 228 const VkAllocationCallbacks *alloc = 229 pAllocator ? pAllocator : &dev->base.base.alloc; 230 231 struct vn_descriptor_pool *pool = 232 vk_zalloc(alloc, sizeof(*pool), VN_DEFAULT_ALIGN, 233 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 234 if (!pool) 235 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 236 237 vn_object_base_init(&pool->base, VK_OBJECT_TYPE_DESCRIPTOR_POOL, 238 &dev->base); 239 240 pool->allocator = *alloc; 241 242 /* Without VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, the set 243 * allocation must not fail due to a fragmented pool per spec. In this 244 * case, set allocation can be asynchronous with pool resource tracking. 245 */ 246 pool->async_set_allocation = !( 247 pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT); 248 249 pool->max.set_count = pCreateInfo->maxSets; 250 251 for (uint32_t i = 0; i < pCreateInfo->poolSizeCount; i++) { 252 const VkDescriptorPoolSize *pool_size = &pCreateInfo->pPoolSizes[i]; 253 254 assert(pool_size->type < VN_NUM_DESCRIPTOR_TYPES); 255 256 pool->max.descriptor_counts[pool_size->type] += 257 pool_size->descriptorCount; 258 } 259 260 list_inithead(&pool->descriptor_sets); 261 262 VkDescriptorPool pool_handle = vn_descriptor_pool_to_handle(pool); 263 vn_async_vkCreateDescriptorPool(dev->instance, device, pCreateInfo, NULL, 264 &pool_handle); 265 266 *pDescriptorPool = pool_handle; 267 268 return VK_SUCCESS; 269} 270 271void 272vn_DestroyDescriptorPool(VkDevice device, 273 VkDescriptorPool descriptorPool, 274 const VkAllocationCallbacks *pAllocator) 275{ 276 struct vn_device *dev = vn_device_from_handle(device); 277 struct vn_descriptor_pool *pool = 278 vn_descriptor_pool_from_handle(descriptorPool); 279 const VkAllocationCallbacks *alloc; 280 281 if (!pool) 282 return; 283 284 alloc = pAllocator ? pAllocator : &pool->allocator; 285 286 /* We must emit vkDestroyDescriptorPool before freeing the sets in 287 * pool->descriptor_sets. Otherwise, another thread might reuse their 288 * object ids while they still refer to the sets in the renderer. 289 */ 290 vn_async_vkDestroyDescriptorPool(dev->instance, device, descriptorPool, 291 NULL); 292 293 list_for_each_entry_safe(struct vn_descriptor_set, set, 294 &pool->descriptor_sets, head) 295 vn_descriptor_set_destroy(dev, set, alloc); 296 297 vn_object_base_fini(&pool->base); 298 vk_free(alloc, pool); 299} 300 301static bool 302vn_descriptor_pool_alloc_descriptors( 303 struct vn_descriptor_pool *pool, 304 const struct vn_descriptor_set_layout *layout, 305 uint32_t last_binding_descriptor_count) 306{ 307 struct vn_descriptor_pool_state recovery; 308 309 if (!pool->async_set_allocation) 310 return true; 311 312 if (pool->used.set_count == pool->max.set_count) 313 return false; 314 315 /* backup current pool state to recovery */ 316 recovery = pool->used; 317 318 ++pool->used.set_count; 319 320 for (uint32_t i = 0; i <= layout->last_binding; i++) { 321 const VkDescriptorType type = layout->bindings[i].type; 322 const uint32_t count = i == layout->last_binding 323 ? last_binding_descriptor_count 324 : layout->bindings[i].count; 325 326 pool->used.descriptor_counts[type] += count; 327 328 if (pool->used.descriptor_counts[type] > 329 pool->max.descriptor_counts[type]) { 330 /* restore pool state before this allocation */ 331 pool->used = recovery; 332 return false; 333 } 334 } 335 336 return true; 337} 338 339static void 340vn_descriptor_pool_free_descriptors( 341 struct vn_descriptor_pool *pool, 342 const struct vn_descriptor_set_layout *layout, 343 uint32_t last_binding_descriptor_count) 344{ 345 if (!pool->async_set_allocation) 346 return; 347 348 for (uint32_t i = 0; i <= layout->last_binding; i++) { 349 const uint32_t count = i == layout->last_binding 350 ? last_binding_descriptor_count 351 : layout->bindings[i].count; 352 353 pool->used.descriptor_counts[layout->bindings[i].type] -= count; 354 } 355 356 --pool->used.set_count; 357} 358 359static void 360vn_descriptor_pool_reset_descriptors(struct vn_descriptor_pool *pool) 361{ 362 if (!pool->async_set_allocation) 363 return; 364 365 memset(&pool->used, 0, sizeof(pool->used)); 366} 367 368VkResult 369vn_ResetDescriptorPool(VkDevice device, 370 VkDescriptorPool descriptorPool, 371 VkDescriptorPoolResetFlags flags) 372{ 373 struct vn_device *dev = vn_device_from_handle(device); 374 struct vn_descriptor_pool *pool = 375 vn_descriptor_pool_from_handle(descriptorPool); 376 const VkAllocationCallbacks *alloc = &pool->allocator; 377 378 vn_async_vkResetDescriptorPool(dev->instance, device, descriptorPool, 379 flags); 380 381 list_for_each_entry_safe(struct vn_descriptor_set, set, 382 &pool->descriptor_sets, head) 383 vn_descriptor_set_destroy(dev, set, alloc); 384 385 vn_descriptor_pool_reset_descriptors(pool); 386 387 return VK_SUCCESS; 388} 389 390/* descriptor set commands */ 391 392VkResult 393vn_AllocateDescriptorSets(VkDevice device, 394 const VkDescriptorSetAllocateInfo *pAllocateInfo, 395 VkDescriptorSet *pDescriptorSets) 396{ 397 struct vn_device *dev = vn_device_from_handle(device); 398 struct vn_descriptor_pool *pool = 399 vn_descriptor_pool_from_handle(pAllocateInfo->descriptorPool); 400 const VkAllocationCallbacks *alloc = &pool->allocator; 401 const VkDescriptorSetVariableDescriptorCountAllocateInfo *variable_info = 402 NULL; 403 VkResult result; 404 405 /* 14.2.3. Allocation of Descriptor Sets 406 * 407 * If descriptorSetCount is zero or this structure is not included in 408 * the pNext chain, then the variable lengths are considered to be zero. 409 */ 410 variable_info = vk_find_struct_const( 411 pAllocateInfo->pNext, 412 DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO); 413 414 if (variable_info && !variable_info->descriptorSetCount) 415 variable_info = NULL; 416 417 for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 418 struct vn_descriptor_set_layout *layout = 419 vn_descriptor_set_layout_from_handle(pAllocateInfo->pSetLayouts[i]); 420 uint32_t last_binding_descriptor_count = 0; 421 struct vn_descriptor_set *set = NULL; 422 423 /* 14.2.3. Allocation of Descriptor Sets 424 * 425 * If VkDescriptorSetAllocateInfo::pSetLayouts[i] does not include a 426 * variable count descriptor binding, then pDescriptorCounts[i] is 427 * ignored. 428 */ 429 if (!layout->has_variable_descriptor_count) { 430 last_binding_descriptor_count = 431 layout->bindings[layout->last_binding].count; 432 } else if (variable_info) { 433 last_binding_descriptor_count = variable_info->pDescriptorCounts[i]; 434 } 435 436 if (!vn_descriptor_pool_alloc_descriptors( 437 pool, layout, last_binding_descriptor_count)) { 438 pDescriptorSets[i] = VK_NULL_HANDLE; 439 result = VK_ERROR_OUT_OF_POOL_MEMORY; 440 goto fail; 441 } 442 443 set = vk_zalloc(alloc, sizeof(*set), VN_DEFAULT_ALIGN, 444 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 445 if (!set) { 446 vn_descriptor_pool_free_descriptors(pool, layout, 447 last_binding_descriptor_count); 448 pDescriptorSets[i] = VK_NULL_HANDLE; 449 result = VK_ERROR_OUT_OF_HOST_MEMORY; 450 goto fail; 451 } 452 453 vn_object_base_init(&set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET, 454 &dev->base); 455 456 /* We might reorder vkCmdBindDescriptorSets after 457 * vkDestroyDescriptorSetLayout due to batching. The spec says 458 * 459 * VkDescriptorSetLayout objects may be accessed by commands that 460 * operate on descriptor sets allocated using that layout, and those 461 * descriptor sets must not be updated with vkUpdateDescriptorSets 462 * after the descriptor set layout has been destroyed. Otherwise, a 463 * VkDescriptorSetLayout object passed as a parameter to create 464 * another object is not further accessed by that object after the 465 * duration of the command it is passed into. 466 * 467 * It is ambiguous but the reordering is likely invalid. Let's keep the 468 * layout alive with the set to defer vkDestroyDescriptorSetLayout. 469 */ 470 set->layout = vn_descriptor_set_layout_ref(dev, layout); 471 set->last_binding_descriptor_count = last_binding_descriptor_count; 472 list_addtail(&set->head, &pool->descriptor_sets); 473 474 VkDescriptorSet set_handle = vn_descriptor_set_to_handle(set); 475 pDescriptorSets[i] = set_handle; 476 } 477 478 if (pool->async_set_allocation) { 479 vn_async_vkAllocateDescriptorSets(dev->instance, device, pAllocateInfo, 480 pDescriptorSets); 481 } else { 482 result = vn_call_vkAllocateDescriptorSets( 483 dev->instance, device, pAllocateInfo, pDescriptorSets); 484 if (result != VK_SUCCESS) 485 goto fail; 486 } 487 488 return VK_SUCCESS; 489 490fail: 491 for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 492 struct vn_descriptor_set *set = 493 vn_descriptor_set_from_handle(pDescriptorSets[i]); 494 if (!set) 495 break; 496 497 vn_descriptor_pool_free_descriptors(pool, set->layout, 498 set->last_binding_descriptor_count); 499 500 vn_descriptor_set_destroy(dev, set, alloc); 501 } 502 503 memset(pDescriptorSets, 0, 504 sizeof(*pDescriptorSets) * pAllocateInfo->descriptorSetCount); 505 506 return vn_error(dev->instance, result); 507} 508 509VkResult 510vn_FreeDescriptorSets(VkDevice device, 511 VkDescriptorPool descriptorPool, 512 uint32_t descriptorSetCount, 513 const VkDescriptorSet *pDescriptorSets) 514{ 515 struct vn_device *dev = vn_device_from_handle(device); 516 struct vn_descriptor_pool *pool = 517 vn_descriptor_pool_from_handle(descriptorPool); 518 const VkAllocationCallbacks *alloc = &pool->allocator; 519 520 vn_async_vkFreeDescriptorSets(dev->instance, device, descriptorPool, 521 descriptorSetCount, pDescriptorSets); 522 523 for (uint32_t i = 0; i < descriptorSetCount; i++) { 524 struct vn_descriptor_set *set = 525 vn_descriptor_set_from_handle(pDescriptorSets[i]); 526 527 if (!set) 528 continue; 529 530 vn_descriptor_set_destroy(dev, set, alloc); 531 } 532 533 return VK_SUCCESS; 534} 535 536static struct vn_update_descriptor_sets * 537vn_update_descriptor_sets_alloc(uint32_t write_count, 538 uint32_t image_count, 539 uint32_t buffer_count, 540 uint32_t view_count, 541 const VkAllocationCallbacks *alloc, 542 VkSystemAllocationScope scope) 543{ 544 const size_t writes_offset = sizeof(struct vn_update_descriptor_sets); 545 const size_t images_offset = 546 writes_offset + sizeof(VkWriteDescriptorSet) * write_count; 547 const size_t buffers_offset = 548 images_offset + sizeof(VkDescriptorImageInfo) * image_count; 549 const size_t views_offset = 550 buffers_offset + sizeof(VkDescriptorBufferInfo) * buffer_count; 551 const size_t alloc_size = views_offset + sizeof(VkBufferView) * view_count; 552 553 void *storage = vk_alloc(alloc, alloc_size, VN_DEFAULT_ALIGN, scope); 554 if (!storage) 555 return NULL; 556 557 struct vn_update_descriptor_sets *update = storage; 558 update->write_count = write_count; 559 update->writes = storage + writes_offset; 560 update->images = storage + images_offset; 561 update->buffers = storage + buffers_offset; 562 update->views = storage + views_offset; 563 564 return update; 565} 566 567static struct vn_update_descriptor_sets * 568vn_update_descriptor_sets_parse_writes(uint32_t write_count, 569 const VkWriteDescriptorSet *writes, 570 const VkAllocationCallbacks *alloc) 571{ 572 uint32_t img_count = 0; 573 for (uint32_t i = 0; i < write_count; i++) { 574 const VkWriteDescriptorSet *write = &writes[i]; 575 switch (write->descriptorType) { 576 case VK_DESCRIPTOR_TYPE_SAMPLER: 577 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 578 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 579 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 580 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 581 img_count += write->descriptorCount; 582 break; 583 default: 584 break; 585 } 586 } 587 588 struct vn_update_descriptor_sets *update = 589 vn_update_descriptor_sets_alloc(write_count, img_count, 0, 0, alloc, 590 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 591 if (!update) 592 return NULL; 593 594 /* the encoder does not ignore 595 * VkWriteDescriptorSet::{pImageInfo,pBufferInfo,pTexelBufferView} when it 596 * should 597 * 598 * TODO make the encoder smarter 599 */ 600 memcpy(update->writes, writes, sizeof(*writes) * write_count); 601 img_count = 0; 602 for (uint32_t i = 0; i < write_count; i++) { 603 const struct vn_descriptor_set *set = 604 vn_descriptor_set_from_handle(writes[i].dstSet); 605 const struct vn_descriptor_set_layout_binding *binding = 606 &set->layout->bindings[writes[i].dstBinding]; 607 VkWriteDescriptorSet *write = &update->writes[i]; 608 VkDescriptorImageInfo *imgs = &update->images[img_count]; 609 610 switch (write->descriptorType) { 611 case VK_DESCRIPTOR_TYPE_SAMPLER: 612 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 613 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 614 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 615 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 616 memcpy(imgs, write->pImageInfo, 617 sizeof(*imgs) * write->descriptorCount); 618 img_count += write->descriptorCount; 619 620 for (uint32_t j = 0; j < write->descriptorCount; j++) { 621 switch (write->descriptorType) { 622 case VK_DESCRIPTOR_TYPE_SAMPLER: 623 imgs[j].imageView = VK_NULL_HANDLE; 624 break; 625 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 626 if (binding->has_immutable_samplers) 627 imgs[j].sampler = VK_NULL_HANDLE; 628 break; 629 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 630 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 631 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 632 imgs[j].sampler = VK_NULL_HANDLE; 633 break; 634 default: 635 break; 636 } 637 } 638 639 write->pImageInfo = imgs; 640 write->pBufferInfo = NULL; 641 write->pTexelBufferView = NULL; 642 break; 643 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 644 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 645 write->pImageInfo = NULL; 646 write->pBufferInfo = NULL; 647 break; 648 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 649 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 650 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 651 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 652 write->pImageInfo = NULL; 653 write->pTexelBufferView = NULL; 654 break; 655 default: 656 write->pImageInfo = NULL; 657 write->pBufferInfo = NULL; 658 write->pTexelBufferView = NULL; 659 break; 660 } 661 } 662 663 return update; 664} 665 666void 667vn_UpdateDescriptorSets(VkDevice device, 668 uint32_t descriptorWriteCount, 669 const VkWriteDescriptorSet *pDescriptorWrites, 670 uint32_t descriptorCopyCount, 671 const VkCopyDescriptorSet *pDescriptorCopies) 672{ 673 struct vn_device *dev = vn_device_from_handle(device); 674 const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 675 676 struct vn_update_descriptor_sets *update = 677 vn_update_descriptor_sets_parse_writes(descriptorWriteCount, 678 pDescriptorWrites, alloc); 679 if (!update) { 680 /* TODO update one-by-one? */ 681 vn_log(dev->instance, "TODO descriptor set update ignored due to OOM"); 682 return; 683 } 684 685 vn_async_vkUpdateDescriptorSets(dev->instance, device, update->write_count, 686 update->writes, descriptorCopyCount, 687 pDescriptorCopies); 688 689 vk_free(alloc, update); 690} 691 692/* descriptor update template commands */ 693 694static struct vn_update_descriptor_sets * 695vn_update_descriptor_sets_parse_template( 696 const VkDescriptorUpdateTemplateCreateInfo *create_info, 697 const VkAllocationCallbacks *alloc, 698 struct vn_descriptor_update_template_entry *entries) 699{ 700 uint32_t img_count = 0; 701 uint32_t buf_count = 0; 702 uint32_t view_count = 0; 703 for (uint32_t i = 0; i < create_info->descriptorUpdateEntryCount; i++) { 704 const VkDescriptorUpdateTemplateEntry *entry = 705 &create_info->pDescriptorUpdateEntries[i]; 706 707 switch (entry->descriptorType) { 708 case VK_DESCRIPTOR_TYPE_SAMPLER: 709 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 710 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 711 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 712 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 713 img_count += entry->descriptorCount; 714 break; 715 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 716 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 717 view_count += entry->descriptorCount; 718 break; 719 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 720 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 721 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 722 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 723 buf_count += entry->descriptorCount; 724 break; 725 default: 726 unreachable("unhandled descriptor type"); 727 break; 728 } 729 } 730 731 struct vn_update_descriptor_sets *update = vn_update_descriptor_sets_alloc( 732 create_info->descriptorUpdateEntryCount, img_count, buf_count, 733 view_count, alloc, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 734 if (!update) 735 return NULL; 736 737 img_count = 0; 738 buf_count = 0; 739 view_count = 0; 740 for (uint32_t i = 0; i < create_info->descriptorUpdateEntryCount; i++) { 741 const VkDescriptorUpdateTemplateEntry *entry = 742 &create_info->pDescriptorUpdateEntries[i]; 743 VkWriteDescriptorSet *write = &update->writes[i]; 744 745 write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; 746 write->pNext = NULL; 747 write->dstBinding = entry->dstBinding; 748 write->dstArrayElement = entry->dstArrayElement; 749 write->descriptorCount = entry->descriptorCount; 750 write->descriptorType = entry->descriptorType; 751 752 entries[i].offset = entry->offset; 753 entries[i].stride = entry->stride; 754 755 switch (entry->descriptorType) { 756 case VK_DESCRIPTOR_TYPE_SAMPLER: 757 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 758 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 759 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 760 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 761 write->pImageInfo = &update->images[img_count]; 762 write->pBufferInfo = NULL; 763 write->pTexelBufferView = NULL; 764 img_count += entry->descriptorCount; 765 break; 766 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 767 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 768 write->pImageInfo = NULL; 769 write->pBufferInfo = NULL; 770 write->pTexelBufferView = &update->views[view_count]; 771 view_count += entry->descriptorCount; 772 break; 773 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 774 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 775 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 776 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 777 write->pImageInfo = NULL; 778 write->pBufferInfo = &update->buffers[buf_count]; 779 write->pTexelBufferView = NULL; 780 buf_count += entry->descriptorCount; 781 break; 782 default: 783 break; 784 } 785 } 786 787 return update; 788} 789 790VkResult 791vn_CreateDescriptorUpdateTemplate( 792 VkDevice device, 793 const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo, 794 const VkAllocationCallbacks *pAllocator, 795 VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate) 796{ 797 struct vn_device *dev = vn_device_from_handle(device); 798 const VkAllocationCallbacks *alloc = 799 pAllocator ? pAllocator : &dev->base.base.alloc; 800 801 const size_t templ_size = 802 offsetof(struct vn_descriptor_update_template, 803 entries[pCreateInfo->descriptorUpdateEntryCount + 1]); 804 struct vn_descriptor_update_template *templ = vk_zalloc( 805 alloc, templ_size, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 806 if (!templ) 807 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 808 809 vn_object_base_init(&templ->base, 810 VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, &dev->base); 811 812 templ->update = vn_update_descriptor_sets_parse_template( 813 pCreateInfo, alloc, templ->entries); 814 if (!templ->update) { 815 vk_free(alloc, templ); 816 return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 817 } 818 819 mtx_init(&templ->mutex, mtx_plain); 820 821 /* no host object */ 822 VkDescriptorUpdateTemplate templ_handle = 823 vn_descriptor_update_template_to_handle(templ); 824 *pDescriptorUpdateTemplate = templ_handle; 825 826 return VK_SUCCESS; 827} 828 829void 830vn_DestroyDescriptorUpdateTemplate( 831 VkDevice device, 832 VkDescriptorUpdateTemplate descriptorUpdateTemplate, 833 const VkAllocationCallbacks *pAllocator) 834{ 835 struct vn_device *dev = vn_device_from_handle(device); 836 struct vn_descriptor_update_template *templ = 837 vn_descriptor_update_template_from_handle(descriptorUpdateTemplate); 838 const VkAllocationCallbacks *alloc = 839 pAllocator ? pAllocator : &dev->base.base.alloc; 840 841 if (!templ) 842 return; 843 844 /* no host object */ 845 vk_free(alloc, templ->update); 846 mtx_destroy(&templ->mutex); 847 848 vn_object_base_fini(&templ->base); 849 vk_free(alloc, templ); 850} 851 852void 853vn_UpdateDescriptorSetWithTemplate( 854 VkDevice device, 855 VkDescriptorSet descriptorSet, 856 VkDescriptorUpdateTemplate descriptorUpdateTemplate, 857 const void *pData) 858{ 859 struct vn_device *dev = vn_device_from_handle(device); 860 struct vn_descriptor_set *set = 861 vn_descriptor_set_from_handle(descriptorSet); 862 struct vn_descriptor_update_template *templ = 863 vn_descriptor_update_template_from_handle(descriptorUpdateTemplate); 864 struct vn_update_descriptor_sets *update = templ->update; 865 866 /* duplicate update instead to avoid locking? */ 867 mtx_lock(&templ->mutex); 868 869 for (uint32_t i = 0; i < update->write_count; i++) { 870 const struct vn_descriptor_update_template_entry *entry = 871 &templ->entries[i]; 872 const struct vn_descriptor_set_layout_binding *binding = 873 &set->layout->bindings[update->writes[i].dstBinding]; 874 VkWriteDescriptorSet *write = &update->writes[i]; 875 876 write->dstSet = vn_descriptor_set_to_handle(set); 877 878 switch (write->descriptorType) { 879 case VK_DESCRIPTOR_TYPE_SAMPLER: 880 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 881 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 882 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 883 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 884 for (uint32_t j = 0; j < write->descriptorCount; j++) { 885 const bool need_sampler = 886 (write->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || 887 write->descriptorType == 888 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) && 889 !binding->has_immutable_samplers; 890 const bool need_view = 891 write->descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER; 892 const VkDescriptorImageInfo *src = 893 pData + entry->offset + entry->stride * j; 894 VkDescriptorImageInfo *dst = 895 (VkDescriptorImageInfo *)&write->pImageInfo[j]; 896 897 dst->sampler = need_sampler ? src->sampler : VK_NULL_HANDLE; 898 dst->imageView = need_view ? src->imageView : VK_NULL_HANDLE; 899 dst->imageLayout = src->imageLayout; 900 } 901 break; 902 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 903 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 904 for (uint32_t j = 0; j < write->descriptorCount; j++) { 905 const VkBufferView *src = 906 pData + entry->offset + entry->stride * j; 907 VkBufferView *dst = (VkBufferView *)&write->pTexelBufferView[j]; 908 *dst = *src; 909 } 910 break; 911 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 912 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 913 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 914 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 915 for (uint32_t j = 0; j < write->descriptorCount; j++) { 916 const VkDescriptorBufferInfo *src = 917 pData + entry->offset + entry->stride * j; 918 VkDescriptorBufferInfo *dst = 919 (VkDescriptorBufferInfo *)&write->pBufferInfo[j]; 920 *dst = *src; 921 } 922 break; 923 default: 924 unreachable("unhandled descriptor type"); 925 break; 926 } 927 } 928 929 vn_async_vkUpdateDescriptorSets(dev->instance, device, update->write_count, 930 update->writes, 0, NULL); 931 932 mtx_unlock(&templ->mutex); 933} 934