From 26c9c3f70d28062af855fa95bd84f0c6e39558a9 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Sat, 8 Sep 2018 12:32:20 +1000 Subject: [PATCH] spec: add initial vtable stubs --- CMakeLists.txt | 3 ++ tools/spec.py | 93 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 76 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 502e1e4..cb4e65f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ add_custom_command ( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/vk.hpp" "${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp" + "${CMAKE_CURRENT_BINARY_DIR}/icd/vtable.hpp" COMMENT "[spec.py] vk.hpp" COMMAND @@ -39,6 +40,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" + "--icd" "${CMAKE_CURRENT_BINARY_DIR}/icd/vtable.hpp" "--dispatch" "${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp" "--platform" "${VK_PLATFORM}" DEPENDS @@ -61,6 +63,7 @@ endif() ##----------------------------------------------------------------------------- add_library (cruft-vk-icd STATIC + ${CMAKE_CURRENT_BINARY_DIR}/icd/vtable.hpp ${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp icd/vendor.hpp icd/vendor.cpp diff --git a/tools/spec.py b/tools/spec.py index aaff279..e5c2e7a 100644 --- a/tools/spec.py +++ b/tools/spec.py @@ -69,9 +69,15 @@ class type(object): This includes (but is not limited to) types, like structures; and values, like constants. """ - def __init__(self, name:str, depends:List[str] = []): + def __init__(self, name:str, depends:List[str] = None): + assert name + self.name = name - self.depends = [] + depends + self.depends = depends or [] + + assert isinstance(self.depends, list) + for i in self.depends: + assert isinstance(i, str) def depends(self): return self.depends @@ -85,18 +91,28 @@ class type(object): ############################################################################### class aliastype(type): - def __init__(self, name:str, target:str): - super().__init__(name, depends=[target]) + """ + A type that is an alias for another type. + + May be serialised using an appropriate host language facility + (eg, a typedef) + """ + def __init__(self, name:str, target:str, depends:List[str]=None): + depends = depends or [] + super().__init__(name, depends=depends+[target]) self.target = target def declare(self): - return "using %(name)s = %(target)s;" % { - "name": self.name, - "target": self.target - } + return f"using {rename(self.name)} = {rename(self.target)};" +##----------------------------------------------------------------------------- class aliasvalue(type): + """ + A value that is an alias for another value. + + May be serialised using an appropriate host language facility. + """ def __init__(self, name:str, target:str): super().__init__(name, depends=[target]) self.target = target @@ -104,8 +120,8 @@ class aliasvalue(type): def declare(self): return "constexpr auto %(name)s = %(target)s;" % { - "name": self.name, - "target": self.target + "name": rename(self.name), + "target": rename(self.target), } @@ -369,6 +385,21 @@ class constant(type): class command(type): + class param(type): + def __init__(self, node, **kwargs): + assert node.tag == 'param' + + super().__init__( + name = node.find('name').text, + depends=[node.find('type').text], + **kwargs + ) + + self.type = "" + for i in node.iter(): + self.type += i.text or "" + self.type += i.tail or "" + def __init__(self, node): assert node.tag == "command" proto = node.find('proto') @@ -376,20 +407,16 @@ class command(type): super().__init__(name) self.result = proto.find('type').text + self.params = [self.param(p) for p in node.findall('./param')] self.depends += [self.result] - - self.params = [] - for p in node.findall('./param'): - self.depends.append(p.find('type').text) - self.params.append("".join(p.itertext())) - - pass + for p in self.params: + self.depends += p.depends def declare(self): return "%(result)s %(name)s (%(params)s) noexcept;" % { 'name': rename(self.name), 'result': self.result, - 'params': ", ".join(self.params) + 'params': ", ".join(p.type for p in self.params) } @@ -652,6 +679,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('--icd', type=str, help='the output path for the icd loading routines') parser.add_argument('--dispatch', type=str, help="the output path for function dispatch") parser.add_argument( '--platform', @@ -700,19 +728,44 @@ if __name__ == '__main__': dst.write('\n') dst.write('}\n') + with open(args.icd, 'w') as icd: + icd.write(""" + #include "vk.hpp" + + namespace cruft::vk::icd { + struct vtable { + """) + + 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") + + icd.write(""" + }; + } + """) + + with open(args.dispatch, 'w') as dispatch: dispatch.write(""" #include "vk.hpp" + #include "vtable.hpp" + #include #pragma GCC diagnostic ignored "-Wunused-parameter" + + static cruft::vk::icd::vtable *s_vtable = nullptr; """) + + 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 (); + 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)}); }} """)