From e9dcb17962f7e58a81c93bae7bd33885675b1043 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 15 Feb 2017 15:41:50 -0800 Subject: [PATCH] vulkan/util: Add generator for enum_to_str functions This adds a python generator to produce enum_to_str functions for Vulkan from the vk.xml API description. It supports extensions as well as core API features, and the generator works with both python2 and python3. Signed-off-by: Dylan Baker Acked-by: Matt Turner Acked-by: Jason Ekstrand --- configure.ac | 1 + src/Makefile.am | 2 +- src/intel/vulkan/Makefile.am | 2 + src/intel/vulkan/anv_util.c | 36 +----- src/vulkan/util/.gitignore | 1 + src/vulkan/util/Makefile.am | 22 ++++ src/vulkan/util/gen_enum_to_str.py | 172 +++++++++++++++++++++++++++++ 7 files changed, 201 insertions(+), 35 deletions(-) create mode 100644 src/vulkan/util/.gitignore create mode 100644 src/vulkan/util/Makefile.am create mode 100644 src/vulkan/util/gen_enum_to_str.py diff --git a/configure.ac b/configure.ac index 7e4544f5bf1..c83a5234da7 100644 --- a/configure.ac +++ b/configure.ac @@ -2691,6 +2691,7 @@ AC_CONFIG_FILES([Makefile src/mesa/main/tests/Makefile src/util/Makefile src/util/tests/hash_table/Makefile + src/vulkan/util/Makefile src/vulkan/wsi/Makefile]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 12e5dcdb12a..cbdf378c54b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -117,7 +117,7 @@ SUBDIRS += intel/tools endif if HAVE_VULKAN_COMMON -SUBDIRS += vulkan/wsi +SUBDIRS += vulkan/util vulkan/wsi endif EXTRA_DIST += vulkan/registry/vk.xml diff --git a/src/intel/vulkan/Makefile.am b/src/intel/vulkan/Makefile.am index 93f2ceb00f1..b9b79f44055 100644 --- a/src/intel/vulkan/Makefile.am +++ b/src/intel/vulkan/Makefile.am @@ -49,6 +49,7 @@ AM_CPPFLAGS = \ -I$(top_builddir)/src \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/vulkan/wsi \ + -I$(top_builddir)/src/vulkan/util \ -I$(top_builddir)/src/compiler \ -I$(top_srcdir)/src/compiler \ -I$(top_builddir)/src/compiler/nir \ @@ -126,6 +127,7 @@ libvulkan_common_la_SOURCES = $(VULKAN_SOURCES) VULKAN_LIB_DEPS += \ libvulkan_common.la \ + $(top_builddir)/src/vulkan/util/libvulkan_util.la \ $(top_builddir)/src/vulkan/wsi/libvulkan_wsi.la \ $(top_builddir)/src/mesa/drivers/dri/i965/libi965_compiler.la \ $(top_builddir)/src/compiler/nir/libnir.la \ diff --git a/src/intel/vulkan/anv_util.c b/src/intel/vulkan/anv_util.c index 6d751870654..ec5c9486d8c 100644 --- a/src/intel/vulkan/anv_util.c +++ b/src/intel/vulkan/anv_util.c @@ -29,6 +29,7 @@ #include #include "anv_private.h" +#include "vk_enum_to_str.h" /** Log an error message. */ void anv_printflike(1, 2) @@ -69,40 +70,7 @@ __vk_errorf(VkResult error, const char *file, int line, const char *format, ...) va_list ap; char buffer[256]; -#define ERROR_CASE(error) case error: error_str = #error; break; - - const char *error_str; - switch ((int32_t)error) { - - /* Core errors */ - ERROR_CASE(VK_ERROR_OUT_OF_HOST_MEMORY) - ERROR_CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY) - ERROR_CASE(VK_ERROR_INITIALIZATION_FAILED) - ERROR_CASE(VK_ERROR_DEVICE_LOST) - ERROR_CASE(VK_ERROR_MEMORY_MAP_FAILED) - ERROR_CASE(VK_ERROR_LAYER_NOT_PRESENT) - ERROR_CASE(VK_ERROR_EXTENSION_NOT_PRESENT) - ERROR_CASE(VK_ERROR_FEATURE_NOT_PRESENT) - ERROR_CASE(VK_ERROR_INCOMPATIBLE_DRIVER) - ERROR_CASE(VK_ERROR_TOO_MANY_OBJECTS) - ERROR_CASE(VK_ERROR_FORMAT_NOT_SUPPORTED) - ERROR_CASE(VK_ERROR_FRAGMENTED_POOL) - - /* Extension errors */ - ERROR_CASE(VK_ERROR_SURFACE_LOST_KHR) - ERROR_CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR) - ERROR_CASE(VK_ERROR_OUT_OF_DATE_KHR) - ERROR_CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR) - ERROR_CASE(VK_ERROR_VALIDATION_FAILED_EXT) - ERROR_CASE(VK_ERROR_INVALID_SHADER_NV) - ERROR_CASE(VK_ERROR_OUT_OF_POOL_MEMORY_KHR) - - default: - assert(!"Unknown error"); - error_str = "unknown error"; - } - -#undef ERROR_CASE + const char *error_str = vk_Result_to_str(error); if (format) { va_start(ap, format); diff --git a/src/vulkan/util/.gitignore b/src/vulkan/util/.gitignore new file mode 100644 index 00000000000..5c79217982b --- /dev/null +++ b/src/vulkan/util/.gitignore @@ -0,0 +1 @@ +vk_enum_to_str.* diff --git a/src/vulkan/util/Makefile.am b/src/vulkan/util/Makefile.am new file mode 100644 index 00000000000..87c96d5e5bb --- /dev/null +++ b/src/vulkan/util/Makefile.am @@ -0,0 +1,22 @@ +vulkan_api_xml = $(top_srcdir)/src/vulkan/registry/vk.xml + +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src + +EXTRA_DIST = \ + gen_enum_to_str.py + +BUILT_SOURCES = \ + vk_enum_to_str.c \ + vk_enum_to_str.h + +vk_enum_to_str.c vk_enum_to_str.h: gen_enum_to_str.py $(vulkan_api_xml) + $(AM_V_GEN)$(PYTHON2) $(srcdir)/gen_enum_to_str.py + +noinst_LTLIBRARIES = libvulkan_util.la + +libvulkan_util_la_SOURCES = \ + vk_enum_to_str.c \ + vk_enum_to_str.h + diff --git a/src/vulkan/util/gen_enum_to_str.py b/src/vulkan/util/gen_enum_to_str.py new file mode 100644 index 00000000000..0564b8e0280 --- /dev/null +++ b/src/vulkan/util/gen_enum_to_str.py @@ -0,0 +1,172 @@ +# encoding=utf-8 +# Copyright © 2017 Intel Corporation + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Create enum to string functions for vulking using vk.xml.""" + +from __future__ import print_function +import os +import textwrap +import xml.etree.cElementTree as et + +from mako.template import Template + +VK_XML = os.path.join(os.path.dirname(__file__), '..', 'registry', 'vk.xml') + +COPYRIGHT = textwrap.dedent(u"""\ + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE.""") + +C_TEMPLATE = Template(textwrap.dedent(u"""\ + /* Autogenerated file -- do not edit + * generated by ${file} + * + ${copyright} + */ + + #include + #include "util/macros.h" + #include "vk_enum_to_str.h" + + % for enum in enums: + + const char * + vk_${enum.name[2:]}_to_str(${enum.name} input) + { + switch(input) { + % for v in enum.values: + case ${v}: + return "${v}"; + % endfor + default: + unreachable("Undefined enum value."); + } + } + %endfor"""), + output_encoding='utf-8') + +H_TEMPLATE = Template(textwrap.dedent(u"""\ + /* Autogenerated file -- do not edit + * generated by ${file} + * + ${copyright} + */ + + #ifndef MESA_VK_ENUM_TO_STR_H + #define MESA_VK_ENUM_TO_STR_H + + #include + + % for enum in enums: + const char * vk_${enum.name[2:]}_to_str(${enum.name} input); + % endfor + + #endif"""), + output_encoding='utf-8') + + +class EnumFactory(object): + """Factory for creating enums.""" + + def __init__(self, type_): + self.registry = {} + self.type = type_ + + def __call__(self, name): + try: + return self.registry[name] + except KeyError: + n = self.registry[name] = self.type(name) + return n + + +class VkEnum(object): + """Simple struct-like class representing a single Vulkan Enum.""" + + def __init__(self, name, values=None): + self.name = name + self.values = values or [] + + +def xml_parser(filename): + """Parse the XML file and return parsed data. + + This parser is a memory efficient iterative XML parser that returns a list + of VkEnum objects. + """ + efactory = EnumFactory(VkEnum) + + with open(filename, 'rb') as f: + context = iter(et.iterparse(f, events=('start', 'end'))) + + # This gives the root element, since goal is to iterate over the + # elements without building a tree, this allows the root to be cleared + # (erase the elements) after the children have been processed. + _, root = next(context) + + for event, elem in context: + if event == 'end' and elem.tag == 'enums': + type_ = elem.attrib.get('type') + if type_ == 'enum': + enum = efactory(elem.attrib['name']) + enum.values.extend([e.attrib['name'] for e in elem + if e.tag == 'enum']) + elif event == 'end' and elem.tag == 'extension': + if elem.attrib['supported'] != 'vulkan': + continue + for e in elem.findall('.//enum[@extends][@offset]'): + enum = efactory(e.attrib['extends']) + enum.values.append(e.attrib['name']) + + root.clear() + + return efactory.registry.values() + + +def main(): + enums = xml_parser(VK_XML) + for template, file_ in [(C_TEMPLATE, 'vk_enum_to_str.c'), + (H_TEMPLATE, 'vk_enum_to_str.h')]: + with open(file_, 'wb') as f: + f.write(template.render( + file=os.path.basename(__file__), + enums=enums, + copyright=COPYRIGHT)) + + +if __name__ == '__main__': + main() -- 2.30.2