| 244 | } |
| 245 | |
| 246 | static bool create_kernel_entry_descriptor_buffer(vulkan_kernel::vulkan_kernel_entry& entry, |
| 247 | const compute_device& dev, |
| 248 | const VkShaderStageFlagBits stage, |
| 249 | const string& func_name, |
| 250 | const llvm_toolchain::function_info& info) { |
| 251 | const auto& vk_dev = (const vulkan_device&)dev; |
| 252 | auto& vk_ctx = *(vulkan_compute*)vk_dev.context; |
| 253 | const auto dev_queue = vk_ctx.get_device_default_queue(vk_dev); |
| 254 | assert(dev_queue != nullptr); |
| 255 | |
| 256 | if (!has_flag<llvm_toolchain::FUNCTION_FLAGS::USES_VULKAN_DESCRIPTOR_BUFFER>(info.flags)) { |
| 257 | log_error("can't use a function that has not been built with descriptor buffer support with descriptor buffers: in function $", func_name); |
| 258 | return false; |
| 259 | } |
| 260 | |
| 261 | auto layout = vulkan_program::build_descriptor_set_layout(dev, func_name, info, stage); |
| 262 | if (!layout) { |
| 263 | return false; |
| 264 | } |
| 265 | entry.desc_set_layout = layout->desc_set_layout; |
| 266 | entry.constant_buffer_info = std::move(layout->constant_buffer_info); |
| 267 | |
| 268 | if (!layout->bindings.empty()) { |
| 269 | // query required buffer size + ensure good alignment |
| 270 | entry.desc_buffer.layout_size_in_bytes = 0; |
| 271 | vk_ctx.vulkan_get_descriptor_set_layout_size(vk_dev.device, entry.desc_set_layout, &entry.desc_buffer.layout_size_in_bytes); |
| 272 | entry.desc_buffer.layout_size_in_bytes = const_math::round_next_multiple(entry.desc_buffer.layout_size_in_bytes, |
| 273 | uint64_t(max(256u, vk_dev.descriptor_buffer_offset_alignment))); |
| 274 | |
| 275 | // query offset for each binding/argument |
| 276 | entry.desc_buffer.argument_offsets.reserve(layout->bindings.size()); |
| 277 | for (const auto& binding : layout->bindings) { |
| 278 | VkDeviceSize offset = 0; |
| 279 | vk_ctx.vulkan_get_descriptor_set_layout_binding_offset(vk_dev.device, entry.desc_set_layout, binding.binding, &offset); |
| 280 | entry.desc_buffer.argument_offsets.emplace_back(offset); |
| 281 | } |
| 282 | |
| 283 | // allocate descriptor buffers |
| 284 | array<vulkan_descriptor_buffer_container::resource_type, vulkan_descriptor_buffer_container::descriptor_count> desc_buffers; |
| 285 | for (uint32_t buf_idx = 0; buf_idx < vulkan_descriptor_buffer_container::descriptor_count; ++buf_idx) { |
| 286 | // alloc with Vulkan flags: need host-visible/host-coherent and descriptor buffer usage flags |
| 287 | desc_buffers[buf_idx].first = vk_ctx.create_buffer(*dev_queue, entry.desc_buffer.layout_size_in_bytes, |
| 288 | // NOTE: read-only on the device side (until writable argument buffers are implemented) |
| 289 | COMPUTE_MEMORY_FLAG::READ | |
| 290 | COMPUTE_MEMORY_FLAG::HOST_READ_WRITE | |
| 291 | COMPUTE_MEMORY_FLAG::VULKAN_HOST_COHERENT | |
| 292 | COMPUTE_MEMORY_FLAG::VULKAN_DESCRIPTOR_BUFFER); |
| 293 | desc_buffers[buf_idx].first->set_debug_label("desc_buf:" + func_name + "#" + to_string(buf_idx)); |
| 294 | auto mapped_host_ptr = desc_buffers[buf_idx].first->map(*dev_queue, (COMPUTE_MEMORY_MAP_FLAG::WRITE_INVALIDATE | |
| 295 | COMPUTE_MEMORY_MAP_FLAG::BLOCK)); |
| 296 | desc_buffers[buf_idx].second = { (uint8_t*)mapped_host_ptr, entry.desc_buffer.layout_size_in_bytes }; |
| 297 | } |
| 298 | entry.desc_buffer.desc_buffer_container = make_unique<vulkan_descriptor_buffer_container>(std::move(desc_buffers)); |
| 299 | |
| 300 | if (!allocate_constant_buffers(entry, dev, func_name, *layout)) { |
| 301 | return false; |
| 302 | } |
| 303 | } |
no test coverage detected