icd: add initial instance and device vtables
This commit is contained in:
parent
26c9c3f70d
commit
b8f405c134
@ -63,11 +63,13 @@ endif()
|
||||
|
||||
##-----------------------------------------------------------------------------
|
||||
add_library (cruft-vk-icd STATIC
|
||||
icd/fwd.hpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/icd/vtable.hpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp
|
||||
icd/vendor.hpp
|
||||
icd/vendor.cpp
|
||||
icd/vendor_${VK_LOADER_VENDOR}
|
||||
icd/vtable.cpp
|
||||
)
|
||||
|
||||
target_link_libraries (cruft-vk-icd cruft-json cruft)
|
||||
|
0
icd/fwd.hpp
Normal file
0
icd/fwd.hpp
Normal file
@ -1,45 +1,46 @@
|
||||
#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) (
|
||||
VkInstanceCreateInfo const*,
|
||||
VkAllocationCallbacks const*,
|
||||
VkInstance*
|
||||
) noexcept;
|
||||
} vtable;
|
||||
|
||||
private:
|
||||
using get_proc_t = void* (*)(VkInstance, char const*);
|
||||
|
||||
::cruft::library m_library;
|
||||
get_proc_t const m_get_proc;
|
||||
};
|
||||
}
|
||||
#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) (
|
||||
VkInstanceCreateInfo const*,
|
||||
VkAllocationCallbacks const*,
|
||||
VkInstance*
|
||||
) noexcept;
|
||||
} vtable;
|
||||
|
||||
private:
|
||||
::cruft::library m_library;
|
||||
|
||||
public:
|
||||
using get_proc_t = void* (*)(VkInstance, char const*);
|
||||
get_proc_t const m_get_proc;
|
||||
};
|
||||
}
|
||||
|
14
icd/vtable.cpp
Normal file
14
icd/vtable.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "icd/vtable.hpp"
|
||||
|
||||
#include "vendor.hpp"
|
||||
|
||||
using cruft::vk::icd::instance_table;
|
||||
|
||||
instance_table::instance_table (vendor &src)
|
||||
{
|
||||
#define LOADFN(name) this->name = reinterpret_cast<decltype(this->name)> (src.m_get_proc(
|
||||
|
||||
this->vkCreateInstance = reinterpret_cast<decltype(this->vkCreateInstance)> (
|
||||
src.m_get_proc(nullptr, "vkCreateInstance")
|
||||
);
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright:
|
||||
* 2017, Danny Robson <danny@nerdcruft.net>
|
||||
* 2017-2018, Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include <cruft/util/iterator.hpp>
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
|
||||
#include "../icd/vendor.hpp"
|
||||
#include "icd/vtable.hpp"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -25,6 +26,7 @@ main (int, char**)
|
||||
{
|
||||
for (auto const &i: cruft::vk::icd::enumerate ()) {
|
||||
cruft::vk::icd::vendor v (i);
|
||||
cruft::vk::icd::instance_table t (v);
|
||||
|
||||
//std::cout << "available_layers: [ "
|
||||
// << cruft::make_infix (cruft::vk::instance::available_layers ())
|
||||
|
128
tools/spec.py
128
tools/spec.py
@ -229,6 +229,7 @@ class handle(type):
|
||||
|
||||
super().__init__(name, depends=[type])
|
||||
self.type = type
|
||||
self.parent = node.attrib.get('parent', None)
|
||||
|
||||
def declare(self):
|
||||
return "struct %(name)s_t; using %(name)s = %(name)s_t*;" % {
|
||||
@ -236,6 +237,20 @@ class handle(type):
|
||||
"type": self.type
|
||||
}
|
||||
|
||||
def has_parent(self, name:str, reg:registry) -> bool:
|
||||
"""
|
||||
Recursively check if this type is derived from a given parent type.
|
||||
"""
|
||||
assert name
|
||||
assert reg
|
||||
|
||||
if not self.parent:
|
||||
return False
|
||||
if self.parent == name:
|
||||
return True
|
||||
|
||||
return reg.types[self.parent].has_parent(name, reg)
|
||||
|
||||
|
||||
class enum(type):
|
||||
def __init__(self,node):
|
||||
@ -395,10 +410,14 @@ class command(type):
|
||||
**kwargs
|
||||
)
|
||||
|
||||
self.type = ""
|
||||
self.type = node.find('type').text
|
||||
|
||||
self.param = ""
|
||||
for i in node.iter():
|
||||
self.type += i.text or ""
|
||||
self.type += i.tail or ""
|
||||
self.param += i.text or ""
|
||||
self.param += i.tail or ""
|
||||
# normalise whitespace
|
||||
self.param = " ".join(self.param.split())
|
||||
|
||||
def __init__(self, node):
|
||||
assert node.tag == "command"
|
||||
@ -416,9 +435,43 @@ class command(type):
|
||||
return "%(result)s %(name)s (%(params)s) noexcept;" % {
|
||||
'name': rename(self.name),
|
||||
'result': self.result,
|
||||
'params': ", ".join(p.type for p in self.params)
|
||||
'params': ", ".join(p.param for p in self.params)
|
||||
}
|
||||
|
||||
def is_instance(self, reg:registry):
|
||||
assert reg
|
||||
|
||||
if not self.params:
|
||||
return True
|
||||
|
||||
first_arg = self.params[0].type
|
||||
if first_arg == 'VkInstance':
|
||||
return True
|
||||
|
||||
first_obj = reg.types[first_arg]
|
||||
|
||||
# If the first type isn't a handle of any description then it should
|
||||
# be an instance function.
|
||||
if not isinstance(first_obj, handle):
|
||||
return True
|
||||
|
||||
# Both VkInstance and VkPhysicalDevice are listed as possible instance
|
||||
# parameters.
|
||||
#
|
||||
# Test that the handle is derived from VkInstance, and not derived from
|
||||
# VkDevice. The second test is required because VkDevice is indirectly
|
||||
# derived from VkInstance. This approach buys us a little more
|
||||
# generality.
|
||||
|
||||
if not first_obj.has_parent('VkInstance', reg):
|
||||
return False
|
||||
if first_arg == 'VkDevice' or first_obj.has_parent('VkDevice', reg):
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_device(self, reg:registry):
|
||||
return not self.is_instance(reg)
|
||||
|
||||
|
||||
class require(object):
|
||||
def __init__(self, root):
|
||||
@ -586,7 +639,7 @@ def parse_types(reg:registry, root):
|
||||
]
|
||||
|
||||
if category in supported_categories:
|
||||
obj = globals()[category] (t)
|
||||
obj = globals()[category](t)
|
||||
reg.types[name] = obj
|
||||
else:
|
||||
raise 'unhandled type'
|
||||
@ -729,17 +782,43 @@ if __name__ == '__main__':
|
||||
dst.write('}\n')
|
||||
|
||||
with open(args.icd, 'w') as icd:
|
||||
icd.write("""
|
||||
commands = [i for i in q if isinstance(i, command)]
|
||||
instance_commands = [i for i in commands if i.is_instance(reg)]
|
||||
device_commands = [i for i in commands if i.is_device(reg)]
|
||||
|
||||
assert len(instance_commands) + len(device_commands) == len(commands)
|
||||
|
||||
icd.write(f"""
|
||||
#include "vk.hpp"
|
||||
|
||||
namespace cruft::vk::icd {
|
||||
struct vtable {
|
||||
#include <cruft/util/preprocessor.hpp>
|
||||
|
||||
#define MAP_COMMANDS(FUNC) MAP0(FUNC,{",".join(i.name for i in commands)})
|
||||
#define MAP_INSTANCE_COMMANDS(FUNC) MAP0(FUNC,{",".join(i.name for i in instance_commands)})
|
||||
#define MAP_DEVICE_COMMANDS(FUNC) MAP0(FUNC,{",".join(i.name for i in device_commands)})
|
||||
|
||||
namespace cruft::vk::icd {{
|
||||
struct vendor;
|
||||
|
||||
struct func {{
|
||||
void *handle;
|
||||
void const *table;
|
||||
}};
|
||||
|
||||
struct instance_table {{
|
||||
instance_table (vendor &);
|
||||
""")
|
||||
|
||||
for obj in q:
|
||||
if not isinstance(obj, command):
|
||||
continue
|
||||
icd.write(f"{obj.result} (*{obj.name}) ({','.join(p.type for p in obj.params)});\n")
|
||||
for obj in instance_commands:
|
||||
icd.write(f"{obj.result} (*{obj.name}) ({','.join(p.param for p in obj.params)}) = nullptr;\n")
|
||||
|
||||
icd.write("""};
|
||||
|
||||
struct device_table {
|
||||
""")
|
||||
|
||||
for obj in device_commands:
|
||||
icd.write(f"{obj.result} (*{obj.name}) ({','.join(p.param for p in obj.params)}) = nullptr;\n")
|
||||
|
||||
icd.write("""
|
||||
};
|
||||
@ -756,16 +835,25 @@ if __name__ == '__main__':
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
static cruft::vk::icd::vtable *s_vtable = nullptr;
|
||||
static cruft::vk::icd::instance_table const *i_table = nullptr;
|
||||
static cruft::vk::icd::device_table const *d_table = nullptr;
|
||||
""")
|
||||
|
||||
|
||||
for obj in q:
|
||||
if not isinstance(obj, command):
|
||||
continue
|
||||
for obj in commands:
|
||||
if obj.is_instance(reg):
|
||||
table = "i_table"
|
||||
elif obj.is_device(reg):
|
||||
table = "d_table"
|
||||
else:
|
||||
raise Exception("unhandled command type")
|
||||
|
||||
dispatch.write(f"""
|
||||
extern "C" {obj.result} {rename(obj.name)} ({", ".join(p.type for p in obj.params)}) noexcept {{
|
||||
return (*s_vtable->{obj.name})({", ".join(p.name for p in obj.params)});
|
||||
}}
|
||||
extern "C" {obj.result} {rename(obj.name)} ({", ".join(p.param for p in obj.params)}) noexcept {{
|
||||
auto const entry = reinterpret_cast<cruft::vk::icd::func const*> ({obj.params[0].name});
|
||||
auto const *table = reinterpret_cast<decltype({table})> (entry->table);
|
||||
|
||||
return (table->{obj.name})(
|
||||
reinterpret_cast<decltype({obj.params[0].name})> (entry->handle),
|
||||
{", ".join(p.name for p in obj.params[1:])}
|
||||
);
|
||||
""")
|
||||
|
Loading…
Reference in New Issue
Block a user