From 530927d3f6a303d9ef1eb1e839566ccb0e813036 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 5 Mar 2019 10:38:14 +0000 Subject: [PATCH] vulkan/util: generate instance/device dispatch tables This will be used by the overlay instead of system installed validation layers helpers. Signed-off-by: Lionel Landwerlin Acked-by: Eric Engestrom --- src/vulkan/Makefile.am | 26 +++---- src/vulkan/meson.build | 21 +++++ src/vulkan/util/gen_enum_to_str.py | 118 +++++++++++++++++++++++++++-- src/vulkan/util/meson.build | 2 +- src/vulkan/wsi/meson.build | 5 -- 5 files changed, 148 insertions(+), 24 deletions(-) diff --git a/src/vulkan/Makefile.am b/src/vulkan/Makefile.am index ff9a79e9c32..9d5416fc855 100644 --- a/src/vulkan/Makefile.am +++ b/src/vulkan/Makefile.am @@ -24,19 +24,6 @@ EXTRA_DIST = \ wsi/meson.build \ meson.build -VULKAN_UTIL_SOURCES = \ - $(VULKAN_UTIL_FILES) \ - $(VULKAN_UTIL_GENERATED_FILES) - -util/vk_enum_to_str.c util/vk_enum_to_str.h: util/gen_enum_to_str.py \ - $(vulkan_api_xml) - $(MKDIR_GEN) - $(PYTHON_GEN) $(srcdir)/util/gen_enum_to_str.py \ - --xml $(vulkan_api_xml) \ - --outdir $(top_builddir)/src/vulkan/util - -libvulkan_util_la_SOURCES = $(VULKAN_UTIL_SOURCES) - AM_CPPFLAGS = \ $(DEFINES) \ -I$(top_srcdir)/include \ @@ -119,6 +106,19 @@ VULKAN_WSI_GENERATED_SOURCES += \ endif +VULKAN_UTIL_SOURCES = \ + $(VULKAN_UTIL_FILES) \ + $(VULKAN_UTIL_GENERATED_FILES) + +util/vk_enum_to_str.c util/vk_enum_to_str.h: util/gen_enum_to_str.py \ + $(vulkan_api_xml) + $(MKDIR_GEN) + $(PYTHON_GEN) $(srcdir)/util/gen_enum_to_str.py \ + --xml $(vulkan_api_xml) \ + --outdir $(top_builddir)/src/vulkan/util + +libvulkan_util_la_SOURCES = $(VULKAN_UTIL_SOURCES) + nodist_libvulkan_wsi_la_SOURCES = $(VULKAN_WSI_GENERATED_SOURCES) libvulkan_wsi_la_SOURCES = $(VULKAN_WSI_SOURCES) diff --git a/src/vulkan/meson.build b/src/vulkan/meson.build index 35d7e5e61d8..a287c308ed2 100644 --- a/src/vulkan/meson.build +++ b/src/vulkan/meson.build @@ -23,6 +23,27 @@ vk_api_xml = files('registry/vk.xml') inc_vulkan_util = include_directories('util') inc_vulkan_wsi = include_directories('wsi') +vulkan_wsi_args = [] +vulkan_wsi_list = [] + +if with_platform_x11 + vulkan_wsi_args += ['-DVK_USE_PLATFORM_XCB_KHR', '-DVK_USE_PLATFORM_XLIB_KHR'] + vulkan_wsi_list += ['xcb', 'x11'] +endif +if with_platform_wayland + vulkan_wsi_args += ['-DVK_USE_PLATFORM_WAYLAND_KHR'] + vulkan_wsi_list += ['wayland'] +endif +if with_platform_drm + vulkan_wsi_args += '-DVK_USE_PLATFORM_DISPLAY_KHR' + vulkan_wsi_list += ['drm'] +endif +if with_xlib_lease + vulkan_wsi_args += '-DVK_USE_PLATFORM_XLIB_XRANDR_EXT' + vulkan_wsi_list += ['xlib_xrandr'] +endif + + subdir('util') subdir('wsi') if get_option('vulkan-overlay-layer') diff --git a/src/vulkan/util/gen_enum_to_str.py b/src/vulkan/util/gen_enum_to_str.py index 06f74eb487c..cf031670ff7 100644 --- a/src/vulkan/util/gen_enum_to_str.py +++ b/src/vulkan/util/gen_enum_to_str.py @@ -57,6 +57,7 @@ C_TEMPLATE = Template(textwrap.dedent(u"""\ ${copyright} */ + #include #include #include #include "util/macros.h" @@ -85,7 +86,46 @@ C_TEMPLATE = Template(textwrap.dedent(u"""\ unreachable("Undefined enum value."); } } - %endfor"""), + %endfor + + void vk_load_instance_commands(VkInstance instance, + PFN_vkGetInstanceProcAddr gpa, + struct vk_instance_dispatch_table *table) + { + memset(table, 0, sizeof(*table)); + table->GetInstanceProcAddr = gpa; + % for cmd in commands: + % if not cmd.device_entrypoint and cmd.name != 'vkGetInstanceProcAddr': + % if cmd.extension is not None and cmd.extension.define is not None: + #ifdef ${cmd.extension.define} + table->${cmd.name[2:]} = (PFN_${cmd.name}) gpa(instance, "${cmd.name}"); + #endif + % else: + table->${cmd.name[2:]} = (PFN_${cmd.name}) gpa(instance, "${cmd.name}"); + % endif + % endif + %endfor + } + + void vk_load_device_commands(VkDevice device, + PFN_vkGetDeviceProcAddr gpa, + struct vk_device_dispatch_table *table) + { + memset(table, 0, sizeof(*table)); + table->GetDeviceProcAddr = gpa; + % for cmd in commands: + % if cmd.device_entrypoint and cmd.name != 'vkGetDeviceProcAddr': + % if cmd.extension is not None and cmd.extension.define is not None: + #ifdef ${cmd.extension.define} + table->${cmd.name[2:]} = (PFN_${cmd.name}) gpa(device, "${cmd.name}"); + #endif + % else: + table->${cmd.name[2:]} = (PFN_${cmd.name}) gpa(device, "${cmd.name}"); + % endif + % endif + %endfor + } + """), output_encoding='utf-8') H_TEMPLATE = Template(textwrap.dedent(u"""\ @@ -113,6 +153,39 @@ H_TEMPLATE = Template(textwrap.dedent(u"""\ const char * vk_${enum.name[2:]}_to_str(${enum.name} input); % endfor + struct vk_instance_dispatch_table { + PFN_vkGetInstanceProcAddr GetInstanceProcAddr; + % for cmd in commands: + % if not cmd.device_entrypoint and cmd.name != 'vkGetInstanceProcAddr': + % if cmd.extension is not None and cmd.extension.define is not None: + #ifdef ${cmd.extension.define} + PFN_${cmd.name} ${cmd.name[2:]}; + #endif + % else: + PFN_${cmd.name} ${cmd.name[2:]}; + % endif + % endif + %endfor + }; + + struct vk_device_dispatch_table { + PFN_vkGetDeviceProcAddr GetDeviceProcAddr; + % for cmd in commands: + % if cmd.device_entrypoint and cmd.name != 'vkGetDeviceProcAddr': + % if cmd.extension is not None and cmd.extension.define is not None: + #ifdef ${cmd.extension.define} + PFN_${cmd.name} ${cmd.name[2:]}; + #endif + % else: + PFN_${cmd.name} ${cmd.name[2:]}; + % endif + % endif + %endfor + }; + + void vk_load_instance_commands(VkInstance instance, PFN_vkGetInstanceProcAddr gpa, struct vk_instance_dispatch_table *table); + void vk_load_device_commands(VkDevice device, PFN_vkGetDeviceProcAddr gpa, struct vk_device_dispatch_table *table); + #ifdef __cplusplus } /* extern "C" */ #endif @@ -148,9 +221,15 @@ class NamedFactory(object): class VkExtension(object): """Simple struct-like class representing extensions""" - def __init__(self, name, number=None): + def __init__(self, name, number=None, platform=None): self.name = name self.number = number + self.define = None + if platform is not None: + ext = '_KHR' + if platform.upper() == 'XLIB_XRANDR': + ext = '_EXT' + self.define = 'VK_USE_PLATFORM_' + platform.upper() + ext class VkEnum(object): @@ -196,7 +275,16 @@ class VkEnum(object): error=error) -def parse_xml(enum_factory, ext_factory, filename): +class VkCommand(object): + """Simple struct-like class representing a single Vulkan command""" + + def __init__(self, name, device_entrypoint=False): + self.name = name + self.device_entrypoint = device_entrypoint + self.extension = None + + +def parse_xml(cmd_factory, enum_factory, ext_factory, filename): """Parse the XML file. Accumulate results into the factories. This parser is a memory efficient iterative XML parser that returns a list @@ -215,15 +303,32 @@ def parse_xml(enum_factory, ext_factory, filename): if enum is not None: enum.add_value_from_xml(value) + for command in xml.findall('./commands/command'): + name = command.find('./proto/name') + first_arg = command.find('./param/type') + # Some commands are alias KHR -> nonKHR, ignore those + if name is not None: + cmd_factory(name.text, + device_entrypoint=(first_arg.text in ('VkDevice', 'VkCommandBuffer', 'VkQueue'))) + for ext_elem in xml.findall('./extensions/extension[@supported="vulkan"]'): + platform = None + if "platform" in ext_elem.attrib: + platform = ext_elem.attrib['platform'] extension = ext_factory(ext_elem.attrib['name'], - number=int(ext_elem.attrib['number'])) + number=int(ext_elem.attrib['number']), + platform=platform) for value in ext_elem.findall('./require/enum[@extends]'): enum = enum_factory.get(value.attrib['extends']) if enum is not None: enum.add_value_from_xml(value, extension) + for t in ext_elem.findall('./require/command'): + command = cmd_factory.get(t.attrib['name']) + if command is not None: + command.extension = extension + def main(): parser = argparse.ArgumentParser() @@ -237,10 +342,12 @@ def main(): args = parser.parse_args() + command_factory = NamedFactory(VkCommand) enum_factory = NamedFactory(VkEnum) ext_factory = NamedFactory(VkExtension) for filename in args.xml_files: - parse_xml(enum_factory, ext_factory, filename) + parse_xml(command_factory, enum_factory, ext_factory, filename) + commands = sorted(command_factory.registry.values(), key=lambda e: e.name) enums = sorted(enum_factory.registry.values(), key=lambda e: e.name) extensions = sorted(ext_factory.registry.values(), key=lambda e: e.name) @@ -249,6 +356,7 @@ def main(): with open(file_, 'wb') as f: f.write(template.render( file=os.path.basename(__file__), + commands=commands, enums=enums, extensions=extensions, copyright=COPYRIGHT, diff --git a/src/vulkan/util/meson.build b/src/vulkan/util/meson.build index df09dd35f85..6aba265cc81 100644 --- a/src/vulkan/util/meson.build +++ b/src/vulkan/util/meson.build @@ -40,6 +40,6 @@ libvulkan_util = static_library( 'vulkan_util', [files_vulkan_util, vk_enum_to_str], include_directories : inc_common, - c_args : [c_vis_args], + c_args : [c_vis_args, vulkan_wsi_args], build_by_default : false, ) diff --git a/src/vulkan/wsi/meson.build b/src/vulkan/wsi/meson.build index 41e9c27ce8d..37555da6be0 100644 --- a/src/vulkan/wsi/meson.build +++ b/src/vulkan/wsi/meson.build @@ -18,13 +18,11 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -vulkan_wsi_args = [] vulkan_wsi_deps = [] files_vulkan_wsi = files('wsi_common.c') if with_platform_x11 - vulkan_wsi_args += ['-DVK_USE_PLATFORM_XCB_KHR', '-DVK_USE_PLATFORM_XLIB_KHR'] vulkan_wsi_deps += [ dep_xcb, dep_x11_xcb, @@ -39,7 +37,6 @@ endif if with_platform_wayland vulkan_wsi_deps += dep_wayland_client - vulkan_wsi_args += ['-DVK_USE_PLATFORM_WAYLAND_KHR'] files_vulkan_wsi += files('wsi_common_wayland.c') files_vulkan_wsi += [ wayland_drm_client_protocol_h, @@ -50,13 +47,11 @@ if with_platform_wayland endif if with_platform_drm - vulkan_wsi_args += '-DVK_USE_PLATFORM_DISPLAY_KHR' files_vulkan_wsi += files('wsi_common_display.c') endif if with_xlib_lease vulkan_wsi_deps += [dep_xcb_xrandr, dep_xlib_xrandr] - vulkan_wsi_args += '-DVK_USE_PLATFORM_XLIB_XRANDR_EXT' endif libvulkan_wsi = static_library( -- 2.30.2