icd: add stub loader definitions

This commit is contained in:
Danny Robson 2018-08-24 17:33:09 +10:00
parent 114f480b4d
commit cf6ba5e462
7 changed files with 183 additions and 12 deletions

View File

@ -4,7 +4,6 @@ project(cruft-vulkan CXX)
###############################################################################
find_package (Vulkan REQUIRED)
find_package (PythonInterp 3 REQUIRED)
find_package (glfw3 REQUIRED)
@ -15,6 +14,7 @@ endif ()
###############################################################################
file (MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/icd")
include_directories ("${CMAKE_CURRENT_BINARY_DIR}")
@ -31,6 +31,7 @@ endif()
add_custom_command (
OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/vk.hpp"
"${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp"
COMMENT
"[spec.py] vk.hpp"
COMMAND
@ -38,6 +39,7 @@ COMMAND
"${CMAKE_CURRENT_SOURCE_DIR}/tools/spec.py"
"--src" "${CMAKE_CURRENT_SOURCE_DIR}/specs/xml/vk.xml"
"--dst" "${CMAKE_CURRENT_BINARY_DIR}/vk.hpp"
"--dispatch" "${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp"
"--platform" "${VK_PLATFORM}"
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/tools/spec.py"
@ -47,7 +49,27 @@ DEPENDS
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/specs/include/vulkan")
###############################################################################
if (WIN32)
set(VK_LOADER_VENDOR win32)
elseif (LINUX)
set(VK_LOADER_VENDOR posix)
else ()
message (FATAL_ERROR "unhandled vk-loader platform")
endif()
##-----------------------------------------------------------------------------
add_library (cruft-vk-icd STATIC
${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp
icd/vendor.hpp
icd/vendor.cpp
icd/vendor_${VK_LOADER_VENDOR}
)
target_link_libraries (cruft-vk-icd cruft-json cruft)
###############################################################################
list (APPEND sources
vk.hpp
@ -107,7 +129,7 @@ list (APPEND sources
##-----------------------------------------------------------------------------
add_library (cruft-vk STATIC ${sources})
target_link_libraries (cruft-vk cruft vulkan)
target_link_libraries (cruft-vk cruft-vk-icd cruft)
###############################################################################

34
icd/vendor.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "vendor.hpp"
#include <cruft/json/tree.hpp>
using cruft::vk::icd::vendor;
template <>
cruft::vk::icd::icd_t
json::tree::io<cruft::vk::icd::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))
, m_get_proc (m_library.symbol<decltype(m_get_proc)> ("vk_icdGetInstanceProcAddr"))
{
vtable.CreateInstance = reinterpret_cast<decltype(vtable.CreateInstance)> (m_get_proc (nullptr, "vkCreateInstance"));
}

40
icd/vendor.hpp Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include "vk.hpp"
#include <cruft/util/library.hpp>
#include <string>
#include <experimental/filesystem>
namespace cruft::vk::icd {
struct icd_t {
std::string file_format_version;
struct {
std::experimental::filesystem::path library_path;
std::string api_version;
} icd;
};
std::vector<icd_t>
enumerate (void);
class vendor {
public:
vendor (icd_t const&);
vendor (::cruft::library &&);
struct vtable_t {
VkResult (*CreateInstance) (const VkInstanceCreateInfo*, const VkAllocationCallbacks*, VkInstance*) noexcept;
} vtable;
private:
using get_proc_t = void* (*)(VkInstance, char const*);
::cruft::library m_library;
get_proc_t const m_get_proc;
};
}

0
icd/vendor_posix.cpp Normal file
View File

51
icd/vendor_win32.cpp Normal file
View File

@ -0,0 +1,51 @@
#include "vendor.hpp"
#include <cruft/json/tree.hpp>
#include <cruft/util/io.hpp>
#include <cruft/util/log.hpp>
#include <cruft/util/win32/registry.hpp>
#include <cruft/util/win32/except.hpp>
///////////////////////////////////////////////////////////////////////////////
std::vector<cruft::vk::icd::icd_t>
cruft::vk::icd::enumerate()
{
std::vector<icd_t> res;
win32::key root (HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Class\\");
for (auto &&adapter: root.subkeys ()) {
for (auto &&device: adapter.subkeys ()) {
// device keys must be of the form '000X'
auto const name = device.name ();
if (name.size () != 4 ||
name[0] != '0' ||
name[1] != '0' ||
name[2] != '0' ||
!std::isdigit(name[3]))
{
continue;
}
// 'VulkanDriverName' contains the JSON for the ICD data. Parse
// this and add to the list. If we encounter an error then
// quietly drop it.
try {
auto const path = device.data<std::string> ("VulkanDriverName");
auto const text = cruft::slurp<char> (path);
auto const jobj = json::tree::parse (cruft::view{text});
auto const data = from_json<icd_t> (*jobj);
res.push_back (data);
} catch (win32::error const&) {
;
} catch (std::exception const &e) {
LOG_WARNING ("error loading Vulkan ICD manifest, %!", e.what ());
}
}
}
return res;
}

View File

@ -16,10 +16,19 @@
#include <iostream>
#include "../icd/vendor.hpp"
///////////////////////////////////////////////////////////////////////////////
int
main (int, char**)
{
auto all = cruft::vk::icd::enumerate ();
for (auto const &i: all) {
cruft::vk::icd::vendor v (i);
}
std::cout << "available_layers: [ "
<< cruft::make_infix (cruft::vk::instance::available_layers ())
<< " ]\n";

View File

@ -652,6 +652,7 @@ if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Transform XML API specification into C++ headers')
parser.add_argument('--src', type=str, help='the path to the XML file to transform')
parser.add_argument('--dst', type=str, help='the output path for the result')
parser.add_argument('--dispatch', type=str, help="the output path for function dispatch")
parser.add_argument(
'--platform',
type=str,
@ -662,7 +663,6 @@ if __name__ == '__main__':
args = parser.parse_args()
src = open(args.src, 'r')
dst = open(args.dst, 'w')
tree = ET.parse(src)
root = tree.getroot()
@ -689,14 +689,29 @@ if __name__ == '__main__':
extensions = ["VK_KHR_swapchain", "VK_EXT_debug_report", "VK_KHR_external_memory"]
q = reg.serialise(args.platform)
with open(args.dst, 'w') as dst:
dst.write("#pragma once\n")
dst.write('extern "C" {\n')
for obj in q:
dst.write(obj.declare())
dst.write('\n')
dst.write(obj.define(reg))
dst.write('\n')
dst.write('}\n')
dst.write("#pragma once\n")
dst.write('extern "C" {\n')
for obj in q:
dst.write(obj.declare())
dst.write('\n')
dst.write(obj.define(reg))
dst.write('\n')
dst.write('}\n')
with open(args.dispatch, 'w') as dispatch:
dispatch.write("""
#include "vk.hpp"
#include <cruft/util/debug.hpp>
#write_types(dst, types)
#pragma GCC diagnostic ignored "-Wunused-parameter"
""")
for obj in q:
if not isinstance(obj, command):
continue
dispatch.write(f"""
extern "C" {obj.result} {rename(obj.name)} ({", ".join(obj.params)}) noexcept {{
unimplemented ();
}}
""")