| {{/* |
| * Copyright 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */}} |
| |
| {{Include "../api/templates/vulkan_common.tmpl"}} |
| {{Global "clang-format" (Strings "clang-format" "-style=file")}} |
| {{Macro "DefineGlobals" $}} |
| {{$ | Macro "get_proc_addr.cpp" | Format (Global "clang-format") | Write "get_proc_addr.cpp"}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| Entry point |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "get_proc_addr.cpp"}} |
| /* |
| * Copyright 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| ¶ |
| // This file is generated. Do not edit manually! |
| // To regenerate: $ apic template ../api/vulkan.api get_proc_addr.cpp.tmpl |
| // Requires apic from https://android.googlesource.com/platform/tools/gpu/. |
| ¶ |
| #include <algorithm> |
| #include <log/log.h> |
| #include "loader.h" |
| using namespace vulkan; |
| ¶ |
| #define UNLIKELY(expr) __builtin_expect((expr), 0) |
| ¶ |
| namespace { |
| ¶ |
| struct NameProcEntry { |
| const char* name; |
| PFN_vkVoidFunction proc; |
| }; |
| ¶ |
| struct NameOffsetEntry { |
| const char* name; |
| size_t offset; |
| }; |
| ¶ |
| template <typename TEntry, size_t N> |
| const TEntry* FindProcEntry(const TEntry (&table)[N], const char* name) { |
| auto entry = std::lower_bound( |
| table, table + N, name, |
| [](const TEntry& e, const char* n) { return strcmp(e.name, n) < 0; }); |
| if (entry != (table + N) && strcmp(entry->name, name) == 0) |
| return entry; |
| return nullptr; |
| } |
| ¶ |
| const NameProcEntry kInstanceProcTbl[] = {« |
| // clang-format off |
| {{range $f := SortBy (AllCommands $) "FunctionName"}} |
| {{if and (Macro "IsDispatched" $f) (eq (Macro "Vtbl" $f) "Instance")}} |
| {"{{Macro "FunctionName" $f}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "FunctionName" $f}})}, |
| {{end}} |
| {{end}} |
| // clang-format on |
| »}; |
| ¶ |
| const NameProcEntry kDeviceProcTbl[] = {« |
| // clang-format off |
| {{range $f := SortBy (AllCommands $) "FunctionName"}} |
| {{if and (Macro "IsDispatched" $f) (eq (Macro "Vtbl" $f) "Device")}} |
| {"{{Macro "FunctionName" $f}}", reinterpret_cast<PFN_vkVoidFunction>({{Macro "FunctionName" $f}})}, |
| {{end}} |
| {{end}} |
| // clang-format on |
| »}; |
| ¶ |
| const NameOffsetEntry kInstanceOffsetTbl[] = {« |
| // clang-format off |
| {{range $f := SortBy (AllCommands $) "FunctionName"}} |
| {{if and (Macro "IsDispatched" $f) (eq (Macro "Vtbl" $f) "Instance")}} |
| {"{{Macro "FunctionName" $f}}", offsetof(InstanceVtbl, {{TrimPrefix "vk" (Macro "FunctionName" $f)}})}, |
| {{end}} |
| {{end}} |
| // clang-format on |
| »}; |
| ¶ |
| const NameOffsetEntry kDeviceOffsetTbl[] = {« |
| // clang-format off |
| {{range $f := SortBy (AllCommands $) "FunctionName"}} |
| {{if and (Macro "IsDispatched" $f) (eq (Macro "Vtbl" $f) "Device")}} |
| {"{{Macro "FunctionName" $f}}", offsetof(DeviceVtbl, {{TrimPrefix "vk" (Macro "FunctionName" $f)}})}, |
| {{end}} |
| {{end}} |
| // clang-format on |
| »}; |
| ¶ |
| } // namespace |
| ¶ |
| namespace vulkan { |
| ¶ |
| PFN_vkVoidFunction GetGlobalInstanceProcAddr(const char* name) { |
| const NameProcEntry* entry = FindProcEntry(kInstanceProcTbl, name); |
| if (entry) |
| return entry->proc; |
| // vkGetDeviceProcAddr must be available at the global/instance level for bootstrapping |
| if (strcmp(name, "vkGetDeviceProcAddr") == 0) |
| return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr); |
| return nullptr; |
| } |
| ¶ |
| PFN_vkVoidFunction GetGlobalDeviceProcAddr(const char* name) { |
| const NameProcEntry* entry = FindProcEntry(kDeviceProcTbl, name); |
| if (entry) |
| return entry->proc; |
| return nullptr; |
| } |
| ¶ |
| PFN_vkVoidFunction GetSpecificInstanceProcAddr(const InstanceVtbl* vtbl, |
| const char* name) { |
| size_t offset; |
| const NameOffsetEntry* entry = FindProcEntry(kInstanceOffsetTbl, name); |
| if (entry) |
| offset = entry->offset; |
| else |
| return nullptr; |
| const unsigned char* base = reinterpret_cast<const unsigned char*>(vtbl); |
| return *reinterpret_cast<PFN_vkVoidFunction*>( |
| const_cast<unsigned char*>(base) + offset); |
| } |
| ¶ |
| PFN_vkVoidFunction GetSpecificDeviceProcAddr(const DeviceVtbl* vtbl, |
| const char* name) { |
| size_t offset; |
| const NameOffsetEntry* entry = FindProcEntry(kDeviceOffsetTbl, name); |
| if (entry) |
| offset = entry->offset; |
| else |
| return nullptr; |
| const unsigned char* base = reinterpret_cast<const unsigned char*>(vtbl); |
| return *reinterpret_cast<PFN_vkVoidFunction*>( |
| const_cast<unsigned char*>(base) + offset); |
| } |
| ¶ |
| bool LoadInstanceVtbl(VkInstance instance, |
| VkInstance instance_next, |
| PFN_vkGetInstanceProcAddr get_proc_addr, |
| InstanceVtbl& vtbl) {« |
| bool success = true; |
| // clang-format off |
| vtbl.GetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(get_proc_addr(instance_next, "vkGetInstanceProcAddr")); |
| if (UNLIKELY(!vtbl.GetInstanceProcAddr)) { |
| ALOGE("missing instance proc: %s", "vkGetInstanceProcAddr"); |
| success = false; |
| } |
| vtbl.CreateInstance = reinterpret_cast<PFN_vkCreateInstance>(get_proc_addr(instance, "vkCreateInstance")); |
| if (UNLIKELY(!vtbl.CreateInstance)) { |
| // This is allowed to fail as the driver doesn't have to return vkCreateInstance when given an instance |
| } |
| {{range $f := AllCommands $}} |
| {{if eq (Macro "Vtbl" $f) "Instance"}} |
| {{if not (eq (Macro "FunctionName" $f) "vkGetInstanceProcAddr")}} |
| {{if not (GetAnnotation $f "extension")}} |
| vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}} = § |
| reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§ |
| get_proc_addr(instance, "{{Macro "FunctionName" $f}}")); |
| if (UNLIKELY(!vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}})) { |
| ALOGE("missing instance proc: %s", "{{Macro "FunctionName" $f}}"); |
| success = false; |
| } |
| {{end}} |
| {{end}} |
| {{end}} |
| {{end}} |
| {{range $f := AllCommands $}} |
| {{if eq (Macro "Vtbl" $f) "Instance"}} |
| {{if and (GetAnnotation $f "extension") (Macro "IsDispatched" $f)}} |
| vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}} = § |
| reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§ |
| get_proc_addr(instance, "{{Macro "FunctionName" $f}}")); |
| {{end}} |
| {{end}} |
| {{end}} |
| // clang-format on |
| return success; |
| »} |
| ¶ |
| bool LoadDeviceVtbl(VkDevice device, |
| VkDevice device_next, |
| PFN_vkGetDeviceProcAddr get_proc_addr, |
| DeviceVtbl& vtbl) {« |
| bool success = true; |
| // clang-format off |
| vtbl.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(get_proc_addr(device_next, "vkGetDeviceProcAddr")); |
| if (UNLIKELY(!vtbl.GetDeviceProcAddr)) { |
| ALOGE("missing device proc: %s", "vkGetDeviceProcAddr"); |
| success = false; |
| } |
| {{range $f := AllCommands $}} |
| {{if and (eq (Macro "Vtbl" $f) "Device") (not (eq (Macro "FunctionName" $f) "vkGetDeviceProcAddr"))}} |
| {{if not (GetAnnotation $f "extension")}} |
| vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}} = § |
| reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§ |
| get_proc_addr(device, "{{Macro "FunctionName" $f}}")); |
| if (UNLIKELY(!vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}})) { |
| ALOGE("missing device proc: %s", "{{Macro "FunctionName" $f}}"); |
| success = false; |
| } |
| {{end}} |
| {{end}} |
| {{end}} |
| {{range $f := AllCommands $}} |
| {{if eq (Macro "Vtbl" $f) "Device"}} |
| {{if and (GetAnnotation $f "extension") (Macro "IsDispatched" $f)}} |
| vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}} = § |
| reinterpret_cast<{{Macro "FunctionPtrName" $f}}>(§ |
| get_proc_addr(device, "{{Macro "FunctionName" $f}}")); |
| if (UNLIKELY(!vtbl.{{TrimPrefix "vk" (Macro "FunctionName" $f)}})) { |
| ALOGE("missing device proc: %s", "{{Macro "FunctionName" $f}}"); |
| success = false; |
| } |
| {{end}} |
| {{end}} |
| {{end}} |
| vtbl.GetSwapchainGrallocUsageANDROID = reinterpret_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(get_proc_addr(device, "vkGetSwapchainGrallocUsageANDROID")); |
| if (UNLIKELY(!vtbl.GetSwapchainGrallocUsageANDROID)) { |
| // TODO(jessehall): temporarily make this optional, until drivers have been updated |
| // ALOGE("missing device proc: %s", "vkGetSwapchainGrallocUsageANDROID"); |
| ALOGW("missing device proc: %s", "vkGetSwapchainGrallocUsageANDROID"); |
| // success = false; |
| } |
| vtbl.AcquireImageANDROID = reinterpret_cast<PFN_vkAcquireImageANDROID>(get_proc_addr(device, "vkAcquireImageANDROID")); |
| if (UNLIKELY(!vtbl.AcquireImageANDROID)) { |
| // TODO(jessehall): temporarily make this optional, until drivers have been updated |
| // ALOGE("missing device proc: %s", "vkImportNativeFenceANDROID"); |
| ALOGW("missing device proc: %s", "vkAcquireImageANDROID"); |
| // success = false; |
| } |
| vtbl.QueueSignalReleaseImageANDROID = reinterpret_cast<PFN_vkQueueSignalReleaseImageANDROID>(get_proc_addr(device, "vkQueueSignalReleaseImageANDROID")); |
| if (UNLIKELY(!vtbl.QueueSignalReleaseImageANDROID)) { |
| // TODO(jessehall): temporarily make this optional, until drivers have been updated |
| // ALOGE("missing device proc: %s", "vkQueueSignalReleaseImageANDROID"); |
| ALOGW("missing device proc: %s", "vkQueueSignalReleaseImageANDROID"); |
| // success = false; |
| } |
| // TODO(jessehall): these are deprecated; remove when drivers have been updated |
| vtbl.ImportNativeFenceANDROID = reinterpret_cast<PFN_vkImportNativeFenceANDROID>(get_proc_addr(device, "vkImportNativeFenceANDROID")); |
| vtbl.QueueSignalNativeFenceANDROID = reinterpret_cast<PFN_vkQueueSignalNativeFenceANDROID>(get_proc_addr(device, "vkQueueSignalNativeFenceANDROID")); |
| if (!((!vtbl.AcquireImageANDROID && !vtbl.QueueSignalReleaseImageANDROID && vtbl.ImportNativeFenceANDROID && vtbl.QueueSignalNativeFenceANDROID) || |
| (vtbl.AcquireImageANDROID && vtbl.QueueSignalReleaseImageANDROID && !vtbl.ImportNativeFenceANDROID && !vtbl.QueueSignalNativeFenceANDROID))) { |
| ALOGE("driver doesn't support exactly one of old- or new-style VK_ANDROID_native_buffer commands"); |
| success = false; |
| } |
| // clang-format on |
| return success; |
| »} |
| ¶ |
| } // namespace vulkan |
| ¶ |
| {{end}} |
| |
| |
| {{/* |
| ------------------------------------------------------------------------------- |
| This function emits nil for extension entrypoints that should not be |
| included in dispatch tables, "true" otherwise. Extensions that are ony used |
| directly between the loader and driver, or that aren't supported on Android |
| at all, should be excluded from dispatch. |
| ------------------------------------------------------------------------------- |
| */}} |
| {{define "IsUnsupportedExtension"}} |
| {{$ext := index $.Arguments 0}} |
| {{ if eq $ext "VK_KHR_display"}}true |
| {{else if eq $ext "VK_KHR_display_swapchain"}}true |
| {{else if eq $ext "VK_KHR_xlib_surface"}}true |
| {{else if eq $ext "VK_KHR_xcb_surface"}}true |
| {{else if eq $ext "VK_KHR_wayland_surface"}}true |
| {{else if eq $ext "VK_KHR_mir_surface"}}true |
| {{else if eq $ext "VK_KHR_win32_surface"}}true |
| {{end}} |
| {{end}} |
| |
| {{define "IsDispatched"}} |
| {{AssertType $ "Function"}} |
| {{$ext := GetAnnotation $ "extension"}} |
| {{if not $ext}}true |
| {{else if not (Macro "IsUnsupportedExtension" $ext)}}true |
| {{end}} |
| {{end}} |