2019-03-02 22:47:03 +11:00
|
|
|
#include "vendor.hpp"
|
|
|
|
|
|
|
|
#include <cruft/json/tree.hpp>
|
|
|
|
|
|
|
|
#include <cruft/util/std.hpp>
|
|
|
|
#include <cruft/util/log.hpp>
|
|
|
|
|
2019-03-03 11:53:31 +11:00
|
|
|
using cruft::vk::load::vendor;
|
2019-03-02 22:47:03 +11:00
|
|
|
|
|
|
|
|
|
|
|
#define MAP_ICD_COMMANDS(FUNC,...) MAP0(FUNC,\
|
|
|
|
vk_icdNegotiateLoaderICDInterfaceVersion,\
|
|
|
|
vk_icdGetInstanceProcAddr,\
|
|
|
|
vk_icdGetPhysicalDeviceProcAddr)
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
template <>
|
2019-03-03 11:53:31 +11:00
|
|
|
cruft::vk::load::icd_t
|
|
|
|
json::tree::io<cruft::vk::load::icd_t>::deserialise (json::tree::node const &obj)
|
2019-03-02 22:47:03 +11:00
|
|
|
{
|
|
|
|
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:
|
2019-03-03 11:53:31 +11:00
|
|
|
LOG_INFO ("vk::load version %!", version);
|
2019-03-02 22:47:03 +11:00
|
|
|
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)
|
|
|
|
};
|
2019-01-05 23:30:52 +11:00
|
|
|
}
|