vulkan/util: generate define for a selected few enums

One of the unfortunate effect of Vulkan starting to use 64bit bitmasks
is that they can no longer be defined using enums because C doesn't
guarantees that enum values will be 64bits.

Vulkan therefore started using those patterns :

  static const VkAccessFlags2KHR VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 0x00000001;

This has the effect that we can not longer use those values in
switch/case statements.

This change introduces defines so that we can keep doing this. For now
only VkAccessFlags2KHR/VkPipelineStageFlags2KHR are allowed to be
redefined this way, this list could be changed later (or all bitmask
could be processed this way).

v2: Generate hexadecimal numbers (Jason)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9045>
This commit is contained in:
Lionel Landwerlin 2020-11-11 15:27:29 +02:00 committed by Marge Bot
parent dbf4cfeff5
commit 9af7506370

View file

@ -178,6 +178,19 @@ H_DEFINE_TEMPLATE = Template(textwrap.dedent(u"""\
#define _${ext.name}_number (${ext.number})
% endfor
% for enum in bitmasks:
/* Redefine bitmask values of ${enum.name} */
% if enum.guard:
#ifdef ${enum.guard}
% endif
% for v in enum.values.keys():
#define ${enum.values[v]} (${hex(v)}ULL)
% endfor
% if enum.guard:
#endif
% endif
% endfor
#ifdef __cplusplus
} /* extern "C" */
#endif
@ -262,6 +275,9 @@ class VkEnum(object):
if 'value' in elem.attrib:
self.add_value(elem.attrib['name'],
value=int(elem.attrib['value'], base=0))
elif 'bitpos' in elem.attrib:
self.add_value(elem.attrib['name'],
value=(1 << int(elem.attrib['bitpos'], base=0)))
elif 'alias' in elem.attrib:
self.add_value(elem.attrib['name'], alias=elem.attrib['alias'])
else:
@ -301,8 +317,8 @@ class VkObjectType(object):
self.enum_to_name = dict()
def parse_xml(enum_factory, ext_factory, struct_factory, obj_type_factory,
filename):
def parse_xml(enum_factory, ext_factory, struct_factory, bitmask_factory,
obj_type_factory, filename):
"""Parse the XML file. Accumulate results into the factories.
This parser is a memory efficient iterative XML parser that returns a list
@ -316,8 +332,19 @@ def parse_xml(enum_factory, ext_factory, struct_factory, obj_type_factory,
for value in enum_type.findall('./enum'):
enum.add_value_from_xml(value)
# For bitmask we only add the Enum selected for convenience.
for enum_type in xml.findall('./enums[@type="bitmask"]'):
enum = bitmask_factory.get(enum_type.attrib['name'])
if enum is not None:
for value in enum_type.findall('./enum'):
enum.add_value_from_xml(value)
for value in xml.findall('./feature/require/enum[@extends]'):
enum = enum_factory.get(value.attrib['extends'])
extends = value.attrib['extends']
enum = enum_factory.get(extends)
if enum is not None:
enum.add_value_from_xml(value)
enum = bitmask_factory.get(extends)
if enum is not None:
enum.add_value_from_xml(value)
@ -342,7 +369,11 @@ def parse_xml(enum_factory, ext_factory, struct_factory, obj_type_factory,
define=define)
for value in ext_elem.findall('./require/enum[@extends]'):
enum = enum_factory.get(value.attrib['extends'])
extends = value.attrib['extends']
enum = enum_factory.get(extends)
if enum is not None:
enum.add_value_from_xml(value, extension)
enum = bitmask_factory.get(extends)
if enum is not None:
enum.add_value_from_xml(value, extension)
for t in ext_elem.findall('./require/type'):
@ -381,12 +412,19 @@ def main():
ext_factory = NamedFactory(VkExtension)
struct_factory = NamedFactory(VkChainStruct)
obj_type_factory = NamedFactory(VkObjectType)
# Only treat this bitmask for now
bitmask_factory = NamedFactory(VkEnum)
bitmask_factory('VkAccessFlagBits2KHR')
bitmask_factory('VkPipelineStageFlagBits2KHR')
for filename in args.xml_files:
parse_xml(enum_factory, ext_factory, struct_factory, obj_type_factory,
filename)
parse_xml(enum_factory, ext_factory, struct_factory, bitmask_factory,
obj_type_factory, filename)
enums = sorted(enum_factory.registry.values(), key=lambda e: e.name)
extensions = sorted(ext_factory.registry.values(), key=lambda e: e.name)
structs = sorted(struct_factory.registry.values(), key=lambda e: e.name)
bitmasks = sorted(bitmask_factory.registry.values(), key=lambda e: e.name)
object_types = sorted(obj_type_factory.registry.values(), key=lambda e: e.name)
for template, file_ in [(C_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.c')),
@ -398,6 +436,7 @@ def main():
enums=enums,
extensions=extensions,
structs=structs,
bitmasks=bitmasks,
object_types=object_types,
copyright=COPYRIGHT))