2018-09-08 12:31:43 +10:00
|
|
|
|
|
|
|
#include "vendor.hpp"
|
|
|
|
|
|
|
|
#include <cruft/util/log.hpp>
|
|
|
|
#include <cruft/util/posix/except.hpp>
|
|
|
|
|
|
|
|
#include <cruft/json/tree.hpp>
|
|
|
|
|
|
|
|
#include <wordexp.h>
|
|
|
|
|
|
|
|
namespace fs = std::experimental::filesystem;
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::vector<cruft::vk::icd::icd_t>
|
|
|
|
cruft::vk::icd::enumerate (void)
|
|
|
|
{
|
|
|
|
// The predefined, ordered, search locations for manifests
|
|
|
|
static char const *locations[] = {
|
|
|
|
"/usr/local/etc/vulkan/icd.d/",
|
|
|
|
"/usr/local/share/vulkan/icd.d/",
|
|
|
|
"/etc/vulkan/icd.d/",
|
|
|
|
"/usr/share/vulkan/icd.d/",
|
|
|
|
"$HOME/.local/share/vulkan/icd.d/",
|
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<icd_t> found;
|
|
|
|
|
|
|
|
for (auto const &loc: locations) {
|
|
|
|
// We use wordexp rather than std::filesystem because we need to
|
|
|
|
// perform environment expansion to account of $HOME in at least one
|
|
|
|
// of the paths, so we may as well just use the same approach for
|
|
|
|
// everything else too.
|
|
|
|
wordexp_t words;
|
|
|
|
posix::error::try_call (wordexp, loc, &words, WRDE_NOCMD | WRDE_UNDEF);
|
|
|
|
std::unique_ptr<wordexp_t, decltype(&wordfree)> cleanup {&words, &wordfree};
|
|
|
|
|
|
|
|
// Just try to parse everything we can find in the directory (if it
|
|
|
|
// happens to exist) and fail out if it doesn't work. Marginally safer
|
|
|
|
// than doing various tests.
|
|
|
|
for (size_t i = 0; i < words.we_wordc; ++i) {
|
|
|
|
try {
|
|
|
|
for (auto const &path: fs::directory_iterator (words.we_wordv[i])) {
|
|
|
|
found.push_back (from_json<icd_t> (*json::tree::parse (path)));
|
|
|
|
}
|
|
|
|
} catch (std::exception const &e) {
|
|
|
|
LOG_INFO("failed to parse icd manifest; %!", e.what ());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return found;
|
|
|
|
}
|