Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_instance.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
# Authors:
23
# Hoe Hao Cheng <[email protected]>
24
#
25
26
from mako.template import Template
27
from os import path
28
from xml.etree import ElementTree
29
from zink_extensions import Extension,Layer,ExtensionRegistry,Version
30
import sys
31
32
# constructor: Extension(name, conditions=[], nonstandard=False)
33
# The attributes:
34
# - conditions: If the extension is provided by the Vulkan implementation, then
35
# these are the extra conditions needed to enable the extension.
36
# - nonstandard: Disables validation (cross-checking with vk.xml) if True.
37
EXTENSIONS = [
38
Extension("VK_EXT_debug_utils"),
39
Extension("VK_KHR_get_physical_device_properties2"),
40
Extension("VK_MVK_moltenvk",
41
nonstandard=True),
42
Extension("VK_KHR_surface"),
43
]
44
45
# constructor: Layer(name, conditions=[])
46
# - conditions: See documentation of EXTENSIONS.
47
LAYERS = [
48
# if we have debug_util, allow a validation layer to be added.
49
Layer("VK_LAYER_KHRONOS_validation",
50
conditions=["zink_debug & ZINK_DEBUG_VALIDATION"]),
51
Layer("VK_LAYER_LUNARG_standard_validation",
52
conditions=["zink_debug & ZINK_DEBUG_VALIDATION", "!have_layer_KHRONOS_validation"]),
53
]
54
55
REPLACEMENTS = {
56
"VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_EXTENSION_NAME" : "VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME"
57
}
58
59
header_code = """
60
#ifndef ZINK_INSTANCE_H
61
#define ZINK_INSTANCE_H
62
63
#include "os/os_process.h"
64
65
#include <vulkan/vulkan.h>
66
67
#if defined(__APPLE__)
68
// Source of MVK_VERSION
69
#include "MoltenVK/vk_mvk_moltenvk.h"
70
#endif
71
72
struct zink_screen;
73
74
struct zink_instance_info {
75
uint32_t loader_version;
76
77
%for ext in extensions:
78
bool have_${ext.name_with_vendor()};
79
%endfor
80
81
%for layer in layers:
82
bool have_layer_${layer.pure_name()};
83
%endfor
84
};
85
86
VkInstance
87
zink_create_instance(struct zink_instance_info *instance_info);
88
89
void
90
zink_verify_instance_extensions(struct zink_screen *screen);
91
92
/* stub functions that get inserted into the dispatch table if they are not
93
* properly loaded.
94
*/
95
%for ext in extensions:
96
%if registry.in_registry(ext.name):
97
%for cmd in registry.get_registry_entry(ext.name).instance_commands:
98
void zink_stub_${cmd.lstrip("vk")}(void);
99
%endfor
100
%for cmd in registry.get_registry_entry(ext.name).pdevice_commands:
101
void zink_stub_${cmd.lstrip("vk")}(void);
102
%endfor
103
%endif
104
%endfor
105
106
#endif
107
"""
108
109
impl_code = """
110
#include "zink_instance.h"
111
#include "zink_screen.h"
112
113
VkInstance
114
zink_create_instance(struct zink_instance_info *instance_info)
115
{
116
/* reserve one slot for MoltenVK */
117
const char *layers[${len(layers) + 1}] = {0};
118
uint32_t num_layers = 0;
119
120
const char *extensions[${len(extensions) + 1}] = {0};
121
uint32_t num_extensions = 0;
122
123
%for ext in extensions:
124
bool have_${ext.name_with_vendor()} = false;
125
%endfor
126
127
%for layer in layers:
128
bool have_layer_${layer.pure_name()} = false;
129
%endfor
130
131
#if defined(MVK_VERSION)
132
bool have_moltenvk_layer = false;
133
#endif
134
135
// Build up the extensions from the reported ones but only for the unnamed layer
136
uint32_t extension_count = 0;
137
if (vkEnumerateInstanceExtensionProperties(NULL, &extension_count, NULL) == VK_SUCCESS) {
138
VkExtensionProperties *extension_props = malloc(extension_count * sizeof(VkExtensionProperties));
139
if (extension_props) {
140
if (vkEnumerateInstanceExtensionProperties(NULL, &extension_count, extension_props) == VK_SUCCESS) {
141
for (uint32_t i = 0; i < extension_count; i++) {
142
%for ext in extensions:
143
if (!strcmp(extension_props[i].extensionName, ${ext.extension_name_literal()})) {
144
have_${ext.name_with_vendor()} = true;
145
}
146
%endfor
147
}
148
}
149
free(extension_props);
150
}
151
}
152
153
// Build up the layers from the reported ones
154
uint32_t layer_count = 0;
155
156
if (vkEnumerateInstanceLayerProperties(&layer_count, NULL) == VK_SUCCESS) {
157
VkLayerProperties *layer_props = malloc(layer_count * sizeof(VkLayerProperties));
158
if (layer_props) {
159
if (vkEnumerateInstanceLayerProperties(&layer_count, layer_props) == VK_SUCCESS) {
160
for (uint32_t i = 0; i < layer_count; i++) {
161
%for layer in layers:
162
if (!strcmp(layer_props[i].layerName, ${layer.extension_name_literal()})) {
163
have_layer_${layer.pure_name()} = true;
164
}
165
%endfor
166
#if defined(MVK_VERSION)
167
if (!strcmp(layer_props[i].layerName, "MoltenVK")) {
168
have_moltenvk_layer = true;
169
layers[num_layers++] = "MoltenVK";
170
}
171
#endif
172
}
173
}
174
free(layer_props);
175
}
176
}
177
178
%for ext in extensions:
179
<%
180
conditions = ""
181
if ext.enable_conds:
182
for cond in ext.enable_conds:
183
conditions += "&& (" + cond + ") "
184
conditions = conditions.strip()
185
%>\
186
if (have_${ext.name_with_vendor()} ${conditions}) {
187
instance_info->have_${ext.name_with_vendor()} = have_${ext.name_with_vendor()};
188
extensions[num_extensions++] = ${ext.extension_name_literal()};
189
}
190
%endfor
191
192
%for layer in layers:
193
<%
194
conditions = ""
195
if layer.enable_conds:
196
for cond in layer.enable_conds:
197
conditions += "&& (" + cond + ") "
198
conditions = conditions.strip()
199
%>\
200
if (have_layer_${layer.pure_name()} ${conditions}) {
201
layers[num_layers++] = ${layer.extension_name_literal()};
202
instance_info->have_layer_${layer.pure_name()} = true;
203
}
204
%endfor
205
206
VkApplicationInfo ai = {0};
207
ai.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
208
209
char proc_name[128];
210
if (os_get_process_name(proc_name, ARRAY_SIZE(proc_name)))
211
ai.pApplicationName = proc_name;
212
else
213
ai.pApplicationName = "unknown";
214
215
ai.pEngineName = "mesa zink";
216
ai.apiVersion = instance_info->loader_version;
217
218
VkInstanceCreateInfo ici = {0};
219
ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
220
ici.pApplicationInfo = &ai;
221
ici.ppEnabledExtensionNames = extensions;
222
ici.enabledExtensionCount = num_extensions;
223
ici.ppEnabledLayerNames = layers;
224
ici.enabledLayerCount = num_layers;
225
226
VkInstance instance = VK_NULL_HANDLE;
227
VkResult err = vkCreateInstance(&ici, NULL, &instance);
228
if (err != VK_SUCCESS)
229
return VK_NULL_HANDLE;
230
231
return instance;
232
}
233
234
void
235
zink_verify_instance_extensions(struct zink_screen *screen)
236
{
237
%for ext in extensions:
238
%if registry.in_registry(ext.name):
239
if (screen->instance_info.have_${ext.name_with_vendor()}) {
240
%for cmd in registry.get_registry_entry(ext.name).instance_commands:
241
if (!screen->vk.${cmd.lstrip("vk")}) {
242
#ifndef NDEBUG
243
screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_${cmd.lstrip("vk")};
244
#else
245
screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_function_not_loaded;
246
#endif
247
}
248
%endfor
249
%for cmd in registry.get_registry_entry(ext.name).pdevice_commands:
250
if (!screen->vk.${cmd.lstrip("vk")}) {
251
#ifndef NDEBUG
252
screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_${cmd.lstrip("vk")};
253
#else
254
screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_function_not_loaded;
255
#endif
256
}
257
%endfor
258
}
259
%endif
260
%endfor
261
}
262
263
#ifndef NDEBUG
264
/* generated stub functions */
265
## see zink_device_info.py for why this is needed
266
<% generated_funcs = set() %>
267
268
%for ext in extensions:
269
%if registry.in_registry(ext.name):
270
%for cmd in registry.get_registry_entry(ext.name).instance_commands + registry.get_registry_entry(ext.name).pdevice_commands:
271
%if cmd in generated_funcs:
272
<% continue %>
273
%else:
274
<% generated_funcs.add(cmd) %>
275
%endif
276
void
277
zink_stub_${cmd.lstrip("vk")}()
278
{
279
mesa_loge("ZINK: ${cmd} is not loaded properly!");
280
abort();
281
}
282
%endfor
283
%endif
284
%endfor
285
286
#endif
287
"""
288
289
290
def replace_code(code: str, replacement: dict):
291
for (k, v) in replacement.items():
292
code = code.replace(k, v)
293
294
return code
295
296
297
if __name__ == "__main__":
298
try:
299
header_path = sys.argv[1]
300
impl_path = sys.argv[2]
301
vkxml_path = sys.argv[3]
302
303
header_path = path.abspath(header_path)
304
impl_path = path.abspath(impl_path)
305
vkxml_path = path.abspath(vkxml_path)
306
except:
307
print("usage: %s <path to .h> <path to .c> <path to vk.xml>" % sys.argv[0])
308
exit(1)
309
310
registry = ExtensionRegistry(vkxml_path)
311
312
extensions = EXTENSIONS
313
layers = LAYERS
314
replacement = REPLACEMENTS
315
316
# Perform extension validation and set core_since for the extension if available
317
error_count = 0
318
for ext in extensions:
319
if not registry.in_registry(ext.name):
320
# disable validation for nonstandard extensions
321
if ext.is_nonstandard:
322
continue
323
324
error_count += 1
325
print("The extension {} is not registered in vk.xml - a typo?".format(ext.name))
326
continue
327
328
entry = registry.get_registry_entry(ext.name)
329
330
if entry.ext_type != "instance":
331
error_count += 1
332
print("The extension {} is {} extension - expected an instance extension.".format(ext.name, entry.ext_type))
333
continue
334
335
if entry.promoted_in:
336
ext.core_since = Version((*entry.promoted_in, 0))
337
338
if error_count > 0:
339
print("zink_instance.py: Found {} error(s) in total. Quitting.".format(error_count))
340
exit(1)
341
342
with open(header_path, "w") as header_file:
343
header = Template(header_code).render(extensions=extensions, layers=layers, registry=registry).strip()
344
header = replace_code(header, replacement)
345
print(header, file=header_file)
346
347
with open(impl_path, "w") as impl_file:
348
impl = Template(impl_code).render(extensions=extensions, layers=layers, registry=registry).strip()
349
impl = replace_code(impl, replacement)
350
print(impl, file=impl_file)
351
352