| 42 | } |
| 43 | |
| 44 | void indirect_command_description::compute_buffer_counts_from_functions(const compute_device& dev, const vector<const compute_kernel*>& functions) { |
| 45 | #if !defined(FLOOR_NO_VULKAN) |
| 46 | // for Vulkan, we can directly derive a "buffer count" from the descriptor buffer/layout size and the SSBO descriptor size |
| 47 | const auto is_vulkan = (dev.context->get_compute_type() == COMPUTE_TYPE::VULKAN); |
| 48 | if (is_vulkan) { |
| 49 | const auto ssbo_size = ((const vulkan_device&)dev).desc_buffer_sizes.ssbo; |
| 50 | for (const auto& func : functions) { |
| 51 | const auto entry = func->get_kernel_entry(dev); |
| 52 | if (!entry || !entry->info) { |
| 53 | continue; |
| 54 | } |
| 55 | const auto vk_entry = (const vulkan_kernel::vulkan_kernel_entry*)entry; |
| 56 | const auto buf_count = uint32_t((vk_entry->desc_buffer.layout_size_in_bytes + ssbo_size - 1u) / ssbo_size); |
| 57 | switch (entry->info->type) { |
| 58 | case llvm_toolchain::FUNCTION_TYPE::KERNEL: |
| 59 | max_kernel_buffer_count = max(max_kernel_buffer_count, buf_count); |
| 60 | break; |
| 61 | case llvm_toolchain::FUNCTION_TYPE::VERTEX: |
| 62 | case llvm_toolchain::FUNCTION_TYPE::TESSELLATION_EVALUATION: |
| 63 | max_vertex_buffer_count = max(max_vertex_buffer_count, buf_count); |
| 64 | break; |
| 65 | case llvm_toolchain::FUNCTION_TYPE::FRAGMENT: |
| 66 | max_fragment_buffer_count = max(max_fragment_buffer_count, buf_count); |
| 67 | break; |
| 68 | case llvm_toolchain::FUNCTION_TYPE::NONE: |
| 69 | case llvm_toolchain::FUNCTION_TYPE::TESSELLATION_CONTROL: |
| 70 | case llvm_toolchain::FUNCTION_TYPE::ARGUMENT_BUFFER_STRUCT: |
| 71 | throw runtime_error("unhandled function type"); |
| 72 | } |
| 73 | } |
| 74 | // NOTE: still continue and perform the "normal" buffer count computation (as a validity check) |
| 75 | } |
| 76 | #else |
| 77 | constexpr const auto is_vulkan = false; |
| 78 | #endif |
| 79 | |
| 80 | for (const auto& func : functions) { |
| 81 | const auto entry = func->get_kernel_entry(dev); |
| 82 | if (!entry || !entry->info) { |
| 83 | continue; |
| 84 | } |
| 85 | uint32_t buf_count = 0; |
| 86 | for (const auto& arg : entry->info->args) { |
| 87 | #if defined(FLOOR_DEBUG) |
| 88 | if (arg.image_type != llvm_toolchain::ARG_IMAGE_TYPE::NONE) { |
| 89 | log_error("must not have image parameters (in function \"$\") intended for indirect compute/render", entry->info->name); |
| 90 | continue; |
| 91 | } |
| 92 | #endif |
| 93 | switch (arg.special_type) { |
| 94 | case llvm_toolchain::SPECIAL_TYPE::NONE: |
| 95 | case llvm_toolchain::SPECIAL_TYPE::SSBO: |
| 96 | ++buf_count; |
| 97 | break; |
| 98 | case llvm_toolchain::SPECIAL_TYPE::ARGUMENT_BUFFER: |
| 99 | // for Vulkan, argument buffers are separately stored descriptor buffers (-> don't need to account for them here) |
| 100 | if (!is_vulkan) { |
| 101 | ++buf_count; |
nothing calls this directly
no test coverage detected