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
|
add_library (cruft-vk-icd STATIC
|
||||||
|
icd/fwd.hpp
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/icd/vtable.hpp
|
${CMAKE_CURRENT_BINARY_DIR}/icd/vtable.hpp
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp
|
${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp
|
||||||
icd/vendor.hpp
|
icd/vendor.hpp
|
||||||
icd/vendor.cpp
|
icd/vendor.cpp
|
||||||
icd/vendor_${VK_LOADER_VENDOR}
|
icd/vendor_${VK_LOADER_VENDOR}
|
||||||
|
icd/vtable.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries (cruft-vk-icd cruft-json cruft)
|
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
|
#pragma once
|
||||||
|
|
||||||
#include "vk.hpp"
|
#include "vk.hpp"
|
||||||
|
|
||||||
#include <cruft/util/library.hpp>
|
#include <cruft/util/library.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <experimental/filesystem>
|
#include <experimental/filesystem>
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
namespace cruft::vk::icd {
|
namespace cruft::vk::icd {
|
||||||
struct icd_t {
|
struct icd_t {
|
||||||
std::string file_format_version;
|
std::string file_format_version;
|
||||||
struct {
|
struct {
|
||||||
std::experimental::filesystem::path library_path;
|
std::experimental::filesystem::path library_path;
|
||||||
std::string api_version;
|
std::string api_version;
|
||||||
} icd;
|
} icd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
std::vector<icd_t>
|
std::vector<icd_t>
|
||||||
enumerate (void);
|
enumerate (void);
|
||||||
|
|
||||||
|
|
||||||
class vendor {
|
class vendor {
|
||||||
public:
|
public:
|
||||||
vendor (icd_t const&);
|
vendor (icd_t const&);
|
||||||
vendor (::cruft::library &&);
|
vendor (::cruft::library &&);
|
||||||
|
|
||||||
struct vtable_t {
|
struct vtable_t {
|
||||||
VkResult (*CreateInstance) (
|
VkResult (*CreateInstance) (
|
||||||
VkInstanceCreateInfo const*,
|
VkInstanceCreateInfo const*,
|
||||||
VkAllocationCallbacks const*,
|
VkAllocationCallbacks const*,
|
||||||
VkInstance*
|
VkInstance*
|
||||||
) noexcept;
|
) noexcept;
|
||||||
} vtable;
|
} vtable;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using get_proc_t = void* (*)(VkInstance, char const*);
|
::cruft::library m_library;
|
||||||
|
|
||||||
::cruft::library m_library;
|
public:
|
||||||
get_proc_t const m_get_proc;
|
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/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*
|
*
|
||||||
* Copyright:
|
* Copyright:
|
||||||
* 2017, Danny Robson <danny@nerdcruft.net>
|
* 2017-2018, Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cruft/util/iterator.hpp>
|
#include <cruft/util/iterator.hpp>
|
||||||
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "../icd/vendor.hpp"
|
#include "../icd/vendor.hpp"
|
||||||
|
#include "icd/vtable.hpp"
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -25,6 +26,7 @@ main (int, char**)
|
|||||||
{
|
{
|
||||||
for (auto const &i: cruft::vk::icd::enumerate ()) {
|
for (auto const &i: cruft::vk::icd::enumerate ()) {
|
||||||
cruft::vk::icd::vendor v (i);
|
cruft::vk::icd::vendor v (i);
|
||||||
|
cruft::vk::icd::instance_table t (v);
|
||||||
|
|
||||||
//std::cout << "available_layers: [ "
|
//std::cout << "available_layers: [ "
|
||||||
// << cruft::make_infix (cruft::vk::instance::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])
|
super().__init__(name, depends=[type])
|
||||||
self.type = type
|
self.type = type
|
||||||
|
self.parent = node.attrib.get('parent', None)
|
||||||
|
|
||||||
def declare(self):
|
def declare(self):
|
||||||
return "struct %(name)s_t; using %(name)s = %(name)s_t*;" % {
|
return "struct %(name)s_t; using %(name)s = %(name)s_t*;" % {
|
||||||
@ -236,6 +237,20 @@ class handle(type):
|
|||||||
"type": self.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):
|
class enum(type):
|
||||||
def __init__(self,node):
|
def __init__(self,node):
|
||||||
@ -395,10 +410,14 @@ class command(type):
|
|||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
self.type = ""
|
self.type = node.find('type').text
|
||||||
|
|
||||||
|
self.param = ""
|
||||||
for i in node.iter():
|
for i in node.iter():
|
||||||
self.type += i.text or ""
|
self.param += i.text or ""
|
||||||
self.type += i.tail or ""
|
self.param += i.tail or ""
|
||||||
|
# normalise whitespace
|
||||||
|
self.param = " ".join(self.param.split())
|
||||||
|
|
||||||
def __init__(self, node):
|
def __init__(self, node):
|
||||||
assert node.tag == "command"
|
assert node.tag == "command"
|
||||||
@ -416,9 +435,43 @@ class command(type):
|
|||||||
return "%(result)s %(name)s (%(params)s) noexcept;" % {
|
return "%(result)s %(name)s (%(params)s) noexcept;" % {
|
||||||
'name': rename(self.name),
|
'name': rename(self.name),
|
||||||
'result': self.result,
|
'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):
|
class require(object):
|
||||||
def __init__(self, root):
|
def __init__(self, root):
|
||||||
@ -586,7 +639,7 @@ def parse_types(reg:registry, root):
|
|||||||
]
|
]
|
||||||
|
|
||||||
if category in supported_categories:
|
if category in supported_categories:
|
||||||
obj = globals()[category] (t)
|
obj = globals()[category](t)
|
||||||
reg.types[name] = obj
|
reg.types[name] = obj
|
||||||
else:
|
else:
|
||||||
raise 'unhandled type'
|
raise 'unhandled type'
|
||||||
@ -729,17 +782,43 @@ if __name__ == '__main__':
|
|||||||
dst.write('}\n')
|
dst.write('}\n')
|
||||||
|
|
||||||
with open(args.icd, 'w') as icd:
|
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"
|
#include "vk.hpp"
|
||||||
|
|
||||||
namespace cruft::vk::icd {
|
#include <cruft/util/preprocessor.hpp>
|
||||||
struct vtable {
|
|
||||||
|
#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:
|
for obj in instance_commands:
|
||||||
if not isinstance(obj, command):
|
icd.write(f"{obj.result} (*{obj.name}) ({','.join(p.param for p in obj.params)}) = nullptr;\n")
|
||||||
continue
|
|
||||||
icd.write(f"{obj.result} (*{obj.name}) ({','.join(p.type for p in obj.params)});\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("""
|
icd.write("""
|
||||||
};
|
};
|
||||||
@ -756,16 +835,25 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
#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 commands:
|
||||||
for obj in q:
|
if obj.is_instance(reg):
|
||||||
if not isinstance(obj, command):
|
table = "i_table"
|
||||||
continue
|
elif obj.is_device(reg):
|
||||||
|
table = "d_table"
|
||||||
|
else:
|
||||||
|
raise Exception("unhandled command type")
|
||||||
|
|
||||||
dispatch.write(f"""
|
dispatch.write(f"""
|
||||||
extern "C" {obj.result} {rename(obj.name)} ({", ".join(p.type for p in obj.params)}) noexcept {{
|
extern "C" {obj.result} {rename(obj.name)} ({", ".join(p.param for p in obj.params)}) noexcept {{
|
||||||
return (*s_vtable->{obj.name})({", ".join(p.name for p in obj.params)});
|
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