#include "vendor.hpp" #include #include #include using cruft::vk::icd::vendor; #define MAP_ICD_COMMANDS(FUNC,...) MAP0(FUNC,\ vk_icdNegotiateLoaderICDInterfaceVersion,\ vk_icdGetInstanceProcAddr,\ vk_icdGetPhysicalDeviceProcAddr) /////////////////////////////////////////////////////////////////////////////// template <> cruft::vk::icd::icd_t json::tree::io::deserialise (json::tree::node const &obj) { return { .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 (), }, }; } /////////////////////////////////////////////////////////////////////////////// vendor::vendor (icd_t const &_icd): vendor (cruft::library (_icd.icd.library_path)) { ; } //----------------------------------------------------------------------------- vendor::vendor (::cruft::library &&_library) : m_library (std::move (_library)) { // Negotiate needs to be called before anything else. But we load all the // ICD calls at once for simplicity. #define GET(NAME) vtable.NAME = m_library.symbol (#NAME); MAP_ICD_COMMANDS (GET) #undef GET version = 2; switch (auto err = vtable.vk_icdNegotiateLoaderICDInterfaceVersion (&version); err) { case VK_ERROR_INCOMPATIBLE_DRIVER: static constexpr char incompatible_message[] = "Incompatible Vulkan ICD interface"; LOG_ERROR ("%! %!", incompatible_message, version); throw std::runtime_error (incompatible_message); default: static constexpr char unknown_message[] = "Unknown Vulkan ICD interface response"; LOG_ERROR ( "%! %!", unknown_message, static_cast>(err) ); throw std::runtime_error (unknown_message); case VK_SUCCESS: LOG_INFO ("vk::icd version %!", version); break; } // Only load the instance table after we've queried all the icd functions. itable = { #define LOADFN(NAME) \ .NAME = reinterpret_cast< \ decltype(itable.NAME) \ > ( \ vtable.vk_icdGetInstanceProcAddr (nullptr, #NAME) \ ), MAP_INSTANCE_COMMANDS (LOADFN) }; }