| 1396 | } |
| 1397 | |
| 1398 | bool reshade::runtime::load_effect(const std::filesystem::path &source_file, const ini_file &preset, size_t effect_index, size_t permutation_index, bool force_load, bool preprocess_required) |
| 1399 | { |
| 1400 | const std::chrono::high_resolution_clock::time_point time_load_started = std::chrono::high_resolution_clock::now(); |
| 1401 | |
| 1402 | // Generate a unique string identifying this effect |
| 1403 | std::string attributes; |
| 1404 | attributes += "app=" + g_target_executable_path.stem().u8string() + ';'; |
| 1405 | attributes += "width=" + std::to_string(_effect_permutations[permutation_index].width) + ';'; |
| 1406 | attributes += "height=" + std::to_string(_effect_permutations[permutation_index].height) + ';'; |
| 1407 | attributes += "color_space=" + std::to_string(static_cast<uint32_t>(_effect_permutations[permutation_index].color_space)) + ';'; |
| 1408 | attributes += "color_format=" + std::to_string(static_cast<uint32_t>(_effect_permutations[permutation_index].color_format)) + ';'; |
| 1409 | attributes += "version=" + std::to_string(VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_REVISION) + ';'; |
| 1410 | attributes += "performance_mode=" + std::string(_performance_mode ? "1" : "0") + ';'; |
| 1411 | attributes += "vendor=" + std::to_string(_vendor_id) + ';'; |
| 1412 | attributes += "device=" + std::to_string(_device_id) + ';'; |
| 1413 | |
| 1414 | const std::string effect_name = source_file.filename().u8string(); |
| 1415 | |
| 1416 | std::vector<std::pair<std::string, std::string>> preprocessor_definitions = _global_preprocessor_definitions; |
| 1417 | // Insert preset preprocessor definitions before global ones, so that if there are duplicates, the preset ones are used (since 'add_macro_definition' succeeds only for the first occurance) |
| 1418 | if (const auto preset_it = _preset_preprocessor_definitions.find({}); |
| 1419 | preset_it != _preset_preprocessor_definitions.end()) |
| 1420 | preprocessor_definitions.insert(preprocessor_definitions.begin(), preset_it->second.cbegin(), preset_it->second.cend()); |
| 1421 | if (const auto preset_it = _preset_preprocessor_definitions.find(effect_name); |
| 1422 | preset_it != _preset_preprocessor_definitions.end()) |
| 1423 | preprocessor_definitions.insert(preprocessor_definitions.begin(), preset_it->second.cbegin(), preset_it->second.cend()); |
| 1424 | |
| 1425 | #if RESHADE_ADDON |
| 1426 | std::vector<std::string> addon_definitions; |
| 1427 | addon_definitions.reserve(addon_loaded_info.size()); |
| 1428 | for (const addon_info &info : addon_loaded_info) |
| 1429 | { |
| 1430 | if (info.handle == nullptr) |
| 1431 | continue; // Skip disabled add-ons |
| 1432 | |
| 1433 | std::string addon_definition; |
| 1434 | addon_definition.reserve(6 + info.name.size()); |
| 1435 | addon_definition = "ADDON_"; |
| 1436 | std::transform(info.name.begin(), info.name.end(), std::back_inserter(addon_definition), |
| 1437 | [](const std::string::value_type c) { |
| 1438 | return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') ? c : (c >= 'a' && c <= 'z') ? static_cast<std::string::value_type>(c - 'a' + 'A') : '_'; |
| 1439 | }); |
| 1440 | preprocessor_definitions.emplace_back(addon_definition, std::to_string(std::max(1, info.version.number.major * 10000 + info.version.number.minor * 100 + info.version.number.build))); |
| 1441 | } |
| 1442 | #endif |
| 1443 | |
| 1444 | for (const std::pair<std::string, std::string> &definition : preprocessor_definitions) |
| 1445 | attributes += definition.first + '=' + definition.second + ';'; |
| 1446 | |
| 1447 | std::error_code ec; |
| 1448 | std::set<std::filesystem::path> include_paths; |
| 1449 | if (source_file.is_absolute()) |
| 1450 | include_paths.emplace(source_file.parent_path()); |
| 1451 | for (std::filesystem::path include_path : _effect_search_paths) |
| 1452 | { |
| 1453 | const bool recursive_search = include_path.filename() == L"**"; |
| 1454 | if (recursive_search) |
| 1455 | include_path.remove_filename(); |
nothing calls this directly
no test coverage detected