Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_extensions.py
4570 views
# Copyright © 2020 Hoe Hao Cheng1#2# Permission is hereby granted, free of charge, to any person obtaining a3# copy of this software and associated documentation files (the "Software"),4# to deal in the Software without restriction, including without limitation5# the rights to use, copy, modify, merge, publish, distribute, sublicense,6# and/or sell copies of the Software, and to permit persons to whom the7# Software is furnished to do so, subject to the following conditions:8#9# The above copyright notice and this permission notice (including the next10# paragraph) shall be included in all copies or substantial portions of the11# Software.12#13# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING18# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS19# IN THE SOFTWARE.20#2122import re23from xml.etree import ElementTree24from typing import List,Tuple2526class Version:27device_version = (1,0,0)28struct_version = (1,0)2930def __init__(self, version, struct=()):31self.device_version = version3233if not struct:34self.struct_version = (version[0], version[1])35else:36self.struct_version = struct3738# e.g. "VK_MAKE_VERSION(1,2,0)"39def version(self):40return ("VK_MAKE_VERSION("41+ str(self.device_version[0])42+ ","43+ str(self.device_version[1])44+ ","45+ str(self.device_version[2])46+ ")")4748# e.g. "10"49def struct(self):50return (str(self.struct_version[0])+str(self.struct_version[1]))5152# the sType of the extension's struct53# e.g. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT54# for VK_EXT_transform_feedback and struct="FEATURES"55def stype(self, struct: str):56return ("VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_"57+ str(self.struct_version[0]) + "_" + str(self.struct_version[1])58+ '_' + struct)5960class Extension:61name = None62alias = None63is_required = False64is_nonstandard = False65enable_conds = None66core_since = None6768# these are specific to zink_device_info.py:69has_properties = False70has_features = False71guard = False7273def __init__(self, name, alias="", required=False, nonstandard=False,74properties=False, features=False, conditions=None, guard=False,75core_since=None):76self.name = name77self.alias = alias78self.is_required = required79self.is_nonstandard = nonstandard80self.has_properties = properties81self.has_features = features82self.enable_conds = conditions83self.guard = guard84self.core_since = core_since8586if alias == "" and (properties == True or features == True):87raise RuntimeError("alias must be available when properties and/or features are used")8889# e.g.: "VK_EXT_robustness2" -> "robustness2"90def pure_name(self):91return '_'.join(self.name.split('_')[2:])9293# e.g.: "VK_EXT_robustness2" -> "EXT_robustness2"94def name_with_vendor(self):95return self.name[3:]9697# e.g.: "VK_EXT_robustness2" -> "Robustness2"98def name_in_camel_case(self):99return "".join([x.title() for x in self.name.split('_')[2:]])100101# e.g.: "VK_EXT_robustness2" -> "VK_EXT_ROBUSTNESS2_EXTENSION_NAME"102# do note that inconsistencies exist, i.e. we have103# VK_EXT_ROBUSTNESS_2_EXTENSION_NAME defined in the headers, but then104# we also have VK_KHR_MAINTENANCE1_EXTENSION_NAME105def extension_name(self):106return self.name.upper() + "_EXTENSION_NAME"107108# generate a C string literal for the extension109def extension_name_literal(self):110return '"' + self.name + '"'111112# get the field in zink_device_info that refers to the extension's113# feature/properties struct114# e.g. rb2_<suffix> for VK_EXT_robustness2115def field(self, suffix: str):116return self.alias + '_' + suffix117118def physical_device_struct(self, struct: str):119if self.name_in_camel_case().endswith(struct):120struct = ""121122return ("VkPhysicalDevice"123+ self.name_in_camel_case()124+ struct125+ self.vendor())126127# the sType of the extension's struct128# e.g. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT129# for VK_EXT_transform_feedback and struct="FEATURES"130def stype(self, struct: str):131return ("VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_"132+ self.pure_name().upper()133+ '_' + struct + '_'134+ self.vendor())135136# e.g. EXT in VK_EXT_robustness2137def vendor(self):138return self.name.split('_')[1]139140# Type aliases141Layer = Extension142143class ExtensionRegistryEntry:144# type of extension - right now it's either "instance" or "device"145ext_type = ""146# the version in which the extension is promoted to core VK147promoted_in = None148# functions added by the extension are referred to as "commands" in the registry149device_commands = None150pdevice_commands = None151instance_commands = None152constants = None153features_struct = None154properties_struct = None155156class ExtensionRegistry:157# key = extension name, value = registry entry158registry = dict()159160def __init__(self, vkxml_path: str):161vkxml = ElementTree.parse(vkxml_path)162163commands_type = dict()164aliases = dict()165166for cmd in vkxml.findall("commands/command"):167name = cmd.find("./proto/name")168169if name is not None and name.text:170commands_type[name.text] = cmd.find("./param/type").text171elif cmd.get("name") is not None:172aliases[cmd.get("name")] = cmd.get("alias")173174for (cmd, alias) in aliases.items():175commands_type[cmd] = commands_type[alias]176177for ext in vkxml.findall("extensions/extension"):178# Reserved extensions are marked with `supported="disabled"`179if ext.get("supported") == "disabled":180continue181182name = ext.attrib["name"]183184entry = ExtensionRegistryEntry()185entry.ext_type = ext.attrib["type"]186entry.promoted_in = self.parse_promotedto(ext.get("promotedto"))187188entry.device_commands = []189entry.pdevice_commands = []190entry.instance_commands = []191192for cmd in ext.findall("require/command"):193cmd_name = cmd.get("name")194if cmd_name:195if commands_type[cmd_name] in ("VkDevice", "VkCommandBuffer", "VkQueue"):196entry.device_commands.append(cmd_name)197elif commands_type[cmd_name] in ("VkPhysicalDevice"):198entry.pdevice_commands.append(cmd_name)199else:200entry.instance_commands.append(cmd_name)201202entry.constants = []203for enum in ext.findall("require/enum"):204enum_name = enum.get("name")205enum_extends = enum.get("extends")206# we are only interested in VK_*_EXTENSION_NAME, which does not207# have an "extends" attribute208if not enum_extends:209entry.constants.append(enum_name)210211for ty in ext.findall("require/type"):212ty_name = ty.get("name")213if (self.is_features_struct(ty_name) and214entry.features_struct is None):215entry.features_struct = ty_name216elif (self.is_properties_struct(ty_name) and217entry.properties_struct is None):218entry.properties_struct = ty_name219220self.registry[name] = entry221222def in_registry(self, ext_name: str):223return ext_name in self.registry224225def get_registry_entry(self, ext_name: str):226if self.in_registry(ext_name):227return self.registry[ext_name]228229# Parses e.g. "VK_VERSION_x_y" to integer tuple (x, y)230# For any erroneous inputs, None is returned231def parse_promotedto(self, promotedto: str):232result = None233234if promotedto and promotedto.startswith("VK_VERSION_"):235(major, minor) = promotedto.split('_')[-2:]236result = (int(major), int(minor))237238return result239240def is_features_struct(self, struct: str):241return re.match(r"VkPhysicalDevice.*Features.*", struct) is not None242243def is_properties_struct(self, struct: str):244return re.match(r"VkPhysicalDevice.*Properties.*", struct) is not None245246247