197 lines
6.4 KiB
Python

Import('env')
env = env.Clone()
VK_FUNCTION_BLACKLIST = {'vkGetFramebufferTilePropertiesQCOM', 'vkGetDynamicRenderingTilePropertiesQCOM'}
def parse_cmd_node(node, vulkan_hpp):
proto_tag = node.find('proto')
cmd_name = proto_tag and proto_tag.find('name').text or node.attrib.get('name', '')
if not cmd_name or cmd_name in VK_FUNCTION_BLACKLIST:
return
if proto_tag is None:
vulkan_hpp['commands'][node.attrib['name']] = {
'name': node.attrib['name'],
'alias': node.attrib['alias'],
'extension': '',
'platform': ''
}
return
type_tag = proto_tag.find('type')
name_tag = proto_tag.find('name')
params = []
for param_tag in node.findall('param'):
param_type_tag = param_tag.find('type')
param_name_tag = param_tag.find('name')
params.append({
'type': ((param_tag.text or "") + param_type_tag.text + (param_type_tag.tail or "")).strip(),
'name': param_name_tag.text.strip(),
'name_type_suffix': (param_name_tag.tail or "").strip()
})
vulkan_hpp['commands'][name_tag.text.strip()] = {
'name': name_tag.text.strip(),
'return_type': type_tag.text,
'params': params,
'extension': '',
'platform': ''
}
def parse_type_node(node, vulkan_hpp):
alias_for = node.attrib.get('alias')
type_name = node.attrib.get('name', '')
if alias_for is not None:
vulkan_hpp['types'][type_name] = {
'name': type_name,
'alias': alias_for,
'extension': '',
'platform': ''
}
return
category = node.attrib.get('category')
if category in ('struct', 'union'):
parse_struct_type_node(node, vulkan_hpp)
elif category == 'handle':
parse_handle_type_node(node, vulkan_hpp)
def parse_struct_type_node(node, vulkan_hpp):
type_name = node.attrib['name']
category = node.attrib.get('category')
members = []
sType = ''
for member_tag in node.findall('member'):
member_type_tag = member_tag.find('type')
member_name_tag = member_tag.find('name')
members.append({
'type': ((member_tag.text or "") + member_type_tag.text + (member_type_tag.tail or "")).strip(),
'name': member_name_tag.text.strip(),
'name_type_suffix': (member_name_tag.tail or "").strip(),
'length': member_tag.attrib.get('len', '')
})
if member_name_tag.text == 'sType':
sType = member_tag.attrib.get('values', '').split(',')[0]
vulkan_hpp['types'][type_name] = {
'name': type_name,
'category': category,
'members': members,
'sType': sType,
'extension': '',
'platform': ''
}
def parse_handle_type_node(node, vulkan_hpp):
name_tag = node.find('name')
if name_tag is None:
return
type_name = name_tag.text
vulkan_hpp['types'][type_name] = {
'name': type_name,
'category': 'handle',
'objtypeenum': node.attrib['objtypeenum'],
'extension': '',
'platform': ''
}
def parse_platform_node(platform_node, vulkan_hpp):
platform_name = platform_node.attrib['name']
vulkan_hpp['platforms'][platform_name] = {
'protect': platform_node.attrib['protect']
}
def parse_extension_node(extension_node, vulkan_hpp):
extension_name = extension_node.attrib['name']
platform_name = extension_node.attrib.get('platform', '')
require_node = extension_node.find('require')
for cmd_node in require_node.findall('command'):
cmd_name = cmd_node.attrib['name']
if cmd_name in vulkan_hpp['commands']:
vulkan_hpp['commands'][cmd_name]['extension'] = extension_name
vulkan_hpp['commands'][cmd_name]['platform'] = platform_name
for type_node in require_node.findall('type'):
type_name = type_node.attrib['name']
if type_name in vulkan_hpp['types']:
vulkan_hpp['types'][type_name]['extension'] = extension_name
vulkan_hpp['types'][type_name]['platform'] = platform_name
vulkan_hpp['extensions'][extension_name] = {
'platform': platform_name
}
def parse_vulkan_hpp():
import xml.etree.ElementTree as ET
vulkan_hpp = {
'commands': {},
'types': {},
'extensions': {},
'platforms': {}
}
tree = ET.parse('thirdparty/vulkan-docs/xml/vk.xml')
root = tree.getroot()
cmds_node = root.find('commands')
for cmd_node in cmds_node:
parse_cmd_node(cmd_node, vulkan_hpp)
types_node = root.find('types')
for type_node in types_node:
parse_type_node(type_node, vulkan_hpp)
platforms_node = root.find('platforms')
for platform_node in platforms_node:
parse_platform_node(platform_node, vulkan_hpp)
extensions_node = root.find('extensions')
for extension_node in extensions_node:
parse_extension_node(extension_node, vulkan_hpp)
return vulkan_hpp
vulkan_hpp = parse_vulkan_hpp()
def generate_source(target, source, env):
import os
import sys
from importlib.util import module_from_spec, spec_from_file_location
# allow the module to import from its current folder
sys.path.append(os.path.dirname(source[0].abspath))
python_spec = spec_from_file_location('source', source[0].abspath)
python_mod = module_from_spec(python_spec)
python_spec.loader.exec_module(python_mod)
python_mod.vulkan_hpp = vulkan_hpp
python_mod.generate(targets = [t.abspath for t in target])
# restore path
sys.path = sys.path[:-1]
return None
pygen_builder = Builder(action = generate_source)
# env.Append(CCFLAGS = ' -Wall -Wextra -Werror -pedantic -std=c++20')
env.Append(BUILDERS = {'PyGen': pygen_builder})
env.Append(CPPPATH = ['include'])
source_files = Split("""
source/data_pool.cpp
source/dispatch_table.cpp
source/functions.cpp
source/function_ids.cpp
source/layer.cpp
source/record_list.cpp
source/variant_pool.cpp
""")
# env.PyGen('source/functions.hpp', 'generators/functions.hpp.py')
env.PyGen('include/vk_function_ids.h', 'generators/vk_function_ids.h.py')
env.PyGen('source/function_ids.cpp', 'generators/function_ids.cpp.py')
env.PyGen('source/functions.cpp', 'generators/functions.cpp.py')
env.PyGen('source/variant_wrap.hpp', 'generators/variant_wrap.hpp.py')
env.SharedLibrary(
target = 'VkLayer_capture',
source = source_files
)