blob: 7ebe983dbae7767d72aba18bae59e85a44a61a10 [file] [log] [blame]
Chia-I Wu0c203242016-03-15 13:44:51 +08001{{define "Copyright"}}
2/*
3•* Copyright 2016 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¶{{end}}
18
19{{Include "../api/templates/vulkan_common.tmpl"}}
20{{Global "clang-format" (Strings "clang-format" "-style=file")}}
21{{Macro "DefineGlobals" $}}
22{{$ | Macro "api_gen.h" | Format (Global "clang-format") | Write "api_gen.h" }}
23{{$ | Macro "api_gen.cpp" | Format (Global "clang-format") | Write "api_gen.cpp"}}
24
25{{/*
26-------------------------------------------------------------------------------
27 api_gen.h
28-------------------------------------------------------------------------------
29*/}}
30{{define "api_gen.h"}}
31{{Macro "Copyright"}}
32
33// WARNING: This file is generated. See ../README.md for instructions.
34
35#ifndef LIBVULKAN_API_GEN_H
36#define LIBVULKAN_API_GEN_H
37
38#include <vulkan/vulkan.h>
39
40namespace vulkan
41namespace api
42
43struct InstanceDispatchTable {
44 // clang-format off
45 {{range $f := AllCommands $}}
46 {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
47 {{Macro "C++.DeclareDispatchTableEntry" $f}};
48 {{end}}
49 {{end}}
50 // clang-format on
51};
52
53struct DeviceDispatchTable {
54 // clang-format off
55 {{range $f := AllCommands $}}
56 {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
57 {{Macro "C++.DeclareDispatchTableEntry" $f}};
58 {{end}}
59 {{end}}
60 // clang-format on
61};
62
63bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc);
64bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc);
65
66»} // namespace api
67»} // namespace vulkan
68
69#endif // LIBVULKAN_API_GEN_H
70¶{{end}}
71
72
73{{/*
74-------------------------------------------------------------------------------
75 api_gen.cpp
76-------------------------------------------------------------------------------
77*/}}
78{{define "api_gen.cpp"}}
79{{Macro "Copyright"}}
80
81// WARNING: This file is generated. See ../README.md for instructions.
82
83#include <string.h>
84#include <algorithm>
85#include <log/log.h>
86
87#include "api.h"
88
89namespace vulkan
90namespace api
91
92{{Macro "C++.DefineInitProcMacros" "dispatch"}}
93
94bool InitDispatchTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc) {
95 auto& data = GetData(instance);
96 bool success = true;
97
98 // clang-format off
99 {{range $f := AllCommands $}}
100 {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
101 {{Macro "C++.InitProc" $f}}
102 {{end}}
103 {{end}}
104 // clang-format on
105
106 return success;
107}
108
109bool InitDispatchTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc) {
110 auto& data = GetData(dev);
111 bool success = true;
112
113 // clang-format off
114 {{range $f := AllCommands $}}
115 {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
116 {{Macro "C++.InitProc" $f}}
117 {{end}}
118 {{end}}
119 // clang-format on
120
121 return success;
122}
123
124»} // namespace api
125»} // namespace vulkan
126
127// clang-format off
128
129{{range $f := AllCommands $}}
130 {{if (Macro "IsFunctionExported" $f)}}
131 __attribute__((visibility("default")))
132 VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
133 {{ if eq $f.Name "vkGetInstanceProcAddr"}}
134 {{Macro "api.C++.InterceptInstanceProcAddr" $}}
135 {{else if eq $f.Name "vkGetDeviceProcAddr"}}
136 {{Macro "api.C++.InterceptDeviceProcAddr" $}}
137 {{end}}
138
139 {{Macro "api.C++.Dispatch" $f}}
140 }
141
142 {{end}}
143{{end}}
144
145// clang-format on
146¶{{end}}
147
148
149{{/*
150------------------------------------------------------------------------------
151 Emits a declaration of a dispatch table entry.
152------------------------------------------------------------------------------
153*/}}
154{{define "C++.DeclareDispatchTableEntry"}}
155 {{AssertType $ "Function"}}
156
157 {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
158{{end}}
159
160
161{{/*
162-------------------------------------------------------------------------------
163 Emits macros to help initialize dispatch tables.
164-------------------------------------------------------------------------------
165*/}}
166{{define "C++.DefineInitProcMacros"}}
167 #define UNLIKELY(expr) __builtin_expect((expr), 0)
168
169 #define INIT_PROC(obj, proc) do { \
170 data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>( \
171 get_proc(obj, "vk" # proc)); \
172 if (UNLIKELY(!data.{{$}}.proc)) { \
173 ALOGE("missing " # obj " proc: vk" # proc); \
174 success = false; \
175 } \
176 } while(0)
177
178 // TODO do we want to point to a stub or nullptr when ext is not enabled?
179 #define INIT_PROC_EXT(ext, obj, proc) do { \
180 INIT_PROC(obj, proc); \
181 } while(0)
182{{end}}
183
184
185{{/*
186-------------------------------------------------------------------------------
187 Emits code to invoke INIT_PROC or INIT_PROC_EXT.
188-------------------------------------------------------------------------------
189*/}}
190{{define "C++.InitProc"}}
191 {{AssertType $ "Function"}}
192
193 {{$ext := GetAnnotation $ "extension"}}
194 {{if $ext}}
195 INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
196 {{else}}
197 INIT_PROC
198 {{end}}
199
200 {{if (Macro "IsInstanceDispatched" $)}}
201 instance, §
202 {{else}}
203 dev, §
204 {{end}}
205
206 {{Macro "BaseName" $}});
207{{end}}
208
209
210{{/*
211------------------------------------------------------------------------------
212 Emits true if a function is exported and instance-dispatched.
213------------------------------------------------------------------------------
214*/}}
215{{define "api.IsInstanceDispatchTableEntry"}}
216 {{AssertType $ "Function"}}
217
218 {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
219 true
220 {{end}}
221{{end}}
222
223
224{{/*
225------------------------------------------------------------------------------
226 Emits true if a function is exported and device-dispatched.
227------------------------------------------------------------------------------
228*/}}
229{{define "api.IsDeviceDispatchTableEntry"}}
230 {{AssertType $ "Function"}}
231
232 {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
233 true
234 {{end}}
235{{end}}
236
237
238{{/*
239------------------------------------------------------------------------------
240 Emits true if a function is intercepted by vulkan::api.
241------------------------------------------------------------------------------
242*/}}
243{{define "api.IsIntercepted"}}
244 {{AssertType $ "Function"}}
245
246 {{if (Macro "IsFunctionSupported" $)}}
247 {{/* Global functions cannot be dispatched at all */}}
248 {{ if (Macro "IsGloballyDispatched" $)}}true
249
250 {{/* VkPhysicalDevice functions that manage device layers */}}
251 {{else if eq $.Name "vkCreateDevice"}}true
252 {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
253 {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
254
255 {{/* Destroy functions of dispatchable objects */}}
256 {{else if eq $.Name "vkDestroyInstance"}}true
257 {{else if eq $.Name "vkDestroyDevice"}}true
258
259 {{end}}
260 {{end}}
261{{end}}
262
263
264{{/*
265------------------------------------------------------------------------------
266 Emits code for vkGetInstanceProcAddr for function interception.
267------------------------------------------------------------------------------
268*/}}
269{{define "api.C++.InterceptInstanceProcAddr"}}
270 {{AssertType $ "API"}}
271
272 // global functions
273 if (!instance) {
274 {{range $f := AllCommands $}}
275 {{if (Macro "IsGloballyDispatched" $f)}}
276 if (strcmp(pName, "{{$f.Name}}") == 0) return §
277 reinterpret_cast<PFN_vkVoidFunction>(§
278 vulkan::api::{{Macro "BaseName" $f}});
279 {{end}}
280 {{end}}
281
282 ALOGE("vkGetInstanceProcAddr called with %s without instance", pName);
283 return nullptr;
284 }
285
286 static const struct Hook {
287 const char* name;
288 PFN_vkVoidFunction proc;
289 } hooks[] = {
290 {{range $f := SortBy (AllCommands $) "FunctionName"}}
291 {{if (Macro "IsFunctionExported" $f)}}
292 {{/* hide global functions */}}
293 {{if (Macro "IsGloballyDispatched" $f)}}
294 { "{{$f.Name}}", nullptr },
295
296 {{/* redirect intercepted functions */}}
297 {{else if (Macro "api.IsIntercepted" $f)}}
298 { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
299 vulkan::api::{{Macro "BaseName" $f}}) },
300
301 {{/* redirect vkGetInstanceProcAddr to itself */}}
302 {{else if eq $f.Name "vkGetInstanceProcAddr"}}
303 { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
304
305 {{/* redirect device functions to themselves as a workaround for
306 layers that do not intercept in their vkGetInstanceProcAddr */}}
307 {{else if (Macro "IsDeviceDispatched" $f)}}
308 { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
309
310 {{end}}
311 {{end}}
312 {{end}}
313 };
314 // clang-format on
315 constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
316 auto hook = std::lower_bound(
317 hooks, hooks + count, pName,
318 [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
319 if (hook < hooks + count && strcmp(hook->name, pName) == 0) {
320 if (!hook->proc)
321 ALOGE("vkGetInstanceProcAddr called with %s with instance", pName);
322 return hook->proc;
323 }
324 // clang-format off
325
326{{end}}
327
328
329{{/*
330------------------------------------------------------------------------------
331 Emits code for vkGetDeviceProcAddr for function interception.
332------------------------------------------------------------------------------
333*/}}
334{{define "api.C++.InterceptDeviceProcAddr"}}
335 {{AssertType $ "API"}}
336
337 if (device == VK_NULL_HANDLE) {
338 ALOGE("vkGetDeviceProcAddr called with invalid device");
339 return nullptr;
340 }
341
342 static const char* const known_non_device_names[] = {
343 {{range $f := SortBy (AllCommands $) "FunctionName"}}
344 {{if (Macro "IsFunctionSupported" $f)}}
345 {{if not (Macro "IsDeviceDispatched" $f)}}
346 "{{$f.Name}}",
347 {{end}}
348 {{end}}
349 {{end}}
350 };
351 // clang-format on
352 constexpr size_t count = sizeof(known_non_device_names) /
353 sizeof(known_non_device_names[0]);
354 if (!pName ||
355 std::binary_search(
356 known_non_device_names, known_non_device_names + count, pName,
357 [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
358 ALOGE("vkGetDeviceProcAddr called with %s", pName);
359 return nullptr;
360 }
361 // clang-format off
362
363{{end}}
364
365
366{{/*
367------------------------------------------------------------------------------
368 Emits code to dispatch a function.
369------------------------------------------------------------------------------
370*/}}
371{{define "api.C++.Dispatch"}}
372 {{AssertType $ "Function"}}
373
374 {{if (Macro "api.IsIntercepted" $)}}// call into api.cpp{{end}}
375 {{if not (IsVoid $.Return.Type)}}return §{{end}}
376
377 {{if (Macro "api.IsIntercepted" $)}}
378 vulkan::api::§
379 {{else}}
380 {{$p0 := index $.CallParameters 0}}
381 vulkan::api::GetData({{$p0.Name}}).dispatch
382 {{end}}
383
384 {{Macro "BaseName" $}}({{Macro "Arguments" $}});
385{{end}}
386
387
388{{/*
389-------------------------------------------------------------------------------
390 Emits a function/extension name without the "vk"/"VK_" prefix.
391-------------------------------------------------------------------------------
392*/}}
393{{define "BaseName"}}
394 {{ if IsFunction $}}{{TrimPrefix "vk" $.Name}}
395 {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
396 {{else}}{{Error "invalid use of BaseName"}}
397 {{end}}
398{{end}}
399
400
401{{/*
402-------------------------------------------------------------------------------
403 Emits a comma-separated list of C parameter names for the given command.
404-------------------------------------------------------------------------------
405*/}}
406{{define "Arguments"}}
407 {{AssertType $ "Function"}}
408
409 {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
410{{end}}
411
412
413{{/*
414------------------------------------------------------------------------------
415------------------------------------------------------------------------------
416*/}}
417{{define "IsGloballyDispatched"}}
418 {{AssertType $ "Function"}}
419 {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
420 true
421 {{end}}
422{{end}}
423
424
425{{/*
426------------------------------------------------------------------------------
427 Emit "true" for supported functions that undergo table dispatch. Only global
428 functions and functions handled in the loader top without calling into
429 lower layers are not dispatched.
430------------------------------------------------------------------------------
431*/}}
432{{define "IsInstanceDispatched"}}
433 {{AssertType $ "Function"}}
434 {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
435 true
436 {{end}}
437{{end}}
438
439
440{{/*
441------------------------------------------------------------------------------
442 Emit "true" for supported functions that can have device-specific dispatch.
443------------------------------------------------------------------------------
444*/}}
445{{define "IsDeviceDispatched"}}
446 {{AssertType $ "Function"}}
447 {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
448 true
449 {{end}}
450{{end}}
451
452
453{{/*
454------------------------------------------------------------------------------
455 Emit "true" if a function is core or from a supportable extension.
456------------------------------------------------------------------------------
457*/}}
458{{define "IsFunctionSupported"}}
459 {{AssertType $ "Function"}}
460 {{if not (GetAnnotation $ "pfn")}}
461 {{$ext := GetAnnotation $ "extension"}}
462 {{if not $ext}}true
463 {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
464 {{end}}
465 {{end}}
466{{end}}
467
468
469{{/*
470------------------------------------------------------------------------------
471 Decides whether a function should be exported from the Android Vulkan
472 library. Functions in the core API and in loader extensions are exported.
473------------------------------------------------------------------------------
474*/}}
475{{define "IsFunctionExported"}}
476 {{AssertType $ "Function"}}
477
478 {{if (Macro "IsFunctionSupported" $)}}
479 {{$ext := GetAnnotation $ "extension"}}
480 {{if $ext}}
481 {{Macro "IsExtensionExported" $ext}}
482 {{else}}
483 true
484 {{end}}
485 {{end}}
486{{end}}
487
488
489{{/*
490------------------------------------------------------------------------------
491 Emit "true" if an extension is unsupportable on Android.
492------------------------------------------------------------------------------
493*/}}
494{{define "IsExtensionBlacklisted"}}
495 {{$ext := index $.Arguments 0}}
496 {{ if eq $ext "VK_KHR_display"}}true
497 {{else if eq $ext "VK_KHR_display_swapchain"}}true
498 {{else if eq $ext "VK_KHR_xlib_surface"}}true
499 {{else if eq $ext "VK_KHR_xcb_surface"}}true
500 {{else if eq $ext "VK_KHR_wayland_surface"}}true
501 {{else if eq $ext "VK_KHR_mir_surface"}}true
502 {{else if eq $ext "VK_KHR_win32_surface"}}true
503 {{end}}
504{{end}}
505
506
507{{/*
508------------------------------------------------------------------------------
509 Reports whether an extension is implemented entirely by the loader,
510 so drivers should not enumerate it.
511------------------------------------------------------------------------------
512*/}}
513{{define "IsExtensionExported"}}
514 {{$ext := index $.Arguments 0}}
515 {{ if eq $ext "VK_KHR_surface"}}true
516 {{else if eq $ext "VK_KHR_swapchain"}}true
517 {{else if eq $ext "VK_KHR_android_surface"}}true
518 {{end}}
519{{end}}