~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/drivers/zink/zink_extensions.py

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright © 2020 Hoe Hao Cheng
2
 
#
3
 
# Permission is hereby granted, free of charge, to any person obtaining a
4
 
# copy of this software and associated documentation files (the "Software"),
5
 
# to deal in the Software without restriction, including without limitation
6
 
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
7
 
# and/or sell copies of the Software, and to permit persons to whom the
8
 
# Software is furnished to do so, subject to the following conditions:
9
 
#
10
 
# The above copyright notice and this permission notice (including the next
11
 
# paragraph) shall be included in all copies or substantial portions of the
12
 
# Software.
13
 
#
14
 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17
 
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
 
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
 
# IN THE SOFTWARE.
21
 
22
 
 
23
 
import re
24
 
from xml.etree import ElementTree
25
 
from typing import List,Tuple
26
 
 
27
 
class Version:
28
 
    device_version = (1,0,0)
29
 
    struct_version = (1,0)
30
 
 
31
 
    def __init__(self, version, struct=()):
32
 
        self.device_version = version
33
 
 
34
 
        if not struct:
35
 
            self.struct_version = (version[0], version[1])
36
 
        else:
37
 
            self.struct_version = struct
38
 
 
39
 
    # e.g. "VK_MAKE_VERSION(1,2,0)"
40
 
    def version(self):
41
 
        return ("VK_MAKE_VERSION("
42
 
               + str(self.device_version[0])
43
 
               + ","
44
 
               + str(self.device_version[1])
45
 
               + ","
46
 
               + str(self.device_version[2])
47
 
               + ")")
48
 
 
49
 
    # e.g. "10"
50
 
    def struct(self):
51
 
        return (str(self.struct_version[0])+str(self.struct_version[1]))
52
 
 
53
 
    # the sType of the extension's struct
54
 
    # e.g. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT
55
 
    # for VK_EXT_transform_feedback and struct="FEATURES"
56
 
    def stype(self, struct: str):
57
 
        return ("VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_"
58
 
                + str(self.struct_version[0]) + "_" + str(self.struct_version[1])
59
 
                + '_' + struct)
60
 
 
61
 
class Extension:
62
 
    name           = None
63
 
    alias          = None
64
 
    is_required    = False
65
 
    is_nonstandard = False
66
 
    enable_conds   = None
67
 
    core_since     = None
68
 
 
69
 
    # these are specific to zink_device_info.py:
70
 
    has_properties = False
71
 
    has_features   = False
72
 
    guard          = False
73
 
 
74
 
    # these are specific to zink_instance.py:
75
 
    platform_guard = None
76
 
 
77
 
    def __init__(self, name, alias="", required=False, nonstandard=False,
78
 
                 properties=False, features=False, conditions=None, guard=False):
79
 
        self.name = name
80
 
        self.alias = alias
81
 
        self.is_required = required
82
 
        self.is_nonstandard = nonstandard
83
 
        self.has_properties = properties
84
 
        self.has_features = features
85
 
        self.enable_conds = conditions
86
 
        self.guard = guard
87
 
 
88
 
        if alias == "" and (properties == True or features == True):
89
 
            raise RuntimeError("alias must be available when properties and/or features are used")
90
 
 
91
 
    # e.g.: "VK_EXT_robustness2" -> "robustness2"
92
 
    def pure_name(self):
93
 
        return '_'.join(self.name.split('_')[2:])
94
 
    
95
 
    # e.g.: "VK_EXT_robustness2" -> "EXT_robustness2"
96
 
    def name_with_vendor(self):
97
 
        return self.name[3:]
98
 
    
99
 
    # e.g.: "VK_EXT_robustness2" -> "Robustness2"
100
 
    def name_in_camel_case(self):
101
 
        return "".join([x.title() for x in self.name.split('_')[2:]])
102
 
    
103
 
    # e.g.: "VK_EXT_robustness2" -> "VK_EXT_ROBUSTNESS2_EXTENSION_NAME"
104
 
    # do note that inconsistencies exist, i.e. we have
105
 
    # VK_EXT_ROBUSTNESS_2_EXTENSION_NAME defined in the headers, but then
106
 
    # we also have VK_KHR_MAINTENANCE1_EXTENSION_NAME
107
 
    def extension_name(self):
108
 
        return self.name.upper() + "_EXTENSION_NAME"
109
 
 
110
 
    # generate a C string literal for the extension
111
 
    def extension_name_literal(self):
112
 
        return '"' + self.name + '"'
113
 
 
114
 
    # get the field in zink_device_info that refers to the extension's
115
 
    # feature/properties struct
116
 
    # e.g. rb2_<suffix> for VK_EXT_robustness2
117
 
    def field(self, suffix: str):
118
 
        return self.alias + '_' + suffix
119
 
 
120
 
    def physical_device_struct(self, struct: str):
121
 
        if self.name_in_camel_case().endswith(struct):
122
 
            struct = ""
123
 
 
124
 
        return ("VkPhysicalDevice"
125
 
                + self.name_in_camel_case()
126
 
                + struct
127
 
                + self.vendor())
128
 
 
129
 
    # the sType of the extension's struct
130
 
    # e.g. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT
131
 
    # for VK_EXT_transform_feedback and struct="FEATURES"
132
 
    def stype(self, struct: str):
