libcruft-vk/load/vendor.cpp

81 lines
2.4 KiB
C++

#include "vendor.hpp"
#include <cruft/json/tree.hpp>
#include <cruft/util/std.hpp>
#include <cruft/util/log.hpp>
using cruft::vk::load::vendor;
#define MAP_ICD_COMMANDS(FUNC,...) MAP0(FUNC,\
vk_icdNegotiateLoaderICDInterfaceVersion,\
vk_icdGetInstanceProcAddr,\
vk_icdGetPhysicalDeviceProcAddr)
///////////////////////////////////////////////////////////////////////////////
template <>
cruft::vk::load::icd_t
json::tree::io<cruft::vk::load::icd_t>::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<decltype(vtable.NAME)> (#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<std::underlying_type_t<decltype(err)>>(err)
);
throw std::runtime_error (unknown_message);
case VK_SUCCESS:
LOG_INFO ("vk::load 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)
};
}