diff --git a/icd/vendor.cpp b/icd/vendor.cpp index 573c6a4..aa09bd0 100644 --- a/icd/vendor.cpp +++ b/icd/vendor.cpp @@ -10,7 +10,7 @@ cruft::vk::icd::icd_t json::tree::io::deserialise (json::tree::node const &obj) { return { - .file_format_version = obj["'file_format_version"].as_string (), + .file_format_version = obj["file_format_version"].as_string (), .icd = { .library_path = obj["ICD"]["library_path"].as_string ().native (), .api_version = obj["ICD"]["api_version"].as_string (), diff --git a/icd/vendor.hpp b/icd/vendor.hpp index 5b03021..85bc202 100644 --- a/icd/vendor.hpp +++ b/icd/vendor.hpp @@ -8,6 +8,7 @@ #include +/////////////////////////////////////////////////////////////////////////////// namespace cruft::vk::icd { struct icd_t { std::string file_format_version; @@ -28,7 +29,11 @@ namespace cruft::vk::icd { vendor (::cruft::library &&); struct vtable_t { - VkResult (*CreateInstance) (const VkInstanceCreateInfo*, const VkAllocationCallbacks*, VkInstance*) noexcept; + VkResult (*CreateInstance) ( + VkInstanceCreateInfo const*, + VkAllocationCallbacks const*, + VkInstance* + ) noexcept; } vtable; private: diff --git a/icd/vendor_posix.cpp b/icd/vendor_posix.cpp index e69de29..b75b9ab 100644 --- a/icd/vendor_posix.cpp +++ b/icd/vendor_posix.cpp @@ -0,0 +1,53 @@ + +#include "vendor.hpp" + +#include +#include + +#include + +#include + +namespace fs = std::experimental::filesystem; + + +/////////////////////////////////////////////////////////////////////////////// +std::vector +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 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 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 (*json::tree::parse (path))); + } + } catch (std::exception const &e) { + LOG_INFO("failed to parse icd manifest; %!", e.what ()); + } + } + } + + return found; +} diff --git a/tools/info.cpp b/tools/info.cpp index 229d14e..9c011fa 100644 --- a/tools/info.cpp +++ b/tools/info.cpp @@ -23,19 +23,17 @@ int main (int, char**) { - auto all = cruft::vk::icd::enumerate (); - for (auto const &i: all) { + for (auto const &i: cruft::vk::icd::enumerate ()) { cruft::vk::icd::vendor v (i); + + //std::cout << "available_layers: [ " + // << cruft::make_infix (cruft::vk::instance::available_layers ()) + // << " ]\n"; + + cruft::vk::instance instance; + std::cout << "instance: " << instance << '\n'; + + for (const auto &d: cruft::vk::physical_device::find (instance)) + std::cout << d << '\n'; } - - - std::cout << "available_layers: [ " - << cruft::make_infix (cruft::vk::instance::available_layers ()) - << " ]\n"; - - cruft::vk::instance instance; - std::cout << "instance: " << instance << '\n'; - - for (const auto &d: cruft::vk::physical_device::find (instance)) - std::cout << d << '\n'; } \ No newline at end of file