| 263 | } |
| 264 | |
| 265 | static bool create_function_entry_descriptor_buffer(vulkan_function_entry& entry, |
| 266 | const device& dev, |
| 267 | const VkShaderStageFlagBits stage, |
| 268 | const std::string& func_name, |
| 269 | const toolchain::function_info& info) { |
| 270 | const auto& vk_dev = (const vulkan_device&)dev; |
| 271 | auto& vk_ctx = *(vulkan_context*)vk_dev.context; |
| 272 | const auto dev_queue = vk_ctx.get_device_default_queue(vk_dev); |
| 273 | assert(dev_queue != nullptr); |
| 274 | |
| 275 | auto layout = build_descriptor_set_layout(dev, func_name, info, stage); |
| 276 | if (!layout) { |
| 277 | return false; |
| 278 | } |
| 279 | entry.desc_set_layout = layout->desc_set_layout; |
| 280 | entry.constant_buffer_info = std::move(layout->constant_buffer_info); |
| 281 | |
| 282 | if (!layout->bindings.empty()) { |
| 283 | // query required buffer size + ensure good alignment |
| 284 | entry.desc_buffer.layout_size_in_bytes = layout->layout_size; |
| 285 | entry.desc_buffer.layout_size_in_bytes = const_math::round_next_multiple(entry.desc_buffer.layout_size_in_bytes, |
| 286 | uint64_t(std::max(256u, vk_dev.descriptor_buffer_offset_alignment))); |
| 287 | |
| 288 | // query offset for each binding/argument |
| 289 | entry.desc_buffer.argument_offsets.reserve(layout->bindings.size()); |
| 290 | for (const auto& binding : layout->bindings) { |
| 291 | VkDeviceSize offset = 0; |
| 292 | vkGetDescriptorSetLayoutBindingOffsetEXT(vk_dev.device, entry.desc_set_layout, binding.binding, &offset); |
| 293 | entry.desc_buffer.argument_offsets.emplace_back(offset); |
| 294 | } |
| 295 | |
| 296 | // allocate descriptor buffers |
| 297 | std::array<vulkan_descriptor_buffer_container::resource_type, vulkan_descriptor_buffer_container::descriptor_count> desc_buffers; |
| 298 | for (uint32_t buf_idx = 0; buf_idx < vulkan_descriptor_buffer_container::descriptor_count; ++buf_idx) { |
| 299 | // alloc with Vulkan flags: need host-visible/host-coherent and descriptor buffer usage flags |
| 300 | desc_buffers[buf_idx].first = vk_ctx.create_buffer(*dev_queue, entry.desc_buffer.layout_size_in_bytes, |
| 301 | // NOTE: read-only on the device side (until writable argument buffers are implemented) |
| 302 | MEMORY_FLAG::READ | |
| 303 | MEMORY_FLAG::HOST_READ_WRITE | |
| 304 | MEMORY_FLAG::VULKAN_HOST_COHERENT | |
| 305 | MEMORY_FLAG::VULKAN_DESCRIPTOR_BUFFER | |
| 306 | MEMORY_FLAG::__EXP_HEAP_ALLOC); |
| 307 | desc_buffers[buf_idx].first->set_debug_label("desc_buf:" + func_name + "#" + std::to_string(buf_idx)); |
| 308 | auto mapped_host_ptr = desc_buffers[buf_idx].first->map(*dev_queue, (MEMORY_MAP_FLAG::WRITE_INVALIDATE | |
| 309 | MEMORY_MAP_FLAG::BLOCK)); |
| 310 | desc_buffers[buf_idx].second = { (uint8_t*)mapped_host_ptr, entry.desc_buffer.layout_size_in_bytes }; |
| 311 | entry.desc_buffer.desc_buffer_ptrs[buf_idx] = { desc_buffers[buf_idx].first.get(), mapped_host_ptr }; |
| 312 | } |
| 313 | entry.desc_buffer.desc_buffer_container = std::make_unique<vulkan_descriptor_buffer_container>(std::move(desc_buffers)); |
| 314 | |
| 315 | if (!allocate_constant_buffers(entry, dev, func_name, *layout)) { |
| 316 | return false; |
| 317 | } |
| 318 | } |
| 319 | // else: no function parameters/bindings |
| 320 | |
| 321 | // handle argument buffers -> need to create descriptor set layouts for these as well |
| 322 | { |
no test coverage detected