blob: 423dea4d73f99704d55d7468f0fee919772d83c5 [file] [log] [blame]
{{/*
* 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}}