blob: b1c20941e9a1d4ddbc48376900d40d1a4ee88fdf [file] [log] [blame]
Jesse Hall1f91d392015-12-11 16:28:44 -08001{{/*
2 * Copyright 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */}}
16
17{{Include "../api/templates/vulkan_common.tmpl"}}
18{{Global "clang-format" (Strings "clang-format" "-style=file")}}
19{{Macro "DefineGlobals" $}}
20{{$ | Macro "dispatch_gen.h" | Format (Global "clang-format") | Write "dispatch_gen.h" }}
21{{$ | Macro "dispatch_gen.cpp" | Format (Global "clang-format") | Write "dispatch_gen.cpp"}}
22
23{{/*
24-------------------------------------------------------------------------------
25 dispatch_gen.h
26-------------------------------------------------------------------------------
27*/}}
28{{define "dispatch_gen.h"}}
29/*
30•* Copyright 2015 The Android Open Source Project
31•*
32•* Licensed under the Apache License, Version 2.0 (the "License");
33•* you may not use this file except in compliance with the License.
34•* You may obtain a copy of the License at
35•*
36•* http://www.apache.org/licenses/LICENSE-2.0
37•*
38•* Unless required by applicable law or agreed to in writing, software
39•* distributed under the License is distributed on an "AS IS" BASIS,
40•* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
41•* See the License for the specific language governing permissions and
42•* limitations under the License.
43•*/
44
45#define VK_PROTOTYPES
46#define VK_USE_PLATFORM_ANDROID_KHR
47#include <vulkan/vk_android_native_buffer.h>
48#include <vulkan/vulkan.h>
49
50namespace vulkan {
51
52struct InstanceDispatchTable
53 // clang-format off
54 {{range $f := AllCommands $}}
55 {{if (Macro "IsInstanceDispatched" $f)}}
56 {{Macro "FunctionPtrName" $f}} {{Macro "BaseName" $f}};
57 {{end}}
58 {{end}}
59 // clang-format on
60»};
61
62struct DeviceDispatchTable
63 // clang-format off
64 {{range $f := AllCommands $}}
65 {{if (Macro "IsDeviceDispatched" $f)}}
66 {{Macro "FunctionPtrName" $f}} {{Macro "BaseName" $f}};
67 {{end}}
68 {{end}}
69 // clang-format on
70»};
71
72struct DriverDispatchTable
73 // clang-format off
74 {{range $f := AllCommands $}}
75 {{if (Macro "IsInstanceDispatched" $f)}}
76 {{if not (Macro "IsLoaderFunction" $f)}}
77 {{Macro "FunctionPtrName" $f}} {{Macro "BaseName" $f}};
78 {{end}}
79 {{end}}
80 {{end}}
81
82 PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
83
84 {{/* TODO(jessehall): Needed by swapchain code. Figure out a better way of
85 handling this that avoids the special case. Probably should rework
86 things so the driver dispatch table has all driver functions. Probably
87 need separate instance- and device-level copies, fill in all device-
88 dispatched functions in the device-level copies only, and change
89 GetDeviceProcAddr_Bottom to look in the already-loaded driver
90 dispatch table rather than forwarding to the driver's
91 vkGetDeviceProcAddr. */}}
92 PFN_vkCreateImage CreateImage;
93 PFN_vkDestroyImage DestroyImage;
94
95 PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
96 PFN_vkAcquireImageANDROID AcquireImageANDROID;
97 PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
98 // clang-format on
99»};
100
101} // namespace vulkan
102¶{{end}}
103
104
105{{/*
106-------------------------------------------------------------------------------
107 dispatch_gen.cpp
108-------------------------------------------------------------------------------
109*/}}
110{{define "dispatch_gen.cpp"}}
111/*
112•* Copyright 2015 The Android Open Source Project
113•*
114•* Licensed under the Apache License, Version 2.0 (the "License");
115•* you may not use this file except in compliance with the License.
116•* You may obtain a copy of the License at
117•*
118•* http://www.apache.org/licenses/LICENSE-2.0
119•*
120•* Unless required by applicable law or agreed to in writing, software
121•* distributed under the License is distributed on an "AS IS" BASIS,
122•* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123•* See the License for the specific language governing permissions and
124•* limitations under the License.
125•*/
126
127#include <log/log.h>
128#include <algorithm>
129#include "loader.h"
130
131#define UNLIKELY(expr) __builtin_expect((expr), 0)
132
133using namespace vulkan;
134
135namespace {
136
137struct NameProc {
138 const char* name;
139 PFN_vkVoidFunction proc;
140};
141
142PFN_vkVoidFunction Lookup(const char* name, const NameProc* begin, const NameProc* end) {
143 const auto& entry = std::lower_bound(
144 begin, end, name,
145 [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
146 if (entry == end || strcmp(entry->name, name) != 0)
147 return nullptr;
148 return entry->proc;
149}
150
151template <size_t N>
152PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
153 return Lookup(name, procs, procs + N);
154}
155
156const NameProc kLoaderExportProcs[] =
157 // clang-format off
158 {{range $f := SortBy (AllCommands $) "FunctionName"}}
159 {{if (Macro "IsFunctionSupported" $f)}}
160 {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}})},
161 {{end}}
162 {{end}}
163 // clang-format on
164»};
165
166const NameProc kLoaderGlobalProcs[] =
167 // clang-format off
168 {{range $f := SortBy (AllCommands $) "FunctionName"}}
169 {{if and (Macro "HasLoaderTopImpl" $f) (eq (Macro "Vtbl" $f) "Global")}}
170 {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
171 static_cast<{{Macro "FunctionPtrName" $f}}>(§
172 {{Macro "BaseName" $f}}_Top))},
173 {{end}}
174 {{end}}
175 // clang-format on
176»};
177
178const NameProc kLoaderTopProcs[] =
179 // clang-format off
180 {{range $f := SortBy (AllCommands $) "FunctionName"}}
181 {{if (Macro "HasLoaderTopImpl" $f)}}
182 {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
183 static_cast<{{Macro "FunctionPtrName" $f}}>(§
184 {{Macro "BaseName" $f}}_Top))},
185 {{end}}
186 {{end}}
187 // clang-format on
188»};
189
190const NameProc kLoaderBottomProcs[] =
191 // clang-format off
192 {{range $f := SortBy (AllCommands $) "FunctionName"}}
193 {{if (Macro "HasLoaderBottomImpl" $f)}}
194 {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
195 static_cast<{{Macro "FunctionPtrName" $f}}>(§
196 {{Macro "BaseName" $f}}_Bottom))},
197 {{end}}
198 {{end}}
199 // clang-format on
200»};
201
202struct NameOffset {
203 const char* name;
204 size_t offset;
205};
206
207ssize_t Lookup(const char* name,
208 const NameOffset* begin,
209 const NameOffset* end) {
210 const auto& entry = std::lower_bound(
211 begin, end, name, [](const NameOffset& e, const char* n) {
212 return strcmp(e.name, n) < 0;
213 });
214 if (entry == end || strcmp(entry->name, name) != 0)
215 return -1;
216 return static_cast<ssize_t>(entry->offset);
217}
218
219template <size_t N, class Table>
220PFN_vkVoidFunction Lookup(const char* name,
221 const NameOffset (&offsets)[N],
222 const Table& table) {
223 ssize_t offset = Lookup(name, offsets, offsets + N);
224 if (offset < 0)
225 return nullptr;
226 uintptr_t base = reinterpret_cast<uintptr_t>(&table);
227 return *reinterpret_cast<PFN_vkVoidFunction*>(base +
228 static_cast<size_t>(offset));
229}
230
231const NameOffset kInstanceDispatchOffsets[] =
232 // clang-format off
233 {{range $f := SortBy (AllCommands $) "FunctionName"}}
234 {{if (Macro "IsInstanceDispatched" $f)}}
235 {"{{$f.Name}}", offsetof(InstanceDispatchTable, {{Macro "BaseName" $f}})},
236 {{end}}
237 {{end}}
238 // clang-format on
239»};
240
241const NameOffset kDeviceDispatchOffsets[] =
242 // clang-format off
243 {{range $f := SortBy (AllCommands $) "FunctionName"}}
244 {{if (Macro "IsDeviceDispatched" $f)}}
245 {"{{$f.Name}}", offsetof(DeviceDispatchTable, {{Macro "BaseName" $f}})},
246 {{end}}
247 {{end}}
248 // clang-format on
249»};
250
251} // anonymous namespace
252
253namespace vulkan {
254
255PFN_vkVoidFunction GetLoaderExportProcAddr(const char* name) {
256 return Lookup(name, kLoaderExportProcs);
257}
258
259PFN_vkVoidFunction GetLoaderGlobalProcAddr(const char* name) {
260 return Lookup(name, kLoaderGlobalProcs);
261}
262
263PFN_vkVoidFunction GetLoaderTopProcAddr(const char* name) {
264 return Lookup(name, kLoaderTopProcs);
265}
266
267PFN_vkVoidFunction GetLoaderBottomProcAddr(const char* name) {
268 return Lookup(name, kLoaderBottomProcs);
269}
270
271PFN_vkVoidFunction GetDispatchProcAddr(const InstanceDispatchTable& dispatch,
272 const char* name) {
273 return Lookup(name, kInstanceDispatchOffsets, dispatch);
274}
275
276PFN_vkVoidFunction GetDispatchProcAddr(const DeviceDispatchTable& dispatch,
277 const char* name) {
278 return Lookup(name, kDeviceDispatchOffsets, dispatch);
279}
280
281bool LoadInstanceDispatchTable(VkInstance instance,
282 PFN_vkGetInstanceProcAddr get_proc_addr,
283 InstanceDispatchTable& dispatch)
284 bool success = true;
285 // clang-format off
286 {{range $f := AllCommands $}}
287 {{if (Macro "IsInstanceDispatched" $f)}}
288 dispatch.{{Macro "BaseName" $f}} = §
289 reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
290 get_proc_addr(instance, "{{$f.Name}}"));
291 if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
292 ALOGE("missing instance proc: %s", "{{$f.Name}}");
293 success = false;
294 }
295 {{end}}
296 {{end}}
297 // clang-format on
298 return success;
299»}
300
301bool LoadDeviceDispatchTable(VkDevice device,
302 PFN_vkGetDeviceProcAddr get_proc_addr,
303 DeviceDispatchTable& dispatch)
304 bool success = true;
305 // clang-format off
306 {{range $f := AllCommands $}}
307 {{if (Macro "IsDeviceDispatched" $f)}}
308 dispatch.{{Macro "BaseName" $f}} = §
309 reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
310 get_proc_addr(device, "{{$f.Name}}"));
311 if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
312 ALOGE("missing device proc: %s", "{{$f.Name}}");
313 success = false;
314 }
315 {{end}}
316 {{end}}
317 // clang-format on
318 return success;
319»}
320
321bool LoadDriverDispatchTable(VkInstance instance,
322 PFN_vkGetInstanceProcAddr get_proc_addr,
323 DriverDispatchTable& dispatch)
324 bool success = true;
325 // clang-format off
326 {{range $f := AllCommands $}}
327 {{if (Macro "IsInstanceDispatched" $f)}}
328 {{if not (Macro "IsLoaderFunction" $f)}}
329 dispatch.{{Macro "BaseName" $f}} = §
330 reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
331 get_proc_addr(instance, "{{$f.Name}}"));
332 if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
333 ALOGE("missing driver proc: %s", "{{$f.Name}}");
334 success = false;
335 }
336 {{end}}
337 {{end}}
338 {{end}}
339 dispatch.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(get_proc_addr(instance, "vkGetDeviceProcAddr"));
340 if (UNLIKELY(!dispatch.GetDeviceProcAddr)) {
341 ALOGE("missing driver proc: %s", "vkGetDeviceProcAddr");
342 success = false;
343 }
344 dispatch.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(instance, "vkCreateImage"));
345 if (UNLIKELY(!dispatch.CreateImage)) {
346 ALOGE("missing driver proc: %s", "vkCreateImage");
347 success = false;
348 }
349 dispatch.DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(get_proc_addr(instance, "vkDestroyImage"));
350 if (UNLIKELY(!dispatch.DestroyImage)) {
351 ALOGE("missing driver proc: %s", "vkDestroyImage");
352 success = false;
353 }
Jesse Halld9132822016-01-14 15:50:52 -0800354 dispatch.GetSwapchainGrallocUsageANDROID = reinterpret_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(get_proc_addr(instance, "vkGetSwapchainGrallocUsageANDROID"));
355 if (UNLIKELY(!dispatch.GetSwapchainGrallocUsageANDROID)) {
356 ALOGE("missing driver proc: %s", "vkGetSwapchainGrallocUsageANDROID");
357 success = false;
358 }
Jesse Hall1f91d392015-12-11 16:28:44 -0800359 dispatch.AcquireImageANDROID = reinterpret_cast<PFN_vkAcquireImageANDROID>(get_proc_addr(instance, "vkAcquireImageANDROID"));
360 if (UNLIKELY(!dispatch.AcquireImageANDROID)) {
361 ALOGE("missing driver proc: %s", "vkAcquireImageANDROID");
362 success = false;
363 }
364 dispatch.QueueSignalReleaseImageANDROID = reinterpret_cast<PFN_vkQueueSignalReleaseImageANDROID>(get_proc_addr(instance, "vkQueueSignalReleaseImageANDROID"));
365 if (UNLIKELY(!dispatch.QueueSignalReleaseImageANDROID)) {
366 ALOGE("missing driver proc: %s", "vkQueueSignalReleaseImageANDROID");
367 success = false;
368 }
369 // clang-format on
370 return success;
371»}
372
373} // namespace vulkan
374
375// clang-format off
376
377{{range $f := AllCommands $}}
378 {{if and (not (GetAnnotation $f "pfn")) (Macro "IsExported" $f)}}
379 __attribute__((visibility("default")))
380 VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
381 {{if not (IsVoid $f.Return.Type)}}return §{{end}}
382 {{Macro "Dispatch" $f}}({{Macro "Arguments" $f}});
383 }
384
385 {{end}}
386{{end}}
387
388// clang-format on
389¶{{end}}
390
391
392{{/*
393-------------------------------------------------------------------------------
394 Emit the dispatch lookup for a function based on its first parameter.
395-------------------------------------------------------------------------------
396*/}}
397{{define "Dispatch"}}
398 {{AssertType $ "Function"}}
399
400 {{if (Macro "HasLoaderTopImpl" $)}}
401 {{Macro "BaseName" $}}_Top§
402 {{else}}
403 {{$p0 := index $.CallParameters 0}}
404 GetDispatchTable({{$p0.Name}}).{{Macro "BaseName" $}}§
405 {{end}}
406{{end}}
407
408
409{{/*
410-------------------------------------------------------------------------------
411 Emits a function name without the "vk" prefix.
412-------------------------------------------------------------------------------
413*/}}
414{{define "BaseName"}}
415 {{AssertType $ "Function"}}
416 {{TrimPrefix "vk" $.Name}}
417{{end}}
418
419
420{{/*
421-------------------------------------------------------------------------------
422 Emits a comma-separated list of C parameter names for the given command.
423-------------------------------------------------------------------------------
424*/}}
425{{define "Arguments"}}
426 {{AssertType $ "Function"}}
427
428 {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
429{{end}}
430
431
432{{/*
433------------------------------------------------------------------------------
434 Emit "true" for supported functions that undergo table dispatch. Only global
435 functions and functions handled in the loader top without calling into
436 lower layers are not dispatched.
437------------------------------------------------------------------------------
438*/}}
439{{define "IsInstanceDispatched"}}
440 {{AssertType $ "Function"}}
441 {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
442 {{if (ne $.Name "vkGetInstanceProcAddr")}}true{{end}}
443 {{end}}
444{{end}}
445
446
447{{/*
448------------------------------------------------------------------------------
449 Emit "true" for supported functions that can have device-specific dispatch.
450------------------------------------------------------------------------------
451*/}}
452{{define "IsDeviceDispatched"}}
453 {{AssertType $ "Function"}}
454 {{if (Macro "IsFunctionSupported" $)}}
455 {{if eq (Macro "Vtbl" $) "Device"}}
456 {{if ne $.Name "vkGetDeviceProcAddr"}}
457 true
458 {{end}}
459 {{end}}
460 {{end}}
461{{end}}
462
463
464{{/*
465------------------------------------------------------------------------------
466 Emit "true" if a function is core or from a supportable extension.
467------------------------------------------------------------------------------
468*/}}
469{{define "IsFunctionSupported"}}
470 {{AssertType $ "Function"}}
471 {{if not (GetAnnotation $ "pfn")}}
472 {{$ext := GetAnnotation $ "extension"}}
473 {{if not $ext}}true
474 {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
475 {{end}}
476 {{end}}
477{{end}}
478
479
480{{/*
481------------------------------------------------------------------------------
482 Decides whether a function should be exported from the Android Vulkan
483 library. Functions in the core API and in loader extensions are exported.
484------------------------------------------------------------------------------
485*/}}
486{{define "IsExported"}}
487 {{AssertType $ "Function"}}
488
489 {{$ext := GetAnnotation $ "extension"}}
490 {{if $ext}}
491 {{Macro "IsLoaderExtension" $ext}}
492 {{else}}
493 true
494 {{end}}
495{{end}}
496
497
498{{/*
499------------------------------------------------------------------------------
500 Reports whether an extension function is implemented entirely by the loader,
501 and not implemented by drivers.
502------------------------------------------------------------------------------
503*/}}
504{{define "IsLoaderFunction"}}
505 {{AssertType $ "Function"}}
506
507 {{$ext := GetAnnotation $ "extension"}}
508 {{if $ext}}
509 {{Macro "IsLoaderExtension" $ext}}
510 {{end}}
511{{end}}
512
513
514{{/*
515-------------------------------------------------------------------------------
516 Emit "true" if the loader has a top-level implementation for the function
517 that should be called directly rather than dispatching to the first layer.
518-------------------------------------------------------------------------------
519*/}}
520{{define "HasLoaderTopImpl"}}
521 {{AssertType $ "Function"}}
522
523 {{/* Global functions can't be dispatched */}}
524 {{ if and (not (GetAnnotation $ "pfn")) (eq (Macro "Vtbl" $) "Global")}}true
525
526 {{/* G*PA are implemented by reading the dispatch table, not by dispatching
527 through it. */}}
528 {{else if eq $.Name "vkGetInstanceProcAddr"}}true
529 {{else if eq $.Name "vkGetDeviceProcAddr"}}true
530
531 {{/* Loader top needs to initialize dispatch for device-level dispatchable
532 objects */}}
533 {{else if eq $.Name "vkGetDeviceQueue"}}true
534 {{else if eq $.Name "vkAllocateCommandBuffers"}}true
535
536 {{/* vkDestroy for dispatchable objects needs to handle VK_NULL_HANDLE;
537 trying to dispatch through that would crash. */}}
538 {{else if eq $.Name "vkDestroyInstance"}}true
539 {{else if eq $.Name "vkDestroyDevice"}}true
540
541 {{end}}
542{{end}}
543
544
545{{/*
546-------------------------------------------------------------------------------
547 Emit "true" if the loader has a bottom-level implementation for the function
548 which terminates the dispatch chain.
549-------------------------------------------------------------------------------
550*/}}
551{{define "HasLoaderBottomImpl"}}
552 {{AssertType $ "Function"}}
553
554 {{if (Macro "IsFunctionSupported" $)}}
555 {{ if (eq (Macro "Vtbl" $) "Instance")}}true
556 {{else if (Macro "IsLoaderFunction" $)}}true
557 {{else if (eq $.Name "vkCreateInstance")}}true
558 {{else if (eq $.Name "vkGetDeviceProcAddr")}}true
559 {{end}}
560 {{end}}
561{{end}}
562
563
564{{/*
565------------------------------------------------------------------------------
566 Emit "true" if an extension is unsupportable on Android.
567------------------------------------------------------------------------------
568*/}}
569{{define "IsExtensionBlacklisted"}}
570 {{$ext := index $.Arguments 0}}
571 {{ if eq $ext "VK_KHR_display"}}true
572 {{else if eq $ext "VK_KHR_display_swapchain"}}true
573 {{else if eq $ext "VK_KHR_xlib_surface"}}true
574 {{else if eq $ext "VK_KHR_xcb_surface"}}true
575 {{else if eq $ext "VK_KHR_wayland_surface"}}true
576 {{else if eq $ext "VK_KHR_mir_surface"}}true
577 {{else if eq $ext "VK_KHR_win32_surface"}}true
578 {{end}}
579{{end}}
580
581
582{{/*
583------------------------------------------------------------------------------
584 Reports whether an extension is implemented entirely by the loader,
585 so drivers should not enumerate it.
586------------------------------------------------------------------------------
587*/}}
588{{define "IsLoaderExtension"}}
589 {{$ext := index $.Arguments 0}}
590 {{ if eq $ext "VK_KHR_surface"}}true
591 {{else if eq $ext "VK_KHR_swapchain"}}true
592 {{else if eq $ext "VK_KHR_android_surface"}}true
593 {{end}}
594{{end}}