blob: 04d9f239e7bab230e20d4589cb8bd6348fd351d7 [file] [log] [blame]
Adithya Srinivasan01364142019-07-02 15:52:49 -07001#!/usr/bin/env python3
2#
3# Copyright 2019 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17# This script provides the functions for generating the
18# vulkan driver framework directly from the vulkan registry (vk.xml).
19
20import generator_common as gencom
21import os
22
23interceptedExtensions = [
24 'VK_ANDROID_native_buffer',
25 'VK_EXT_debug_report',
26 'VK_EXT_hdr_metadata',
27 'VK_EXT_swapchain_colorspace',
28 'VK_GOOGLE_display_timing',
29 'VK_KHR_android_surface',
30 'VK_KHR_incremental_present',
31 'VK_KHR_shared_presentable_image',
32 'VK_KHR_surface',
33 'VK_KHR_swapchain',
34 'VK_KHR_get_surface_capabilities2'
35]
36
37knownExtensions = interceptedExtensions + [
38 'VK_KHR_get_physical_device_properties2',
39 'VK_ANDROID_external_memory_android_hardware_buffer',
40 'VK_KHR_bind_memory2'
41]
42
43def defineProcHookType(f):
44 f.write ("""struct ProcHook {
45 enum Type {
46 GLOBAL,
47 INSTANCE,
48 DEVICE,
49 };
50 enum Extension {\n""")
51 for exts in knownExtensions:
52 f.write (gencom.clang_off_spaces*2 + exts[3:] + ',\n')
53 f.write ('\n')
54 f.write (gencom.clang_off_spaces*2 + """EXTENSION_CORE, // valid bit
55 EXTENSION_COUNT,
56 EXTENSION_UNKNOWN,
57 };
58
59 const char* name;
60 Type type;
61 Extension extension;
62
63 PFN_vkVoidFunction proc;
64 PFN_vkVoidFunction checked_proc; // always nullptr for non-device hooks
65};\n\n""")
66
67def isExtensionIntercepted(extensionName):
68 if extensionName in interceptedExtensions:
69 return True
70 return False
71
72def isDriverTableEntry(functionName):
73 switchCase = {
74 # Create functions of dispatchable objects
75 'vkCreateDevice' : True,
76 'vkGetDeviceQueue' : True,
77 'vkGetDeviceQueue2' : True,
78 'vkAllocateCommandBuffers' : True,
79
80 # Destroy functions of dispatchable objects
81 'vkDestroyInstance' : True,
82 'vkDestroyDevice' : True,
83
84 # Enumeration of extensions
85 'vkEnumerateDeviceExtensionProperties' : True,
86
87 # We cache physical devices in loader.cpp
88 'vkEnumeratePhysicalDevices' : True,
89 'vkEnumeratePhysicalDeviceGroups' : True,
90
91 'vkGetInstanceProcAddr' : True,
92 'vkGetDeviceProcAddr' : True,
93
94 # VK_KHR_swapchain->VK_ANDROID_native_buffer translation
95 'vkCreateImage' : True,
96 'vkDestroyImage' : True,
97
98 'vkGetPhysicalDeviceProperties' : True,
99 'vkGetPhysicalDeviceProperties2' : True,
100 'vkGetPhysicalDeviceProperties2KHR' : True,
101
102 # VK_KHR_swapchain v69 requirement
103 'vkBindImageMemory2' : True,
104 'vkBindImageMemory2KHR' : True
105 }
106 if gencom.isFunctionSupported(functionName):
107 if functionName in switchCase:
108 return True
109 if functionName in gencom.extensionsDict:
110 if gencom.extensionsDict[functionName] == 'VK_ANDROID_native_buffer' or gencom.extensionsDict[functionName] == 'VK_EXT_debug_report':
111 return True
112 return False
113
114def isInstanceDriverTableEntry(functionName):
115 if isDriverTableEntry(functionName) and gencom.isInstanceDispatched(functionName):
116 return True
117 return False
118
119def isDeviceDriverTableEntry(functionName):
120 if isDriverTableEntry(functionName) and gencom.isDeviceDispatched(functionName):
121 return True
122 return False
123
124def driver_genh():
125 header = """#ifndef LIBVULKAN_DRIVER_GEN_H
126#define LIBVULKAN_DRIVER_GEN_H
127
128#include <vulkan/vk_android_native_buffer.h>
129#include <vulkan/vulkan.h>
130
131#include <bitset>
132
133namespace vulkan {
134namespace driver {\n\n"""
Adithya Srinivasan8dce9d72019-07-11 14:26:04 -0700135 genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.h')
Adithya Srinivasan01364142019-07-02 15:52:49 -0700136 with open(genfile, 'w') as f:
137 f.write (gencom.copyright)
138 f.write (gencom.warning)
139 f.write (header)
140 defineProcHookType(f)
141 f.write ('struct InstanceDriverTable {\n')
142 gencom.clang_off(f, 1)
143 for cmds in gencom.allCommandsList:
144 if isInstanceDriverTableEntry(cmds):
145 f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
146 gencom.clang_on(f, 1)
147 f.write ('};\n\n')
148 f.write ('struct DeviceDriverTable {\n')
149 gencom.clang_off(f,1)
150 for cmds in gencom.allCommandsList:
151 if isDeviceDriverTableEntry(cmds):
152 f.write (gencom.clang_off_spaces + 'PFN_' + cmds + ' ' + cmds[2:] + ';\n')
153 gencom.clang_on(f,1)
154 f.write ('};\n\n')
155 f.write ("""const ProcHook* GetProcHook(const char* name);
156ProcHook::Extension GetProcHookExtension(const char* name);
157
158bool InitDriverTable(VkInstance instance,
159 PFN_vkGetInstanceProcAddr get_proc,
160 const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
161bool InitDriverTable(VkDevice dev,
162 PFN_vkGetDeviceProcAddr get_proc,
163 const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
164
165} // namespace driver
166} // namespace vulkan
167
168#endif // LIBVULKAN_DRIVER_TABLE_H\n""")
Adithya Srinivasan8dce9d72019-07-11 14:26:04 -0700169 f.close()
170 gencom.runClangFormat(genfile)
Adithya Srinivasan01364142019-07-02 15:52:49 -0700171
172def isIntercepted(functionName):
173 switchCase = {
174 # Create functions of dispatchable objects
175 'vkCreateInstance' : True,
176 'vkCreateDevice' : True,
177 'vkEnumeratePhysicalDevices' : True,
178 'vkEnumeratePhysicalDeviceGroups' : True,
179 'vkGetDeviceQueue' : True,
180 'vkGetDeviceQueue2' : True,
181 'vkAllocateCommandBuffers' : True,
182
183 # Destroy functions of dispatchable objects
184 'vkDestroyInstance' : True,
185 'vkDestroyDevice' : True,
186
187 # Enumeration of extensions
188 'vkEnumerateInstanceExtensionProperties' : True,
189 'vkEnumerateDeviceExtensionProperties' : True,
190
191 'vkGetInstanceProcAddr' : True,
192 'vkGetDeviceProcAddr' : True,
193
194 # VK_KHR_swapchain v69 requirement
195 'vkBindImageMemory2' : True,
196 'vkBindImageMemory2KHR' : True
197 }
198 if gencom.isFunctionSupported(functionName):
199 if functionName in switchCase:
200 return switchCase[functionName]
201
202 if functionName in gencom.extensionsDict:
203 return isExtensionIntercepted(gencom.extensionsDict[functionName])
204 return False
205
206def needProcHookStub(functionName):
207 if isIntercepted(functionName) and gencom.isDeviceDispatched(functionName):
208 if functionName in gencom.extensionsDict:
209 if not gencom.isExtensionInternal(gencom.extensionsDict[functionName]):
210 return True
211 return False
212
213def defineInitProc(name, f):
214 f.write ('#define UNLIKELY(expr) __builtin_expect((expr), 0)\n')
215 f.write ('\n')
216 f.write ("""#define INIT_PROC(required, obj, proc) \\
217 do { \\
218 data.""" + name + """.proc = \\
219 reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \\
220 if (UNLIKELY(required && !data.""" + name + """.proc)) { \\
221 ALOGE("missing " #obj " proc: vk" #proc); \\
222 success = false; \\
223 } \\
224 } while (0)\n\n""")
225
226def defineInitProcExt(f):
227 f.write ("""#define INIT_PROC_EXT(ext, required, obj, proc) \\
228 do { \\
229 if (extensions[ProcHook::ext]) \\
230 INIT_PROC(required, obj, proc); \\
231 } while (0)\n\n""")
232
233def defineProcHookStub(functionName, f):
234 if needProcHookStub(functionName):
235 ext_name = gencom.extensionsDict[functionName]
236 base_name = functionName[2:]
237 paramList = [''.join(i) for i in gencom.paramDict[functionName]]
238 p0 = gencom.paramDict[functionName][0][1]
239 f.write ('VKAPI_ATTR ' + gencom.returnTypeDict[functionName] + ' checked' + base_name + '(' + ', '.join(paramList) + ') {\n')
240 ext_hook = 'ProcHook::' + ext_name[3:]
241
242 f.write (gencom.clang_off_spaces + 'if (GetData(' + p0 + ').hook_extensions[' + ext_hook + ']) {\n')
243 f.write (gencom.clang_off_spaces *2)
244 if gencom.returnTypeDict[functionName] != 'void':
245 f.write ('return ')
246 paramNames = [''.join(i[1]) for i in gencom.paramDict[functionName]]
247 f.write (base_name + '(' + ', '.join(paramNames) + ');\n')
248 f.write (gencom.clang_off_spaces + '} else {\n')
249 f.write (gencom.clang_off_spaces*2 + 'Logger(' + p0 + ').Err(' + p0 + ', \"' + ext_name + ' not enabled. ' + functionName + ' not executed.\");\n')
250 if gencom.returnTypeDict[functionName] != 'void':
251 f.write (gencom.clang_off_spaces*2 + 'return VK_SUCCESS;\n')
252 f.write (gencom.clang_off_spaces + '}\n')
253 f.write ('}\n\n')
254
255def defineGlobalProcHook(functionName, f):
256 base_name = functionName[2:]
257 assert (functionName not in gencom.extensionsDict)
258 f.write (gencom.clang_off_spaces + '{\n' + gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n' + gencom.clang_off_spaces*2)
259 f.write ("""ProcHook::GLOBAL,
260 ProcHook::EXTENSION_CORE,
261 reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
262 nullptr,
263 },\n""")
264
265def defineInstanceProcHook(functionName, f):
266 base_name = functionName[2:]
267 f.write (gencom.clang_off_spaces + '{\n')
268 f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
269 f.write (gencom.clang_off_spaces*2 + 'ProcHook::INSTANCE,\n')
270
271 if functionName in gencom.extensionsDict:
272 ext_name = gencom.extensionsDict[functionName]
273 f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
274 if gencom.isExtensionInternal(ext_name):
275 f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
276 else:
277 f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
278
279 else:
280 f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
281 reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
282 nullptr,\n""")
283
284 f.write (gencom.clang_off_spaces + '},\n')
285
286def defineDeviceProcHook(functionName, f):
287 base_name = functionName[2:]
288 f.write (gencom.clang_off_spaces + '{\n')
289 f.write (gencom.clang_off_spaces*2 + '\"' + functionName + '\",\n')
290 f.write (gencom.clang_off_spaces*2 + 'ProcHook::DEVICE,\n')
291
292 if functionName in gencom.extensionsDict:
293 ext_name = gencom.extensionsDict[functionName]
294 f.write (gencom.clang_off_spaces*2 + 'ProcHook::' + ext_name[3:] + ',\n')
295 if gencom.isExtensionInternal(ext_name):
296 f.write (gencom.clang_off_spaces*2 + 'nullptr,\n' + gencom.clang_off_spaces*2 + 'nullptr,\n')
297 else:
298 f.write (gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(' + base_name + '),\n' + gencom.clang_off_spaces*2 + 'reinterpret_cast<PFN_vkVoidFunction>(checked' + base_name + '),\n')
299
300 else:
301 f.write (gencom.clang_off_spaces*2 + """ProcHook::EXTENSION_CORE,
302 reinterpret_cast<PFN_vkVoidFunction>(""" + base_name + """),
303 nullptr,\n""")
304
305 f.write (gencom.clang_off_spaces + '},\n')
306
307def driver_gencpp():
308 header = """#include <log/log.h>
309#include <string.h>
310
311#include <algorithm>
312
313#include "driver.h"
314
315namespace vulkan {
316namespace driver {
317
318namespace {
319
320// clang-format off\n\n"""
321
Adithya Srinivasan8dce9d72019-07-11 14:26:04 -0700322 genfile = os.path.join(os.path.dirname(__file__),'..','libvulkan','driver_gen.cpp')
Adithya Srinivasan01364142019-07-02 15:52:49 -0700323
324 with open(genfile, 'w') as f:
325 f.write (gencom.copyright)
326 f.write (gencom.warning)
327 f.write (header)
328
329 for cmds in gencom.allCommandsList:
330 defineProcHookStub(cmds, f)
331 gencom.clang_on(f, 0)
332 f.write ('\n')
333
334 f.write ('const ProcHook g_proc_hooks[] = {\n')
335 gencom.clang_off(f, 1)
336 sortedCommandsList = sorted(gencom.allCommandsList)
337 for cmds in sortedCommandsList:
338 if isIntercepted(cmds):
339 if gencom.isGloballyDispatched(cmds):
340 defineGlobalProcHook(cmds, f)
341 elif gencom.isInstanceDispatched(cmds):
342 defineInstanceProcHook(cmds, f)
343 elif gencom.isDeviceDispatched(cmds):
344 defineDeviceProcHook(cmds, f)
345 gencom.clang_on(f, 1)
346 f.write ('};\n\n} // namespace\n\n')
347
348 f.write ("""const ProcHook* GetProcHook(const char* name) {
349 const auto& begin = g_proc_hooks;
350 const auto& end =
351 g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
352 const auto hook = std::lower_bound(
353 begin, end, name,
354 [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
355 return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
356}\n\n""")
357
358 f.write ('ProcHook::Extension GetProcHookExtension(const char* name) {\n')
359 gencom.clang_off(f, 1)
360 for exts in knownExtensions:
361 f.write (gencom.clang_off_spaces + 'if (strcmp(name, \"' + exts + '\") == 0) return ProcHook::' + exts[3:] + ';\n')
362 gencom.clang_on(f, 1)
363 f.write (gencom.clang_off_spaces + 'return ProcHook::EXTENSION_UNKNOWN;\n')
364 f.write ('}\n\n')
365
366 defineInitProc('driver', f)
367 defineInitProcExt(f)
368
369 f.write ("""bool InitDriverTable(VkInstance instance,
370 PFN_vkGetInstanceProcAddr get_proc,
371 const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
372 auto& data = GetData(instance);
373 bool success = true;\n\n""")
374 gencom.clang_off(f, 1)
375 for cmds in gencom.allCommandsList:
376 if isInstanceDriverTableEntry(cmds):
377 gencom.initProc(cmds, f)
378 gencom.clang_on(f, 1)
379 f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
380 f.write ('}\n\n')
381
382 f.write ("""bool InitDriverTable(VkDevice dev,
383 PFN_vkGetDeviceProcAddr get_proc,
384 const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
385 auto& data = GetData(dev);
386 bool success = true;\n\n""")
387 gencom.clang_off(f, 1)
388 for cmds in gencom.allCommandsList:
389 if isDeviceDriverTableEntry(cmds):
390 gencom.initProc(cmds, f)
391 gencom.clang_on(f, 1)
392 f.write ('\n' + gencom.clang_off_spaces + 'return success;\n')
393 f.write ('}\n\n} // namespace driver\n} // namespace vulkan\n\n')
394 gencom.clang_on(f, 0)
Adithya Srinivasan8dce9d72019-07-11 14:26:04 -0700395 f.close()
396 gencom.runClangFormat(genfile)