blob: 0f1194c12b754a4085452a3a926275611f13ca16 [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>
Jesse Hall715b86a2016-01-16 16:34:29 -080047#include <vulkan/vk_ext_debug_report.h>
Jesse Hall1f91d392015-12-11 16:28:44 -080048#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"}}
Jesse Hall715b86a2016-01-16 16:34:29 -0800159 {{if (Macro "IsExported" $f)}}
Jesse Hall1f91d392015-12-11 16:28:44 -0800160 {"{{$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,
Jesse Hall6bd5dfa2016-01-16 17:13:30 -0800323 const InstanceExtensionSet& extensions,
Jesse Hall1f91d392015-12-11 16:28:44 -0800324 DriverDispatchTable& dispatch)
325 bool success = true;
326 // clang-format off
327 {{range $f := AllCommands $}}
328 {{if (Macro "IsInstanceDispatched" $f)}}
329 {{if not (Macro "IsLoaderFunction" $f)}}
Jesse Hall6bd5dfa2016-01-16 17:13:30 -0800330 {{$ext := GetAnnotation $f "extension"}}
331 {{if $ext}}
332 if (extensions[{{Macro "ExtensionConstant" $ext}}]) {
333 {{end}}
334 dispatch.{{Macro "BaseName" $f}} = §
335 reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§
336 get_proc_addr(instance, "{{$f.Name}}"));
337 if (UNLIKELY(!dispatch.{{Macro "BaseName" $f}})) {
338 ALOGE("missing driver proc: %s", "{{$f.Name}}");
339 success = false;
340 }
341 {{if $ext}}
Jesse Hall1f91d392015-12-11 16:28:44 -0800342 }
Jesse Hall6bd5dfa2016-01-16 17:13:30 -0800343 {{end}}
Jesse Hall1f91d392015-12-11 16:28:44 -0800344 {{end}}
345 {{end}}
346 {{end}}
347 dispatch.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(get_proc_addr(instance, "vkGetDeviceProcAddr"));
348 if (UNLIKELY(!dispatch.GetDeviceProcAddr)) {
349 ALOGE("missing driver proc: %s", "vkGetDeviceProcAddr");
350 success = false;
351 }
352 dispatch.CreateImage = reinterpret_cast<PFN_vkCreateImage>(get_proc_addr(instance, "vkCreateImage"));
353 if (UNLIKELY(!dispatch.CreateImage)) {
354 ALOGE("missing driver proc: %s", "vkCreateImage");
355 success = false;
356 }
357 dispatch.DestroyImage = reinterpret_cast<PFN_vkDestroyImage>(get_proc_addr(instance, "vkDestroyImage"));
358 if (UNLIKELY(!dispatch.DestroyImage)) {
359 ALOGE("missing driver proc: %s", "vkDestroyImage");
360 success = false;
361 }
Jesse Halld9132822016-01-14 15:50:52 -0800362 dispatch.GetSwapchainGrallocUsageANDROID = reinterpret_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(get_proc_addr(instance, "vkGetSwapchainGrallocUsageANDROID"));
363 if (UNLIKELY(!dispatch.GetSwapchainGrallocUsageANDROID)) {
364 ALOGE("missing driver proc: %s", "vkGetSwapchainGrallocUsageANDROID");
365 success = false;
366 }
Jesse Hall1f91d392015-12-11 16:28:44 -0800367 dispatch.AcquireImageANDROID = reinterpret_cast<PFN_vkAcquireImageANDROID>(get_proc_addr(instance, "vkAcquireImageANDROID"));
368 if (UNLIKELY(!dispatch.AcquireImageANDROID)) {
369 ALOGE("missing driver proc: %s", "vkAcquireImageANDROID");
370 success = false;
371 }
372 dispatch.QueueSignalReleaseImageANDROID = reinterpret_cast<PFN_vkQueueSignalReleaseImageANDROID>(get_proc_addr(instance, "vkQueueSignalReleaseImageANDROID"));
373 if (UNLIKELY(!dispatch.QueueSignalReleaseImageANDROID)) {
374 ALOGE("missing driver proc: %s", "vkQueueSignalReleaseImageANDROID");
375 success = false;
376 }
377 // clang-format on
378 return success;
379»}
380
381} // namespace vulkan
382
383// clang-format off
384
385{{range $f := AllCommands $}}
386 {{if and (not (GetAnnotation $f "pfn")) (Macro "IsExported" $f)}}
387 __attribute__((visibility("default")))
388 VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
389 {{if not (IsVoid $f.Return.Type)}}return §{{end}}
390 {{Macro "Dispatch" $f}}({{Macro "Arguments" $f}});
391 }
392
393 {{end}}
394{{end}}
395
396// clang-format on
397¶{{end}}
398
399
400{{/*
401-------------------------------------------------------------------------------
402 Emit the dispatch lookup for a function based on its first parameter.
403-------------------------------------------------------------------------------
404*/}}
405{{define "Dispatch"}}
406 {{AssertType $ "Function"}}
407
408 {{if (Macro "HasLoaderTopImpl" $)}}
409 {{Macro "BaseName" $}}_Top§
410 {{else}}
411 {{$p0 := index $.CallParameters 0}}
412 GetDispatchTable({{$p0.Name}}).{{Macro "BaseName" $}}§
413 {{end}}
414{{end}}
415
416
417{{/*
418-------------------------------------------------------------------------------
Jesse Hall6bd5dfa2016-01-16 17:13:30 -0800419 Map an extension name to InstanceExtension or DeviceExtension enum value
420-------------------------------------------------------------------------------
421*/}}
422{{define "ExtensionConstant"}}
423 {{$name := index $.Arguments 0}}
424 {{ if (eq $name "VK_KHR_surface")}}kKHR_surface
425 {{else if (eq $name "VK_KHR_android_surface")}}kKHR_android_surface
426 {{else if (eq $name "VK_EXT_debug_report")}}kEXT_debug_report
427 {{end}}
428{{end}}
429
430
431{{/*
432-------------------------------------------------------------------------------
Jesse Hall1f91d392015-12-11 16:28:44 -0800433 Emits a function name without the "vk" prefix.
434-------------------------------------------------------------------------------
435*/}}
436{{define "BaseName"}}
437 {{AssertType $ "Function"}}
438 {{TrimPrefix "vk" $.Name}}
439{{end}}
440
441
442{{/*
443-------------------------------------------------------------------------------
444 Emits a comma-separated list of C parameter names for the given command.
445-------------------------------------------------------------------------------
446*/}}
447{{define "Arguments"}}
448 {{AssertType $ "Function"}}
449
450 {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
451{{end}}
452
453
454{{/*
455------------------------------------------------------------------------------
456 Emit "true" for supported functions that undergo table dispatch. Only global
457 functions and functions handled in the loader top without calling into
458 lower layers are not dispatched.
459------------------------------------------------------------------------------
460*/}}
461{{define "IsInstanceDispatched"}}
462 {{AssertType $ "Function"}}
463 {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
464 {{if (ne $.Name "vkGetInstanceProcAddr")}}true{{end}}
465 {{end}}
466{{end}}
467
468
469{{/*
470------------------------------------------------------------------------------
471 Emit "true" for supported functions that can have device-specific dispatch.
472------------------------------------------------------------------------------
473*/}}
474{{define "IsDeviceDispatched"}}
475 {{AssertType $ "Function"}}
476 {{if (Macro "IsFunctionSupported" $)}}
477 {{if eq (Macro "Vtbl" $) "Device"}}
478 {{if ne $.Name "vkGetDeviceProcAddr"}}
479 true
480 {{end}}
481 {{end}}
482 {{end}}
483{{end}}
484
485
486{{/*
487------------------------------------------------------------------------------
488 Emit "true" if a function is core or from a supportable extension.
489------------------------------------------------------------------------------
490*/}}
491{{define "IsFunctionSupported"}}
492 {{AssertType $ "Function"}}
493 {{if not (GetAnnotation $ "pfn")}}
494 {{$ext := GetAnnotation $ "extension"}}
495 {{if not $ext}}true
496 {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
497 {{end}}
498 {{end}}
499{{end}}
500
501
502{{/*
503------------------------------------------------------------------------------
504 Decides whether a function should be exported from the Android Vulkan
505 library. Functions in the core API and in loader extensions are exported.
506------------------------------------------------------------------------------
507*/}}
508{{define "IsExported"}}
509 {{AssertType $ "Function"}}
510
Jesse Hall715b86a2016-01-16 16:34:29 -0800511 {{if (Macro "IsFunctionSupported" $)}}
512 {{$ext := GetAnnotation $ "extension"}}
513 {{if $ext}}
514 {{Macro "IsLoaderExtension" $ext}}
515 {{else}}
516 true
517 {{end}}
Jesse Hall1f91d392015-12-11 16:28:44 -0800518 {{end}}
519{{end}}
520
521
522{{/*
523------------------------------------------------------------------------------
524 Reports whether an extension function is implemented entirely by the loader,
525 and not implemented by drivers.
526------------------------------------------------------------------------------
527*/}}
528{{define "IsLoaderFunction"}}
529 {{AssertType $ "Function"}}
530
531 {{$ext := GetAnnotation $ "extension"}}
532 {{if $ext}}
533 {{Macro "IsLoaderExtension" $ext}}
534 {{end}}
535{{end}}
536
537
538{{/*
539-------------------------------------------------------------------------------
540 Emit "true" if the loader has a top-level implementation for the function
541 that should be called directly rather than dispatching to the first layer.
542-------------------------------------------------------------------------------
543*/}}
544{{define "HasLoaderTopImpl"}}
545 {{AssertType $ "Function"}}
546
547 {{/* Global functions can't be dispatched */}}
548 {{ if and (not (GetAnnotation $ "pfn")) (eq (Macro "Vtbl" $) "Global")}}true
549
550 {{/* G*PA are implemented by reading the dispatch table, not by dispatching
551 through it. */}}
552 {{else if eq $.Name "vkGetInstanceProcAddr"}}true
553 {{else if eq $.Name "vkGetDeviceProcAddr"}}true
554
555 {{/* Loader top needs to initialize dispatch for device-level dispatchable
556 objects */}}
557 {{else if eq $.Name "vkGetDeviceQueue"}}true
558 {{else if eq $.Name "vkAllocateCommandBuffers"}}true
559
560 {{/* vkDestroy for dispatchable objects needs to handle VK_NULL_HANDLE;
561 trying to dispatch through that would crash. */}}
562 {{else if eq $.Name "vkDestroyInstance"}}true
563 {{else if eq $.Name "vkDestroyDevice"}}true
564
565 {{end}}
566{{end}}
567
568
569{{/*
570-------------------------------------------------------------------------------
571 Emit "true" if the loader has a bottom-level implementation for the function
572 which terminates the dispatch chain.
573-------------------------------------------------------------------------------
574*/}}
575{{define "HasLoaderBottomImpl"}}
576 {{AssertType $ "Function"}}
577
578 {{if (Macro "IsFunctionSupported" $)}}
579 {{ if (eq (Macro "Vtbl" $) "Instance")}}true
580 {{else if (Macro "IsLoaderFunction" $)}}true
581 {{else if (eq $.Name "vkCreateInstance")}}true
582 {{else if (eq $.Name "vkGetDeviceProcAddr")}}true
583 {{end}}
584 {{end}}
585{{end}}
586
587
588{{/*
589------------------------------------------------------------------------------
590 Emit "true" if an extension is unsupportable on Android.
591------------------------------------------------------------------------------
592*/}}
593{{define "IsExtensionBlacklisted"}}
594 {{$ext := index $.Arguments 0}}
595 {{ if eq $ext "VK_KHR_display"}}true
596 {{else if eq $ext "VK_KHR_display_swapchain"}}true
597 {{else if eq $ext "VK_KHR_xlib_surface"}}true
598 {{else if eq $ext "VK_KHR_xcb_surface"}}true
599 {{else if eq $ext "VK_KHR_wayland_surface"}}true
600 {{else if eq $ext "VK_KHR_mir_surface"}}true
601 {{else if eq $ext "VK_KHR_win32_surface"}}true
602 {{end}}
603{{end}}
604
605
606{{/*
607------------------------------------------------------------------------------
608 Reports whether an extension is implemented entirely by the loader,
609 so drivers should not enumerate it.
610------------------------------------------------------------------------------
611*/}}
612{{define "IsLoaderExtension"}}
613 {{$ext := index $.Arguments 0}}
614 {{ if eq $ext "VK_KHR_surface"}}true
615 {{else if eq $ext "VK_KHR_swapchain"}}true
616 {{else if eq $ext "VK_KHR_android_surface"}}true
617 {{end}}
618{{end}}