Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_extensions.py
4570 views
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
def __init__(self, name, alias="", required=False, nonstandard=False,
75
properties=False, features=False, conditions=None, guard=False,
76
core_since=None):
77
self.name = name
78
self.alias = alias
79
self.is_required = required
80
self.is_nonstandard = nonstandard
81
self.has_properties = properties
82
self.has_features = features
83
self.enable_conds = conditions
84
self.guard = guard
85
self.core_since = core_since
86
87
if alias == "" and (properties == True or features == True):
88
raise RuntimeError("alias must be available when properties and/or features are used")
89
90
# e.g.: "VK_EXT_robustness2" -> "robustness2"
91
def pure_name(self):
92
return '_'.join(self.name.split('_')[2:])
93
94
# e.g.: "VK_EXT_robustness2" -> "EXT_robustness2"
95
def name_with_vendor(self):
96
return self.name[3:]
97
98
# e.g.: "VK_EXT_robustness2" -> "Robustness2"
99
def name_in_camel_case(self):
100
return "".join([x.title() for x in self.name.split('_')[2:]])
101
102
# e.g.: "VK_EXT_robustness2" -> "VK_EXT_ROBUSTNESS2_EXTENSION_NAME"
103
# do note that inconsistencies exist, i.e. we have
104
# VK_EXT_ROBUSTNESS_2_EXTENSION_NAME defined in the headers, but then
105
# we also have VK_KHR_MAINTENANCE1_EXTENSION_NAME
106
def extension_name(self):
107
return self.name.upper() + "_EXTENSION_NAME"
108
109
# generate a C string literal for the extension
110
def extension_name_literal(self):
111
return '"' + self.name + '"'
112
113
# get the field in zink_device_info that refers to the extension's
114
# feature/properties struct
115
# e.g. rb2_<suffix> for VK_EXT_robustness2
116
def field(self, suffix: str):
117
return self.alias + '_' + suffix
118
119
def physical_device_struct(self, struct: str):
120
if self.name_in_camel_case().endswith(struct):
121
struct = ""
122
123
return ("VkPhysicalDevice"
124
+ self.name_in_camel_case()
125
+ struct
126
+ self.vendor())
127
128
# the sType of the extension's struct
129
# e.g. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT
130
# for VK_EXT_transform_feedback and struct="FEATURES"
131
def stype(self, struct: str):
132
return ("VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_"
133
+ self.pure_name().upper()
134
+ '_' + struct + '_'
135
+ self.vendor())
136
137
# e.g. EXT in VK_EXT_robustness2
138
def vendor(self):
139
return self.name.split('_')[1]
140
141
# Type aliases
142
Layer = Extension
143
144
class ExtensionRegistryEntry:
145
# type of extension - right now it's either "instance" or "device"
146
ext_type = ""
147
# the version in which the extension is promoted to core VK
148
promoted_in = None
149
# functions added by the extension are referred to as "commands" in the registry
150
device_commands = None
151
pdevice_commands = None
152
instance_commands = None
153
constants = None
154
features_struct = None
155
properties_struct = None
156
157
class ExtensionRegistry:
158
# key = extension name, value = registry entry
159
registry = dict()
160
161
def __init__(self, vkxml_path: str):
162
vkxml = ElementTree.parse(vkxml_path)
163
164
commands_type = dict()
165
aliases = dict()
166
167
for cmd in vkxml.findall("commands/command"):
168
name = cmd.find("./proto/name")
169
170
if name is not None and name.text:
171
commands_type[name.text] = cmd.find("./param/type").text
172
elif cmd.get("name") is not None:
173
aliases[cmd.get("name")] = cmd.get("alias")
174
175
for (cmd, alias) in aliases.items():
176
commands_type[cmd] = commands_type[alias]
177
178
for ext in vkxml.findall("extensions/extension"):
179
# Reserved extensions are marked with `supported="disabled"`
180
if ext.get("supported") == "disabled":
181
continue
182
183
name = ext.attrib["name"]
184
185
entry = ExtensionRegistryEntry()
186
entry.ext_type = ext.attrib["type"]
187
entry.promoted_in = self.parse_promotedto(ext.get("promotedto"))
188
189
entry.device_commands = []
190
entry.pdevice_commands = []
191
entry.instance_commands = []
192
193
for cmd in ext.findall("require/command"):
194
cmd_name = cmd.get("name")
195
if cmd_name:
196
if commands_type[cmd_name] in ("VkDevice", "VkCommandBuffer", "VkQueue"):
197
entry.device_commands.append(cmd_name)
198
elif commands_type[cmd_name] in ("VkPhysicalDevice"):
199
entry.pdevice_commands.append(cmd_name)
200
else:
201
entry.instance_commands.append(cmd_name)
202
203
entry.constants = []
204
for enum in ext.findall("require/enum"):
205
enum_name = enum.get("name")
206
enum_extends = enum.get("extends")
207
# we are only interested in VK_*_EXTENSION_NAME, which does not
208
# have an "extends" attribute
209
if not enum_extends:
210
entry.constants.append(enum_name)
211
212
for ty in ext.findall("require/type"):
213
ty_name = ty.get("name")
214
if (self.is_features_struct(ty_name) and
215
entry.features_struct is None):
216
entry.features_struct = ty_name
217
elif (self.is_properties_struct(ty_name) and
218
entry.properties_struct is None):
219
entry.properties_struct = ty_name
220
221
self.registry[name] = entry
222
223
def in_registry(self, ext_name: str):
224
return ext_name in self.registry
225
226
def get_registry_entry(self, ext_name: str):
227
if self.in_registry(ext_name):
228
return self.registry[ext_name]
229
230
# Parses e.g. "VK_VERSION_x_y" to integer tuple (x, y)
231
# For any erroneous inputs, None is returned
232
def parse_promotedto(self, promotedto: str):
233
result = None
234
235
if promotedto and promotedto.startswith("VK_VERSION_"):
236
(major, minor) = promotedto.split('_')[-2:]
237
result = (int(major), int(minor))
238
239
return result
240
241
def is_features_struct(self, struct: str):
242
return re.match(r"VkPhysicalDevice.*Features.*", struct) is not None
243
244
def is_properties_struct(self, struct: str):
245
return re.match(r"VkPhysicalDevice.*Properties.*", struct) is not None
246
247