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