133
 
        return ("VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_" 
134
 
                + self.pure_name().upper()
135
 
                + '_' + struct + '_' 
136
 
                + self.vendor())
137
 
 
138
 
    # e.g. EXT in VK_EXT_robustness2
139
 
    def vendor(self):
140
 
        return self.name.split('_')[1]
141
 
 
142
 
# Type aliases
143
 
Layer = Extension
144
 
 
145
 
class ExtensionRegistryEntry:
146
 
    # type of extension - right now it's either "instance" or "device"
147
 
    ext_type          = ""
148
 
    # the version in which the extension is promoted to core VK
149
 
    promoted_in       = None
150
 
    # functions added by the extension are referred to as "commands" in the registry
151
 
    device_commands   = None
152
 
    pdevice_commands  = None
153
 
    instance_commands = None
154
 
    constants         = None
155
 
    features_struct   = None
156
 
    properties_struct = None
157
 
    # some instance extensions are locked behind certain platforms
158
 
    platform_guard    = ""
159
 
 
160
 
class ExtensionRegistry:
161
 
    # key = extension name, value = registry entry
162
 
    registry = dict()
163
 
 
164
 
    def __init__(self, vkxml_path: str):
165
 
        vkxml = ElementTree.parse(vkxml_path)
166
 
 
167
 
        commands_type = dict()
168
 
        aliases = dict()
169
 
        platform_guards = dict()
170
 
 
171
 
        for cmd in vkxml.findall("commands/command"):
172
 
            name = cmd.find("./proto/name")
173
 
 
174
 
            if name is not None and name.text:
175
 
                commands_type[name.text] = cmd.find("./param/type").text
176
 
            elif cmd.get("name") is not None:
177
 
                aliases[cmd.get("name")] = cmd.get("alias")
178
 
 
179
 
        for (cmd, alias) in aliases.items():
180
 
            commands_type[cmd] = commands_type[alias]
181
 
 
182
 
        for platform in vkxml.findall("platforms/platform"):
183
 
            name = platform.get("name")
184
 
            guard = platform.get("protect")
185
 
            platform_guards[name] = guard
186
 
 
187
 
        for ext in vkxml.findall("extensions/extension"):
188
 
            # Reserved extensions are marked with `supported="disabled"`
189
 
            if ext.get("supported") == "disabled":
190
 
                continue
191
 
 
192
 
            name = ext.attrib["name"]
193
 
 
194
 
            entry = ExtensionRegistryEntry()
195
 
            entry.ext_type = ext.attrib["type"]
196
 
            entry.promoted_in = self.parse_promotedto(ext.get("promotedto"))
197
 
 
198
 
            entry.device_commands = []
199
 
            entry.pdevice_commands = []
200
 
            entry.instance_commands = []
201
 
 
202
 
            for cmd in ext.findall("require/command"):
203
 
                cmd_name = cmd.get("name")
204
 
                if cmd_name:
205
 
                    if commands_type[cmd_name] in ("VkDevice", "VkCommandBuffer", "VkQueue"):
206
 
                        entry.device_commands.append(cmd_name)
207
 
                    elif commands_type[cmd_name] in ("VkPhysicalDevice"):
208
 
                        entry.pdevice_commands.append(cmd_name)
209
 
                    else:
210
 
                        entry.instance_commands.append(cmd_name)
211
 
 
212
 
            entry.constants = []
213
 
            for enum in ext.findall("require/enum"):
214
 
                enum_name = enum.get("name")
215
 
                enum_extends = enum.get("extends")
216
 
                # we are only interested in VK_*_EXTENSION_NAME, which does not
217
 
                # have an "extends" attribute
218
 
                if not enum_extends:
219
 
                    entry.constants.append(enum_name)
220
 
 
221
 
            for ty in ext.findall("require/type"):
222
 
                ty_name = ty.get("name")
223
 
                if (self.is_features_struct(ty_name) and
224
 
                    entry.features_struct is None):
225
 
                    entry.features_struct = ty_name
226
 
                elif (self.is_properties_struct(ty_name) and
227
 
                      entry.properties_struct is None):
228
 
                    entry.properties_struct = ty_name
229
 
 
230
 
            if ext.get("platform") is not None:
231
 
                entry.platform_guard = platform_guards[ext.get("platform")]
232
 
 
233
 
            self.registry[name] = entry
234
 
 
235
 
    def in_registry(self, ext_name: str):
236
 
        return ext_name in self.registry
237
 
 
238
 
    def get_registry_entry(self, ext_name: str):
239
 
        if self.in_registry(ext_name):
240
 
            return self.registry[ext_name]
241
 
 
242
 
    # Parses e.g. "VK_VERSION_x_y" to integer tuple (x, y)
243
 
    # For any erroneous inputs, None is returned
244
 
    def parse_promotedto(self, promotedto: str):
245
 
        result = None
246
 
 
247
 
        if promotedto and promotedto.startswith("VK_VERSION_"):
248
 
            (major, minor) = promotedto.split('_')[-2:]
249
 
            result = (int(major), int(minor))
250
 
 
251
 
        return result
252
 
 
253
 
    def is_features_struct(self, struct: str):
254
 
        return re.match(r"VkPhysicalDevice.*Features.*", struct) is not None
255
 
 
256
 
    def is_properties_struct(self, struct: str):
257
 
        return re.match(r"VkPhysicalDevice.*Properties.*", struct) is not None