31 const std::vector<fs::path> &available_shaders,
32 const fs::path &library_directory, std::string name) {
33 name = trim_text(std::move(name));
38 fs::path requested(name);
39 if (requested.extension() !=
".spv") {
42 const auto match = std::find_if(
43 available_shaders.begin(), available_shaders.end(),
44 [&](
const fs::path &shader) {
45 return shader.filename() == requested.filename() ||
46 (!library_directory.empty() &&
47 shader.lexically_relative(library_directory) ==
50 return match == available_shaders.end() ? fs::path{} : *match;
55 const std::vector<fs::path> &available_shaders,
56 const fs::path &library_directory,
57 std::ostream &warning_output) {
59 std::ifstream playlist_input(playlist_path);
60 if (!playlist_input) {
61 throw std::runtime_error(
"unable to open playlist: " +
62 playlist_path.string());
65 std::vector<PlaylistNode> playlist;
67 std::vector<fs::path> default_entries;
69 std::size_t line_number = 1;
70 std::size_t entry_count = 0;
72 "shader playlist", line_number++)) {
73 line = trim_text(std::move(line));
74 if (line.empty() || line.front() ==
'#') {
77 if (line.size() >= 2 && line.front() ==
'[' &&
80 throw std::runtime_error(
81 "shader playlist contains too many nodes");
83 std::string node_name =
84 trim_text(line.substr(1, line.size() - 2));
87 "shader playlist node");
88 playlist.push_back({std::move(node_name), {}});
89 current_node = &playlist.back();
92 if (line.front() ==
'[' || line.back() ==
']') {
93 throw std::runtime_error(
94 "malformed shader playlist node at line " +
95 std::to_string(line_number - 1));
98 throw std::runtime_error(
99 "shader playlist contains too many entries");
102 "shader playlist entry");
105 available_shaders, library_directory, line);
106 if (shader.empty()) {
107 warning_output <<
"acmxvk: playlist shader not found: " << line
111 if (current_node !=
nullptr) {
112 current_node->
shaders.push_back(shader);
114 default_entries.push_back(shader);
118 playlist.erase(std::remove_if(playlist.begin(), playlist.end(),
120 return node.shaders.empty();
123 if (!default_entries.empty()) {
124 playlist.insert(playlist.begin(),
125 {
"Default", std::move(default_entries)});
127 if (playlist.empty()) {
128 throw std::runtime_error(
129 "playlist contains no shaders available in the SPIR-V library");