25 fs::path
find_shader_path(
const std::vector<fs::path> &available_shaders,
const fs::path &library_directory, std::string name) {
26 name = trim_text(std::move(name));
31 fs::path requested(name);
32 if (requested.extension() !=
".spv") {
35 const auto match = std::find_if(available_shaders.begin(), available_shaders.end(), [&](
const fs::path &shader) { return shader.filename() == requested.filename() || (!library_directory.empty() && shader.lexically_relative(library_directory) == requested); });
36 return match == available_shaders.end() ? fs::path{} : *match;
39 std::vector<PlaylistNode>
load_playlist(
const fs::path &playlist_path,
const std::vector<fs::path> &available_shaders,
const fs::path &library_directory, std::ostream &warning_output) {
41 std::ifstream playlist_input(playlist_path);
42 if (!playlist_input) {
43 throw std::runtime_error(
"unable to open playlist: " + playlist_path.string());
46 std::vector<PlaylistNode> playlist;
48 std::vector<fs::path> default_entries;
50 std::size_t line_number = 1;
51 std::size_t entry_count = 0;
53 line = trim_text(std::move(line));
54 if (line.empty() || line.front() ==
'#') {
57 if (line.size() >= 2 && line.front() ==
'[' && line.back() ==
']') {
59 throw std::runtime_error(
"shader playlist contains too many nodes");
61 std::string node_name = trim_text(line.substr(1, line.size() - 2));
63 playlist.push_back({std::move(node_name), {}});
64 current_node = &playlist.back();
67 if (line.front() ==
'[' || line.back() ==
']') {
68 throw std::runtime_error(
"malformed shader playlist node at line " + std::to_string(line_number - 1));
71 throw std::runtime_error(
"shader playlist contains too many entries");
75 const fs::path shader =
find_shader_path(available_shaders, library_directory, line);
77 warning_output <<
"acmxvk: playlist shader not found: " << line <<
'\n';
80 if (current_node !=
nullptr) {
81 current_node->
shaders.push_back(shader);
83 default_entries.push_back(shader);
87 playlist.erase(std::remove_if(playlist.begin(), playlist.end(), [](
const PlaylistNode &node) { return node.shaders.empty(); }), playlist.end());
88 if (!default_entries.empty()) {
89 playlist.insert(playlist.begin(), {
"Default", std::move(default_entries)});
91 if (playlist.empty()) {
92 throw std::runtime_error(
"playlist contains no shaders available in the SPIR-V library");