spec: add initial vtable stubs

This commit is contained in:
Danny Robson 2018-09-08 12:32:20 +10:00
parent 11c142f849
commit 26c9c3f70d
2 changed files with 76 additions and 20 deletions

View File

@ -32,6 +32,7 @@ add_custom_command (
OUTPUT OUTPUT
"${CMAKE_CURRENT_BINARY_DIR}/vk.hpp" "${CMAKE_CURRENT_BINARY_DIR}/vk.hpp"
"${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp" "${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/icd/vtable.hpp"
COMMENT COMMENT
"[spec.py] vk.hpp" "[spec.py] vk.hpp"
COMMAND COMMAND
@ -39,6 +40,7 @@ COMMAND
"${CMAKE_CURRENT_SOURCE_DIR}/tools/spec.py" "${CMAKE_CURRENT_SOURCE_DIR}/tools/spec.py"
"--src" "${CMAKE_CURRENT_SOURCE_DIR}/specs/xml/vk.xml" "--src" "${CMAKE_CURRENT_SOURCE_DIR}/specs/xml/vk.xml"
"--dst" "${CMAKE_CURRENT_BINARY_DIR}/vk.hpp" "--dst" "${CMAKE_CURRENT_BINARY_DIR}/vk.hpp"
"--icd" "${CMAKE_CURRENT_BINARY_DIR}/icd/vtable.hpp"
"--dispatch" "${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp" "--dispatch" "${CMAKE_CURRENT_BINARY_DIR}/icd/dispatch.cpp"
"--platform" "${VK_PLATFORM}" "--platform" "${VK_PLATFORM}"
DEPENDS DEPENDS
@ -61,6 +63,7 @@ endif()
##----------------------------------------------------------------------------- ##-----------------------------------------------------------------------------
add_library (cruft-vk-icd STATIC add_library (cruft-vk-icd STATIC
${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

View File

@ -69,9 +69,15 @@ class type(object):
This includes (but is not limited to) types, like structures; and values, This includes (but is not limited to) types, like structures; and values,
like constants. 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.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): def depends(self):
return self.depends return self.depends
@ -85,18 +91,28 @@ class type(object):
############################################################################### ###############################################################################
class aliastype(type): 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 self.target = target
def declare(self): def declare(self):
return "using %(name)s = %(target)s;" % { return f"using {rename(self.name)} = {rename(self.target)};"
"name": self.name,
"target": self.target
}
##-----------------------------------------------------------------------------
class aliasvalue(type): 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): def __init__(self, name:str, target:str):
super().__init__(name, depends=[target]) super().__init__(name, depends=[target])
self.target = target self.target = target
@ -104,8 +120,8 @@ class aliasvalue(type):
def declare(self): def declare(self):
return "constexpr auto %(name)s = %(target)s;" % { return "constexpr auto %(name)s = %(target)s;" % {
"name": self.name, "name": rename(self.name),
"target": self.target "target": rename(self.target),
} }
@ -369,6 +385,21 @@ class constant(type):
class command(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): def __init__(self, node):
assert node.tag == "command" assert node.tag == "command"
proto = node.find('proto') proto = node.find('proto')
@ -376,20 +407,16 @@ class command(type):
super().__init__(name) super().__init__(name)
self.result = proto.find('type').text self.result = proto.find('type').text
self.params = [self.param(p) for p in node.findall('./param')]
self.depends += [self.result] self.depends += [self.result]
for p in self.params:
self.params = [] self.depends += p.depends
for p in node.findall('./param'):
self.depends.append(p.find('type').text)
self.params.append("".join(p.itertext()))
pass
def declare(self): def declare(self):
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(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 = 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('--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('--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('--dispatch', type=str, help="the output path for function dispatch")
parser.add_argument( parser.add_argument(
'--platform', '--platform',
@ -700,19 +728,44 @@ if __name__ == '__main__':
dst.write('\n') dst.write('\n')
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: with open(args.dispatch, 'w') as dispatch:
dispatch.write(""" dispatch.write("""
#include "vk.hpp" #include "vk.hpp"
#include "vtable.hpp"
#include <cruft/util/debug.hpp> #include <cruft/util/debug.hpp>
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
static cruft::vk::icd::vtable *s_vtable = nullptr;
""") """)
for obj in q: for obj in q:
if not isinstance(obj, command): if not isinstance(obj, command):
continue continue
dispatch.write(f""" dispatch.write(f"""
extern "C" {obj.result} {rename(obj.name)} ({", ".join(obj.params)}) noexcept {{ extern "C" {obj.result} {rename(obj.name)} ({", ".join(p.type for p in obj.params)}) noexcept {{
unimplemented (); return (*s_vtable->{obj.name})({", ".join(p.name for p in obj.params)});
}} }}
""") """)