blob: a387d810954eefad46b1b5b786cd8cf4f1901137 [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 }
354 dispatch.AcquireImageANDROID = reinterpret_cast<PFN_vkAcquireImageANDROID>(get_proc_addr(instance, "vkAcquireImageANDROID"));
355 if (UNLIKELY(!dispatch.AcquireImageANDROID)) {
356 ALOGE("missing driver proc: %s", "vkAcquireImageANDROID");
357 success = false;
358 }
359 dispatch.QueueSignalReleaseImageANDROID = reinterpret_cast<PFN_vkQueueSignalReleaseImageANDROID>(get_proc_addr(instance, "vkQueueSignalReleaseImageANDROID"));
360 if (UNLIKELY(!dispatch.QueueSignalReleaseImageANDROID)) {
361 ALOGE("missing driver proc: %s", "vkQueueSignalReleaseImageANDROID");
362 success = false;
363 }
364 // clang-format on
365 return success;
366»}
367
368} // namespace vulkan
369
370// clang-format off
371
372{{range $f := AllCommands $}}
373 {{if and (not (GetAnnotation $f "pfn")) (Macro "IsExported" $f)}}
374 __attribute__((visibility("default")))
375 VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
376 {{if not (IsVoid $f.Return.Type)}}return §{{end}}
377 {{Macro "Dispatch" $f}}({{Macro "Arguments" $f}});
378 }
379
380 {{end}}
381{{end}}
382
383// clang-format on
384¶{{end}}
385
386
387{{/*
388-------------------------------------------------------------------------------
389 Emit the dispatch lookup for a function based on its first parameter.
390-------------------------------------------------------------------------------
391*/}}
392{{define "Dispatch"}}
393 {{AssertType $ "Function"}}
394
395 {{if (Macro "HasLoaderTopImpl" $)}}
396 {{Macro "BaseName" $}}_Top§
397 {{else}}
398 {{$p0 := index $.CallParameters 0}}
399 GetDispatchTable({{$p0.Name}}).{{Macro "BaseName" $}}§
400 {{end}}
401{{end}}
402
403
404{{/*
405-------------------------------------------------------------------------------
406 Emits a function name without the "vk" prefix.
407-------------------------------------------------------------------------------
408*/}}
409{{define "BaseName"}}
410 {{AssertType $ "Function"}}
411 {{TrimPrefix "vk" $.Name}}
412{{end}}
413
414
415{{/*
416-------------------------------------------------------------------------------
417 Emits a comma-separated list of C parameter names for the given command.
418-------------------------------------------------------------------------------
419*/}}
420{{define "Arguments"}}
421 {{AssertType $ "Function"}}
422
423 {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
424{{end}}
425
426
427{{/*
428------------------------------------------------------------------------------
429 Emit "true" for supported functions that undergo table dispatch. Only global
430 functions and functions handled in the loader top without calling into
431 lower layers are not dispatched.
432------------------------------------------------------------------------------
433*/}}
434{{define "IsInstanceDispatched"}}
435 {{AssertType $ "Function"}}
436 {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
437 {{if (ne $.Name "vkGetInstanceProcAddr")}}true{{end}}
438 {{end}}
439{{end}}
440
441
442{{/*
443------------------------------------------------------------------------------
444 Emit "true" for supported functions that can have device-specific dispatch.
445------------------------------------------------------------------------------
446*/}}
447{{define "IsDeviceDispatched"}}
448 {{AssertType $ "Function"}}
449 {{if (Macro "IsFunctionSupported" $)}}
450 {{if eq (Macro "Vtbl" $) "Device"}}
451 {{if ne $.Name "vkGetDeviceProcAddr"}}
452 true
453 {{end}}
454 {{end}}
455 {{end}}
456{{end}}
457
458
459{{/*
460------------------------------------------------------------------------------
461 Emit "true" if a function is core or from a supportable extension.
462------------------------------------------------------------------------------
463*/}}
464{{define "IsFunctionSupported"}}
465 {{AssertType $ "Function"}}
466 {{if not (GetAnnotation $ "pfn")}}
467 {{$ext := GetAnnotation $ "extension"}}
468 {{if not $ext}}true
469 {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
470 {{end}}
471 {{end}}
472{{end}}
473
474
475{{/*
476------------------------------------------------------------------------------
477 Decides whether a function should be exported from the Android Vulkan
478 library. Functions in the core API and in loader extensions are exported.
479------------------------------------------------------------------------------
480*/}}
481{{define "IsExported"}}
482 {{AssertType $ "Function"}}
483
484 {{$ext := GetAnnotation $ "extension"}}
485 {{if $ext}}
486 {{Macro "IsLoaderExtension" $ext}}
487 {{else}}
488 true
489 {{end}}
490{{end}}
491
492
493{{/*
494------------------------------------------------------------------------------
495 Reports whether an extension function is implemented entirely by the loader,
496 and not implemented by drivers.
497------------------------------------------------------------------------------
498*/}}
499{{define "IsLoaderFunction"}}
500 {{AssertType $ "Function"}}
501
502 {{$ext := GetAnnotation $ "extension"}}
503 {{if $ext}}
504 {{Macro "IsLoaderExtension" $ext}}
505 {{end}}
506{{end}}
507
508
509{{/*
510-------------------------------------------------------------------------------
511 Emit "true" if the loader has a top-level implementation for the function
512 that should be called directly rather than dispatching to the first layer.
513-------------------------------------------------------------------------------
514*/}}
515{{define "HasLoaderTopImpl"}}
516 {{AssertType $ "Function"}}
517
518 {{/* Global functions can't be dispatched */}}
519 {{ if and (not (GetAnnotation $ "pfn")) (eq (Macro "Vtbl" $) "Global")}}true
520
521 {{/* G*PA are implemented by reading the dispatch table, not by dispatching
522 through it. */}}
523 {{else if eq $.Name "vkGetInstanceProcAddr"}}true
524 {{else if eq $.Name "vkGetDeviceProcAddr"}}true
525
526 {{/* Loader top needs to initialize dispatch for device-level dispatchable
527 objects */}}
528 {{else if eq $.Name "vkGetDeviceQueue"}}true
529 {{else if eq $.Name "vkAllocateCommandBuffers"}}true
530
531 {{/* vkDestroy for dispatchable objects needs to handle VK_NULL_HANDLE;
532 trying to dispatch through that would crash. */}}
533 {{else if eq $.Name "vkDestroyInstance"}}true
534 {{else if eq $.Name "vkDestroyDevice"}}true
535
536 {{end}}
537{{end}}
538
539
540{{/*
541-------------------------------------------------------------------------------
542 Emit "true" if the loader has a bottom-level implementation for the function
543 which terminates the dispatch chain.
544-------------------------------------------------------------------------------
545*/}}
546{{define "HasLoaderBottomImpl"}}
547 {{AssertType $ "Function"}}
548
549 {{if (Macro "IsFunctionSupported" $)}}
550 {{ if (eq (Macro "Vtbl" $) "Instance")}}true
551 {{else if (Macro "IsLoaderFunction" $)}}true
552 {{else if (eq $.Name "vkCreateInstance")}}true
553 {{else if (eq $.Name "vkGetDeviceProcAddr")}}true
554 {{end}}
555 {{end}}
556{{end}}
557
558
559{{/*
560------------------------------------------------------------------------------
561 Emit "true" if an extension is unsupportable on Android.
562------------------------------------------------------------------------------
563*/}}
564{{define "IsExtensionBlacklisted"}}
565 {{$ext := index $.Arguments 0}}
566 {{ if eq $ext "VK_KHR_display"}}true
567 {{else if eq $ext "VK_KHR_display_swapchain"}}true
568 {{else if eq $ext "VK_KHR_xlib_surface"}}true
569 {{else if eq $ext "VK_KHR_xcb_surface"}}true
570 {{else if eq $ext "VK_KHR_wayland_surface"}}true
571 {{else if eq $ext "VK_KHR_mir_surface"}}true
572 {{else if eq $ext "VK_KHR_win32_surface"}}true
573 {{end}}
574{{end}}
575
576
577{{/*
578------------------------------------------------------------------------------
579 Reports whether an extension is implemented entirely by the loader,
580 so drivers should not enumerate it.
581------------------------------------------------------------------------------
582*/}}
583{{define "IsLoaderExtension"}}
584 {{$ext := index $.Arguments 0}}
585 {{ if eq $ext "VK_KHR_surface"}}true
586 {{else if eq $ext "VK_KHR_swapchain"}}true
587 {{else if eq $ext "VK_KHR_android_surface"}}true
588 {{end}}
589{{end}}