| 328 | } |
| 329 | |
| 330 | vulkan_program::vulkan_program(program_map_type&& programs_) : programs(std::move(programs_)) { |
| 331 | if (programs.empty()) return; |
| 332 | retrieve_unique_kernel_names(programs); |
| 333 | |
| 334 | // create all kernels of all device programs |
| 335 | // note that this essentially reshuffles the program "device -> kernels" data to "kernels -> devices" |
| 336 | kernels.reserve(kernel_names.size()); |
| 337 | for (const auto& func_name : kernel_names) { |
| 338 | vulkan_kernel::kernel_map_type kernel_map; |
| 339 | kernel_map.reserve(kernel_names.size()); |
| 340 | |
| 341 | for (const auto& prog : programs) { |
| 342 | if (!prog.second.valid) continue; |
| 343 | |
| 344 | for (const auto& info : prog.second.functions) { |
| 345 | if (info.name == func_name) { |
| 346 | vulkan_kernel::vulkan_kernel_entry entry; |
| 347 | entry.info = &info; |
| 348 | |
| 349 | auto& prog_entry = prog.second; |
| 350 | const auto& dev = prog.first.get(); |
| 351 | const auto& vk_dev = (const vulkan_device&)dev; |
| 352 | |
| 353 | const VkShaderStageFlagBits stage = (info.type == FUNCTION_TYPE::VERTEX ? VK_SHADER_STAGE_VERTEX_BIT : |
| 354 | info.type == FUNCTION_TYPE::FRAGMENT ? VK_SHADER_STAGE_FRAGMENT_BIT : |
| 355 | VK_SHADER_STAGE_COMPUTE_BIT /* should notice anything else earlier */); |
| 356 | |
| 357 | if (!info.has_valid_required_local_size()) { |
| 358 | entry.max_local_size = dev.max_local_size; |
| 359 | |
| 360 | // always assume that we can execute this with the max possible work-group size, |
| 361 | // i.e. use this as the initial default |
| 362 | entry.max_total_local_size = dev.max_total_local_size; |
| 363 | } else { |
| 364 | // a required local size/dim is specified -> use it |
| 365 | entry.max_local_size = info.required_local_size; |
| 366 | entry.max_total_local_size = info.required_local_size.extent(); |
| 367 | } |
| 368 | |
| 369 | // TODO: make sure that _all_ of this is synchronized |
| 370 | if (!create_kernel_entry_descriptor_buffer(entry, dev, stage, func_name, info)) { |
| 371 | continue; |
| 372 | } |
| 373 | |
| 374 | // find SPIR-V module index for this function |
| 375 | const auto mod_iter = prog_entry.func_to_mod_map.find(func_name); |
| 376 | if (mod_iter == prog_entry.func_to_mod_map.end()) { |
| 377 | log_error("did not find a module mapping for function \"$\"", func_name); |
| 378 | continue; |
| 379 | } |
| 380 | |
| 381 | // stage info, can be used here or at a later point |
| 382 | entry.stage_sub_group_info = VkPipelineShaderStageRequiredSubgroupSizeCreateInfo { |
| 383 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO, |
| 384 | .pNext = nullptr, |
| 385 | // TODO: sub-group size / SIMD-width must really be stored in function info, |
| 386 | // this may not work if the device supports a SIMD-width range and the program has not been compiled for the default width |
| 387 | .requiredSubgroupSize = dev.simd_width, |
nothing calls this directly
no test coverage detected