blob: de348e76832578fd3c61a15df73ad109eec69dcc [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 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 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 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 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);
// special-case extension functions until they can be auto-generated
if (strcmp(name, "vkGetPhysicalDeviceSurfaceSupportKHR") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(vkGetPhysicalDeviceSurfaceSupportKHR);
return nullptr;
}
PFN_vkVoidFunction GetGlobalDeviceProcAddr(const char* name) {
const NameProcEntry* entry = FindProcEntry(kDeviceProcTbl, name);
if (entry)
return entry->proc;
// special-case extension functions until they can be auto-generated
if (strcmp(name, "vkGetSurfacePropertiesKHR") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePropertiesKHR);
if (strcmp(name, "vkGetSurfaceFormatsKHR") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfaceFormatsKHR);
if (strcmp(name, "vkGetSurfacePresentModesKHR") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(vkGetSurfacePresentModesKHR);
if (strcmp(name, "vkCreateSwapchainKHR") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR);
if (strcmp(name, "vkDestroySwapchainKHR") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR);
if (strcmp(name, "vkGetSwapchainImagesKHR") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR);
if (strcmp(name, "vkAcquireNextImageKHR") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR);
if (strcmp(name, "vkQueuePresentKHR") == 0)
return reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR);
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 if (strcmp(name, "vkGetPhysicalDeviceSurfaceSupportKHR") == 0)
offset = offsetof(InstanceVtbl, GetPhysicalDeviceSurfaceSupportKHR);
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 if (strcmp(name, "vkGetSurfacePropertiesKHR") == 0)
offset = offsetof(DeviceVtbl, GetSurfacePropertiesKHR);
else if (strcmp(name, "vkGetSurfaceFormatsKHR") == 0)
offset = offsetof(DeviceVtbl, GetSurfaceFormatsKHR);
else if (strcmp(name, "vkGetSurfacePresentModesKHR") == 0)
offset = offsetof(DeviceVtbl, GetSurfacePresentModesKHR);
else if (strcmp(name, "vkCreateSwapchainKHR") == 0)
offset = offsetof(DeviceVtbl, CreateSwapchainKHR);
else if (strcmp(name, "vkDestroySwapchainKHR") == 0)
offset = offsetof(DeviceVtbl, DestroySwapchainKHR);
else if (strcmp(name, "vkGetSwapchainImagesKHR") == 0)
offset = offsetof(DeviceVtbl, GetSwapchainImagesKHR);
else if (strcmp(name, "vkAcquireNextImageKHR") == 0)
offset = offsetof(DeviceVtbl, AcquireNextImageKHR);
else if (strcmp(name, "vkQueuePresentKHR") == 0)
offset = offsetof(DeviceVtbl, QueuePresentKHR);
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")}}
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}}
// 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 eq (Macro "Vtbl" $f) "Device"}}
{{if not (eq (Macro "FunctionName" $f) "vkGetDeviceProcAddr")}}
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.ImportNativeFenceANDROID = reinterpret_cast<PFN_vkImportNativeFenceANDROID>(get_proc_addr(device, "vkImportNativeFenceANDROID"));
if (UNLIKELY(!vtbl.ImportNativeFenceANDROID)) {
ALOGE("missing device proc: %s", "vkImportNativeFenceANDROID");
success = false;
}
vtbl.QueueSignalNativeFenceANDROID = reinterpret_cast<PFN_vkQueueSignalNativeFenceANDROID>(get_proc_addr(device, "vkQueueSignalNativeFenceANDROID"));
if (UNLIKELY(!vtbl.QueueSignalNativeFenceANDROID)) {
ALOGE("missing device proc: %s", "vkQueueSignalNativeFenceANDROID");
success = false;
}
// clang-format on
return success;
»}
} // namespace vulkan
{{end}}