| 527 | } |
| 528 | |
| 529 | unique_ptr<argument_buffer> vulkan_kernel::create_argument_buffer_internal(const compute_queue& cqueue, |
| 530 | const kernel_entry& kern_entry, |
| 531 | const llvm_toolchain::arg_info& arg floor_unused, |
| 532 | const uint32_t& user_arg_index, |
| 533 | const uint32_t& ll_arg_index, |
| 534 | const COMPUTE_MEMORY_FLAG& add_mem_flags) const { |
| 535 | const auto& vk_dev = (const vulkan_device&)cqueue.get_device(); |
| 536 | const auto& vk_ctx = (const vulkan_compute&)*vk_dev.context; |
| 537 | const auto& vulkan_entry = (const vulkan_kernel_entry&)kern_entry; |
| 538 | |
| 539 | if (!has_flag<llvm_toolchain::FUNCTION_FLAGS::USES_VULKAN_DESCRIPTOR_BUFFER>(vulkan_entry.info->flags)) { |
| 540 | log_error("can't use a function that has not been built with descriptor buffer support with descriptor/argument buffers: in function $", |
| 541 | vulkan_entry.info->name); |
| 542 | return {}; |
| 543 | } |
| 544 | |
| 545 | // check if info exists |
| 546 | const auto& arg_info = vulkan_entry.info->args[ll_arg_index].argument_buffer_info; |
| 547 | if (!arg_info) { |
| 548 | log_error("no argument buffer info for arg at index #$", user_arg_index); |
| 549 | return {}; |
| 550 | } |
| 551 | |
| 552 | const auto arg_buf_name = vulkan_entry.info->name + ".arg_buffer@" + to_string(user_arg_index); |
| 553 | |
| 554 | // argument buffers are implemented as individual descriptor sets inside the parent function/program, stored in descriptor buffers |
| 555 | // -> grab the descriptor set layout from the parent function that has already created this + allocate a descriptor buffer |
| 556 | if (vulkan_entry.argument_buffers.empty()) { |
| 557 | log_error("no argument buffer info in function entry (in $)", vulkan_entry.info->name); |
| 558 | return {}; |
| 559 | } |
| 560 | |
| 561 | // find the argument buffer info index |
| 562 | uint32_t arg_buf_idx = 0; |
| 563 | for (uint32_t i = 0, count = uint32_t(vulkan_entry.info->args.size()); i < min(ll_arg_index, count); ++i) { |
| 564 | if (i == ll_arg_index) { |
| 565 | break; |
| 566 | } |
| 567 | if (vulkan_entry.info->args[i].special_type == SPECIAL_TYPE::ARGUMENT_BUFFER) { |
| 568 | ++arg_buf_idx; |
| 569 | } |
| 570 | } |
| 571 | if (arg_buf_idx >= vulkan_entry.argument_buffers.size()) { |
| 572 | log_error("argument buffer info index is out-of-bounds for function entry (arg #$ in $)", |
| 573 | user_arg_index, vulkan_entry.info->name); |
| 574 | return {}; |
| 575 | } |
| 576 | const auto& arg_buf_info = vulkan_entry.argument_buffers[arg_buf_idx]; |
| 577 | |
| 578 | // the argument buffer size is device/driver dependent (can't be statically known) |
| 579 | // -> query required buffer size + ensure good alignment |
| 580 | VkDeviceSize arg_buffer_size = 0; |
| 581 | vk_ctx.vulkan_get_descriptor_set_layout_size(vk_dev.device, arg_buf_info.layout.desc_set_layout, &arg_buffer_size); |
| 582 | arg_buffer_size = const_math::round_next_multiple(arg_buffer_size, uint64_t(256)); |
| 583 | |
| 584 | // query offset for each binding/argument |
| 585 | vector<VkDeviceSize> argument_offsets; |
| 586 | argument_offsets.reserve(arg_buf_info.layout.bindings.size()); |
nothing calls this directly
no test coverage detected