vulkan: Implement new vkGet*ProcAddrBehavior
The primary goal of this change is to switch to the revised GPA
behavior:
- GIPA(NULL, ..) only works for non-dispatched (global) commands
- GIPA(instance, ..) returns functions for commands that dispatch on any
object type, and the function works for any object of the appropriate
type if it is a child of the instance.
- GDPA(NULL, ..) returns NULL.
- GDPA(device, ..) returns a device-specific function for the command.
This change refactors/tidies many of the things it modified. Some
notable changes:
- All the loader generated code is now in dispatch.tmpl ->
dispatch_gen.{h,cpp}, instead of two separate templates.
- Reorganization allowed generating the dispatch table structures,
eliminating one source of frequent bugs.
- Removes some error-prone macro duplication.
- Handling of extensions and special loader functions is now much
more uniform and hopefully clearer.
- Loader top- and bottom-level functions are now consistently named with
_Top and _Bottom suffixes, and are grouped by level in loader.cpp.
- The VkInstance and VkDevice implementations are no longer derived from
::VkInstance_T and ::VkDevice_T. Was more trouble than it was worth.
- Renamed 'vtbl' to 'dispatch' in most places.
- Renamed nulldrv template and generated files to match the loader
naming pattern: null_driver.tmpl -> null_driver_gen.{h,cpp}
- Now all the entry point prototypes are generated, instead of having
to be updated by hand (another source of several bugs).
Change-Id: Ic263f802d0d523b18a0f00420b3a722aa04ce299
(cherry picked from commit 3cffb8e837222f413a1fe53522e2cc33366b8eeb)
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index cd3503f..f884e8b 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -46,6 +46,9 @@
namespace {
+// Define Handle typedef to be void* as returned from dlopen.
+typedef void* SharedLibraryHandle;
+
// These definitions are taken from the LunarG Vulkan Loader. They are used to
// enforce compatability between the Loader and Layers.
typedef void* (*PFN_vkGetProcAddr)(void* obj, const char* pName);
@@ -56,8 +59,7 @@
void* base_object;
} VkLayerLinkedListElem;
-// Define Handle typedef to be void* as returned from dlopen.
-typedef void* SharedLibraryHandle;
+// ----------------------------------------------------------------------------
// Standard-library allocator that delegates to VkAllocationCallbacks.
//
@@ -106,26 +108,21 @@
template <class Key,
class T,
class Hash = std::hash<Key>,
- class Pred = std::equal_to<Key> >
+ class Pred = std::equal_to<Key>>
using UnorderedMap =
std::unordered_map<Key,
T,
Hash,
Pred,
- CallbackAllocator<std::pair<const Key, T> > >;
+ CallbackAllocator<std::pair<const Key, T>>>;
template <class T>
-using Vector = std::vector<T, CallbackAllocator<T> >;
+using Vector = std::vector<T, CallbackAllocator<T>>;
-typedef std::basic_string<char,
- std::char_traits<char>,
- CallbackAllocator<char> > String;
+typedef std::basic_string<char, std::char_traits<char>, CallbackAllocator<char>>
+ String;
-} // namespace
-
-// -----------------------------------------------------------------------------
-
-namespace {
+// ----------------------------------------------------------------------------
struct LayerData {
String path;
@@ -135,86 +132,7 @@
typedef UnorderedMap<String, LayerData>::iterator LayerMapIterator;
-} // namespace
-
-struct VkInstance_T {
- VkInstance_T(const VkAllocationCallbacks* alloc_callbacks)
- : vtbl(&vtbl_storage),
- alloc(alloc_callbacks),
- num_physical_devices(0),
- layers(CallbackAllocator<std::pair<String, LayerData> >(alloc)),
- active_layers(CallbackAllocator<String>(alloc)) {
- pthread_mutex_init(&layer_lock, 0);
- memset(&vtbl_storage, 0, sizeof(vtbl_storage));
- memset(physical_devices, 0, sizeof(physical_devices));
- memset(&drv.vtbl, 0, sizeof(drv.vtbl));
- drv.GetDeviceProcAddr = nullptr;
- drv.num_physical_devices = 0;
- }
-
- ~VkInstance_T() { pthread_mutex_destroy(&layer_lock); }
-
- InstanceVtbl* vtbl;
- InstanceVtbl vtbl_storage;
-
- const VkAllocationCallbacks* alloc;
- uint32_t num_physical_devices;
- VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
-
- pthread_mutex_t layer_lock;
- // Map of layer names to layer data
- UnorderedMap<String, LayerData> layers;
- // Vector of layers active for this instance
- Vector<LayerMapIterator> active_layers;
- VkDbgMsgCallback message;
-
- struct Driver {
- // Pointers to driver entry points. Used explicitly by the loader; not
- // set as the dispatch table for any objects.
- InstanceVtbl vtbl;
-
- // Pointer to the driver's get_device_proc_addr, must be valid for any
- // of the driver's physical devices. Not part of the InstanceVtbl since
- // it's not an Instance/PhysicalDevice function.
- PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
-
- // Number of physical devices owned by this driver.
- uint32_t num_physical_devices;
- } drv; // may eventually be an array
-};
-
-// -----------------------------------------------------------------------------
-
-namespace {
-
-typedef VkInstance_T Instance;
-
-struct Device {
- Device(Instance* instance_input)
- : instance(instance_input),
- active_layers(CallbackAllocator<LayerMapIterator>(instance->alloc)) {
- memset(&vtbl_storage, 0, sizeof(vtbl_storage));
- vtbl_storage.device = this;
- }
- DeviceVtbl vtbl_storage;
- Instance* instance;
- // Vector of layers active for this device
- Vector<LayerMapIterator> active_layers;
-};
-
-// -----------------------------------------------------------------------------
-// Utility Code
-
-inline const InstanceVtbl* GetVtbl(VkPhysicalDevice physicalDevice) {
- return *reinterpret_cast<InstanceVtbl**>(physicalDevice);
-}
-
-inline const DeviceVtbl* GetVtbl(VkDevice device) {
- return *reinterpret_cast<DeviceVtbl**>(device);
-}
-inline const DeviceVtbl* GetVtbl(VkQueue queue) {
- return *reinterpret_cast<DeviceVtbl**>(queue);
-}
+// ----------------------------------------------------------------------------
VKAPI_ATTR void* DefaultAllocate(void*,
size_t size,
@@ -269,6 +187,8 @@
.pfnFree = DefaultFree,
};
+// ----------------------------------------------------------------------------
+
hwvulkan_device_t* g_hwdevice;
bool EnsureInitialized() {
static std::once_flag once_flag;
@@ -297,6 +217,112 @@
return module != nullptr && g_hwdevice != nullptr;
}
+// -----------------------------------------------------------------------------
+
+struct Instance {
+ Instance(const VkAllocationCallbacks* alloc_callbacks)
+ : dispatch_ptr(&dispatch),
+ handle(reinterpret_cast<VkInstance>(&dispatch_ptr)),
+ get_instance_proc_addr(nullptr),
+ alloc(alloc_callbacks),
+ num_physical_devices(0),
+ layers(CallbackAllocator<std::pair<String, LayerData>>(alloc)),
+ active_layers(CallbackAllocator<String>(alloc)),
+ message(VK_NULL_HANDLE) {
+ memset(&dispatch, 0, sizeof(dispatch));
+ memset(physical_devices, 0, sizeof(physical_devices));
+ pthread_mutex_init(&layer_lock, 0);
+ drv.instance = VK_NULL_HANDLE;
+ memset(&drv.dispatch, 0, sizeof(drv.dispatch));
+ drv.num_physical_devices = 0;
+ }
+
+ ~Instance() { pthread_mutex_destroy(&layer_lock); }
+
+ const InstanceDispatchTable* dispatch_ptr;
+ const VkInstance handle;
+ InstanceDispatchTable dispatch;
+
+ // TODO(jessehall): Only needed by GetInstanceProcAddr_Top for
+ // vkDbg*MessageCallback. Points to the outermost layer's function. Remove
+ // once the DEBUG_CALLBACK is integrated into the API file.
+ PFN_vkGetInstanceProcAddr get_instance_proc_addr;
+
+ const VkAllocationCallbacks* alloc;
+ uint32_t num_physical_devices;
+ VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
+
+ pthread_mutex_t layer_lock;
+ // Map of layer names to layer data
+ UnorderedMap<String, LayerData> layers;
+ // Vector of layers active for this instance
+ Vector<LayerMapIterator> active_layers;
+ VkDbgMsgCallback message;
+
+ struct {
+ VkInstance instance;
+ DriverDispatchTable dispatch;
+ uint32_t num_physical_devices;
+ } drv; // may eventually be an array
+};
+
+struct Device {
+ Device(Instance* instance_)
+ : instance(instance_),
+ active_layers(CallbackAllocator<LayerMapIterator>(instance->alloc)) {
+ memset(&dispatch, 0, sizeof(dispatch));
+ }
+ DeviceDispatchTable dispatch;
+ Instance* instance;
+ PFN_vkGetDeviceProcAddr get_device_proc_addr;
+ // Vector of layers active for this device
+ Vector<LayerMapIterator> active_layers;
+};
+
+template <typename THandle>
+struct HandleTraits {};
+template <>
+struct HandleTraits<VkInstance> {
+ typedef Instance LoaderObjectType;
+};
+template <>
+struct HandleTraits<VkPhysicalDevice> {
+ typedef Instance LoaderObjectType;
+};
+template <>
+struct HandleTraits<VkDevice> {
+ typedef Device LoaderObjectType;
+};
+template <>
+struct HandleTraits<VkQueue> {
+ typedef Device LoaderObjectType;
+};
+template <>
+struct HandleTraits<VkCommandBuffer> {
+ typedef Device LoaderObjectType;
+};
+
+template <typename THandle>
+typename HandleTraits<THandle>::LoaderObjectType& GetDispatchParent(
+ THandle handle) {
+ // TODO(jessehall): Make Instance and Device POD types (by removing the
+ // non-default constructors), so that offsetof is actually legal to use.
+ // The specific case we're using here is safe in gcc/clang (and probably
+ // most other C++ compilers), but isn't guaranteed by C++.
+ typedef typename HandleTraits<THandle>::LoaderObjectType ObjectType;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Winvalid-offsetof"
+ const size_t kDispatchOffset = offsetof(ObjectType, dispatch);
+#pragma clang diagnostic pop
+
+ const auto& dispatch = GetDispatchTable(handle);
+ uintptr_t dispatch_addr = reinterpret_cast<uintptr_t>(&dispatch);
+ uintptr_t object_addr = dispatch_addr - kDispatchOffset;
+ return *reinterpret_cast<ObjectType*>(object_addr);
+}
+
+// -----------------------------------------------------------------------------
+
void DestroyDevice(Device* device) {
const VkAllocationCallbacks* alloc = device->instance->alloc;
device->~Device();
@@ -393,16 +419,16 @@
object->active_layers.push_back(element);
}
-void DeactivateLayer(Instance* instance,
+void DeactivateLayer(Instance& instance,
Vector<LayerMapIterator>::iterator& element) {
LayerMapIterator& layer_map_data = *element;
LayerData& layer_data = layer_map_data->second;
- pthread_mutex_lock(&instance->layer_lock);
+ pthread_mutex_lock(&instance.layer_lock);
layer_data.ref_count--;
if (!layer_data.ref_count) {
dlclose(layer_data.handle);
}
- pthread_mutex_unlock(&instance->layer_lock);
+ pthread_mutex_unlock(&instance.layer_lock);
}
struct InstanceNamesPair {
@@ -436,7 +462,9 @@
}
template <class TInfo, class TObject>
-VkResult ActivateAllLayers(TInfo create_info, Instance* instance, TObject* object) {
+VkResult ActivateAllLayers(TInfo create_info,
+ Instance* instance,
+ TObject* object) {
ALOG_ASSERT(create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ||
create_info->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
"Cannot activate layers for unknown object %p", object);
@@ -469,9 +497,10 @@
auto element = instance->layers.find(layer_name);
if (element == instance->layers.end()) {
ALOGE("requested %s layer '%s' not present",
- create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO ?
- "instance" : "device",
- layer_name.c_str());
+ create_info->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
+ ? "instance"
+ : "device",
+ layer_name.c_str());
return VK_ERROR_LAYER_NOT_PRESENT;
} else {
ActivateLayer(object, instance, layer_name);
@@ -542,185 +571,142 @@
return VK_SUCCESS;
}
-VKAPI_ATTR PFN_vkVoidFunction
-GetLayerDeviceProcAddr(VkDevice device, const char* name) {
- // The static_casts are used to ensure that our function actually
- // matches the API function prototype. Otherwise, if the API function
- // prototype changes (only a problem during API development), the compiler
- // has no way of knowing that the function is supposed to match the
- // prototype, so won't warn us if they don't.
- if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkGetDeviceProcAddr>(GetLayerDeviceProcAddr));
- }
- if (strcmp(name, "vkCreateDevice") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(Noop);
- }
- // WSI extensions are not in the driver so return the loader functions
- if (strcmp(name, "vkCreateSwapchainKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkCreateSwapchainKHR>(CreateSwapchainKHR));
- }
- if (strcmp(name, "vkDestroySwapchainKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkDestroySwapchainKHR>(DestroySwapchainKHR));
- }
- if (strcmp(name, "vkGetSwapchainImagesKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkGetSwapchainImagesKHR>(GetSwapchainImagesKHR));
- }
- if (strcmp(name, "vkAcquireNextImageKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkAcquireNextImageKHR>(AcquireNextImageKHR));
- }
- if (strcmp(name, "vkQueuePresentKHR") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkQueuePresentKHR>(QueuePresentKHR));
- }
- if (!device)
- return GetGlobalDeviceProcAddr(name);
- Device* loader_device = reinterpret_cast<Device*>(GetVtbl(device)->device);
- return loader_device->instance->drv.GetDeviceProcAddr(device, name);
-}
+} // anonymous namespace
+
+namespace vulkan {
// -----------------------------------------------------------------------------
// "Bottom" functions. These are called at the end of the instance dispatch
// chain.
-VKAPI_ATTR
-void DestroyInstanceBottom(VkInstance instance,
- const VkAllocationCallbacks* allocator) {
- // These checks allow us to call DestroyInstanceBottom from any error path
- // in CreateInstanceBottom, before the driver instance is fully initialized.
- if (instance->drv.vtbl.instance != VK_NULL_HANDLE &&
- instance->drv.vtbl.DestroyInstance) {
- instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance,
- allocator);
- }
- if (instance->message) {
- PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
- DebugDestroyMessageCallback =
- reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
- vkGetInstanceProcAddr(instance, "vkDbgDestroyMsgCallback"));
- DebugDestroyMessageCallback(instance, instance->message);
- }
- for (auto it = instance->active_layers.begin();
- it != instance->active_layers.end(); ++it) {
- DeactivateLayer(instance, it);
- }
- const VkAllocationCallbacks* alloc = instance->alloc;
- instance->~VkInstance_T();
- alloc->pfnFree(alloc->pUserData, instance);
-}
-
-VKAPI_ATTR
-VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkInstance* instance_ptr) {
- Instance* instance = *instance_ptr;
+VkResult CreateInstance_Bottom(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* vkinstance) {
+ Instance& instance = GetDispatchParent(*vkinstance);
VkResult result;
- result = g_hwdevice->CreateInstance(create_info, instance->alloc,
- &instance->drv.vtbl.instance);
+ result = g_hwdevice->CreateInstance(create_info, instance.alloc,
+ &instance.drv.instance);
if (result != VK_SUCCESS) {
- DestroyInstanceBottom(instance, allocator);
+ DestroyInstance_Bottom(instance.handle, allocator);
return result;
}
- if (!LoadInstanceVtbl(
- instance->drv.vtbl.instance, instance->drv.vtbl.instance,
- g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
- DestroyInstanceBottom(instance, allocator);
+ if (!LoadDriverDispatchTable(instance.drv.instance,
+ g_hwdevice->GetInstanceProcAddr,
+ instance.drv.dispatch)) {
+ DestroyInstance_Bottom(instance.handle, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
- // vkGetDeviceProcAddr has a bootstrapping problem. We require that it be
- // queryable from the Instance, and that the resulting function work for any
- // VkDevice created from the instance.
- instance->drv.GetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
- g_hwdevice->GetInstanceProcAddr(instance->drv.vtbl.instance,
- "vkGetDeviceProcAddr"));
- if (!instance->drv.GetDeviceProcAddr) {
- ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
- DestroyInstanceBottom(instance, allocator);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- hwvulkan_dispatch_t* dispatch =
- reinterpret_cast<hwvulkan_dispatch_t*>(instance->drv.vtbl.instance);
- if (dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
- // Skip setting dispatch->vtbl on the driver instance handle, since we
- // never intentionally call through it; we go through Instance::drv.vtbl
- // instead.
+ hwvulkan_dispatch_t* drv_dispatch =
+ reinterpret_cast<hwvulkan_dispatch_t*>(instance.drv.instance);
+ if (drv_dispatch->magic == HWVULKAN_DISPATCH_MAGIC) {
+ // Skip setting drv_dispatch->vtbl, since we never call through it;
+ // we go through instance.drv.dispatch instead.
} else {
ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
- dispatch->magic);
- DestroyInstanceBottom(instance, allocator);
+ drv_dispatch->magic);
+ DestroyInstance_Bottom(instance.handle, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
uint32_t num_physical_devices = 0;
- result = instance->drv.vtbl.EnumeratePhysicalDevices(
- instance->drv.vtbl.instance, &num_physical_devices, nullptr);
+ result = instance.drv.dispatch.EnumeratePhysicalDevices(
+ instance.drv.instance, &num_physical_devices, nullptr);
if (result != VK_SUCCESS) {
- DestroyInstanceBottom(instance, allocator);
+ DestroyInstance_Bottom(instance.handle, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
- result = instance->drv.vtbl.EnumeratePhysicalDevices(
- instance->drv.vtbl.instance, &num_physical_devices,
- instance->physical_devices);
+ result = instance.drv.dispatch.EnumeratePhysicalDevices(
+ instance.drv.instance, &num_physical_devices,
+ instance.physical_devices);
if (result != VK_SUCCESS) {
- DestroyInstanceBottom(instance, allocator);
+ DestroyInstance_Bottom(instance.handle, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
for (uint32_t i = 0; i < num_physical_devices; i++) {
- dispatch = reinterpret_cast<hwvulkan_dispatch_t*>(
- instance->physical_devices[i]);
- if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
+ hwvulkan_dispatch_t* pdev_dispatch =
+ reinterpret_cast<hwvulkan_dispatch_t*>(
+ instance.physical_devices[i]);
+ if (pdev_dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
- dispatch->magic);
- DestroyInstanceBottom(instance, allocator);
+ pdev_dispatch->magic);
+ DestroyInstance_Bottom(instance.handle, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
- dispatch->vtbl = instance->vtbl;
+ pdev_dispatch->vtbl = instance.dispatch_ptr;
}
- instance->drv.num_physical_devices = num_physical_devices;
+ instance.drv.num_physical_devices = num_physical_devices;
- instance->num_physical_devices = instance->drv.num_physical_devices;
+ instance.num_physical_devices = instance.drv.num_physical_devices;
return VK_SUCCESS;
}
-VKAPI_ATTR
-VkResult EnumeratePhysicalDevicesBottom(VkInstance instance,
- uint32_t* pdev_count,
- VkPhysicalDevice* pdevs) {
- uint32_t count = instance->num_physical_devices;
+PFN_vkVoidFunction GetInstanceProcAddr_Bottom(VkInstance, const char* name) {
+ PFN_vkVoidFunction pfn;
+ if ((pfn = GetLoaderBottomProcAddr(name)))
+ return pfn;
+ // TODO: Possibly move this into the instance table
+ // TODO: Possibly register the callbacks in the loader
+ if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
+ strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
+ return reinterpret_cast<PFN_vkVoidFunction>(Noop);
+ }
+ return nullptr;
+}
+
+VkResult EnumeratePhysicalDevices_Bottom(VkInstance vkinstance,
+ uint32_t* pdev_count,
+ VkPhysicalDevice* pdevs) {
+ Instance& instance = GetDispatchParent(vkinstance);
+ uint32_t count = instance.num_physical_devices;
if (pdevs) {
count = std::min(count, *pdev_count);
- std::copy(instance->physical_devices,
- instance->physical_devices + count, pdevs);
+ std::copy(instance.physical_devices, instance.physical_devices + count,
+ pdevs);
}
*pdev_count = count;
return VK_SUCCESS;
}
-VKAPI_ATTR
-void GetPhysicalDeviceFeaturesBottom(VkPhysicalDevice pdev,
- VkPhysicalDeviceFeatures* features) {
- GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFeatures(pdev, features);
+void GetPhysicalDeviceProperties_Bottom(
+ VkPhysicalDevice pdev,
+ VkPhysicalDeviceProperties* properties) {
+ GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceProperties(
+ pdev, properties);
}
-VKAPI_ATTR
-void GetPhysicalDeviceFormatPropertiesBottom(VkPhysicalDevice pdev,
- VkFormat format,
- VkFormatProperties* properties) {
- GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceFormatProperties(
+void GetPhysicalDeviceFeatures_Bottom(VkPhysicalDevice pdev,
+ VkPhysicalDeviceFeatures* features) {
+ GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceFeatures(pdev,
+ features);
+}
+
+void GetPhysicalDeviceMemoryProperties_Bottom(
+ VkPhysicalDevice pdev,
+ VkPhysicalDeviceMemoryProperties* properties) {
+ GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceMemoryProperties(
+ pdev, properties);
+}
+
+void GetPhysicalDeviceQueueFamilyProperties_Bottom(
+ VkPhysicalDevice pdev,
+ uint32_t* pCount,
+ VkQueueFamilyProperties* properties) {
+ GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceQueueFamilyProperties(
+ pdev, pCount, properties);
+}
+
+void GetPhysicalDeviceFormatProperties_Bottom(VkPhysicalDevice pdev,
+ VkFormat format,
+ VkFormatProperties* properties) {
+ GetDispatchParent(pdev).drv.dispatch.GetPhysicalDeviceFormatProperties(
pdev, format, properties);
}
-VKAPI_ATTR
-VkResult GetPhysicalDeviceImageFormatPropertiesBottom(
+VkResult GetPhysicalDeviceImageFormatProperties_Bottom(
VkPhysicalDevice pdev,
VkFormat format,
VkImageType type,
@@ -728,41 +714,52 @@
VkImageUsageFlags usage,
VkImageCreateFlags flags,
VkImageFormatProperties* properties) {
- return GetVtbl(pdev)
- ->instance->drv.vtbl.GetPhysicalDeviceImageFormatProperties(
+ return GetDispatchParent(pdev)
+ .drv.dispatch.GetPhysicalDeviceImageFormatProperties(
pdev, format, type, tiling, usage, flags, properties);
}
-VKAPI_ATTR
-void GetPhysicalDevicePropertiesBottom(VkPhysicalDevice pdev,
- VkPhysicalDeviceProperties* properties) {
- GetVtbl(pdev)
- ->instance->drv.vtbl.GetPhysicalDeviceProperties(pdev, properties);
-}
-
-VKAPI_ATTR
-void GetPhysicalDeviceQueueFamilyPropertiesBottom(
+void GetPhysicalDeviceSparseImageFormatProperties_Bottom(
VkPhysicalDevice pdev,
- uint32_t* pCount,
- VkQueueFamilyProperties* properties) {
- GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceQueueFamilyProperties(
- pdev, pCount, properties);
+ VkFormat format,
+ VkImageType type,
+ VkSampleCountFlagBits samples,
+ VkImageUsageFlags usage,
+ VkImageTiling tiling,
+ uint32_t* properties_count,
+ VkSparseImageFormatProperties* properties) {
+ GetDispatchParent(pdev)
+ .drv.dispatch.GetPhysicalDeviceSparseImageFormatProperties(
+ pdev, format, type, samples, usage, tiling, properties_count,
+ properties);
}
VKAPI_ATTR
-void GetPhysicalDeviceMemoryPropertiesBottom(
+VkResult EnumerateDeviceExtensionProperties_Bottom(
VkPhysicalDevice pdev,
- VkPhysicalDeviceMemoryProperties* properties) {
- GetVtbl(pdev)->instance->drv.vtbl.GetPhysicalDeviceMemoryProperties(
- pdev, properties);
+ const char* layer_name,
+ uint32_t* properties_count,
+ VkExtensionProperties* properties) {
+ // TODO: what are we supposed to do with layer_name here?
+ return GetDispatchParent(pdev)
+ .drv.dispatch.EnumerateDeviceExtensionProperties(
+ pdev, layer_name, properties_count, properties);
}
VKAPI_ATTR
-VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
- const VkDeviceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkDevice* out_device) {
- Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
+VkResult EnumerateDeviceLayerProperties_Bottom(VkPhysicalDevice pdev,
+ uint32_t* properties_count,
+ VkLayerProperties* properties) {
+ return GetDispatchParent(pdev).drv.dispatch.EnumerateDeviceLayerProperties(
+ pdev, properties_count, properties);
+}
+
+VKAPI_ATTR
+VkResult CreateDevice_Bottom(VkPhysicalDevice pdev,
+ const VkDeviceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkDevice* device_out) {
+ Instance& instance = GetDispatchParent(pdev);
VkResult result;
if (!allocator) {
@@ -786,30 +783,35 @@
}
VkDevice drv_device;
- result = instance.drv.vtbl.CreateDevice(pdev, create_info, allocator,
- &drv_device);
+ result = instance.drv.dispatch.CreateDevice(pdev, create_info, allocator,
+ &drv_device);
if (result != VK_SUCCESS) {
DestroyDevice(device);
return result;
}
- hwvulkan_dispatch_t* dispatch =
+ hwvulkan_dispatch_t* drv_dispatch =
reinterpret_cast<hwvulkan_dispatch_t*>(drv_device);
- if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
- ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR, dispatch->magic);
+ if (drv_dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
+ ALOGE("invalid VkDevice dispatch magic: 0x%" PRIxPTR,
+ drv_dispatch->magic);
PFN_vkDestroyDevice destroy_device =
reinterpret_cast<PFN_vkDestroyDevice>(
- instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
+ instance.drv.dispatch.GetDeviceProcAddr(drv_device,
+ "vkDestroyDevice"));
destroy_device(drv_device, allocator);
DestroyDevice(device);
return VK_ERROR_INITIALIZATION_FAILED;
}
- dispatch->vtbl = &device->vtbl_storage;
+ drv_dispatch->vtbl = &device->dispatch;
+ device->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
+ instance.drv.dispatch.GetDeviceProcAddr(drv_device,
+ "vkGetDeviceProcAddr"));
void* base_object = static_cast<void*>(drv_device);
void* next_object = base_object;
VkLayerLinkedListElem* next_element;
- PFN_vkGetDeviceProcAddr next_get_proc_addr = GetLayerDeviceProcAddr;
+ PFN_vkGetDeviceProcAddr next_get_proc_addr = GetDeviceProcAddr_Bottom;
Vector<VkLayerLinkedListElem> elem_list(
device->active_layers.size(),
CallbackAllocator<VkLayerLinkedListElem>(instance.alloc));
@@ -840,123 +842,89 @@
}
}
- if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
- static_cast<VkDevice>(next_object), next_get_proc_addr,
- device->vtbl_storage)) {
+ // This is the magic call that initializes all the layer devices and
+ // allows them to create their device_handle -> device_data mapping.
+ next_get_proc_addr(static_cast<VkDevice>(next_object),
+ "vkGetDeviceProcAddr");
+
+ // We must create all the layer devices *before* retrieving the device
+ // procaddrs, so that the layers know which extensions are enabled and
+ // therefore which functions to return procaddrs for.
+ PFN_vkCreateDevice create_device = reinterpret_cast<PFN_vkCreateDevice>(
+ next_get_proc_addr(drv_device, "vkCreateDevice"));
+ create_device(pdev, create_info, allocator, &drv_device);
+
+ if (!LoadDeviceDispatchTable(static_cast<VkDevice>(base_object),
+ next_get_proc_addr, device->dispatch)) {
DestroyDevice(device);
return VK_ERROR_INITIALIZATION_FAILED;
}
- PFN_vkCreateDevice layer_createDevice =
- reinterpret_cast<PFN_vkCreateDevice>(
- device->vtbl_storage.GetDeviceProcAddr(drv_device,
- "vkCreateDevice"));
- layer_createDevice(pdev, create_info, allocator, &drv_device);
-
- // TODO(mlentine) : This is needed to use WSI layer validation. Remove this
- // when new version of layer initialization exits.
- if (!LoadDeviceVtbl(static_cast<VkDevice>(base_object),
- static_cast<VkDevice>(next_object), next_get_proc_addr,
- device->vtbl_storage)) {
- DestroyDevice(device);
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-
- *out_device = drv_device;
+ *device_out = drv_device;
return VK_SUCCESS;
}
-VKAPI_ATTR
-VkResult EnumerateDeviceExtensionPropertiesBottom(
- VkPhysicalDevice pdev,
- const char* layer_name,
- uint32_t* properties_count,
- VkExtensionProperties* properties) {
- // TODO: what are we supposed to do with layer_name here?
- return GetVtbl(pdev)->instance->drv.vtbl.EnumerateDeviceExtensionProperties(
- pdev, layer_name, properties_count, properties);
+void DestroyInstance_Bottom(VkInstance vkinstance,
+ const VkAllocationCallbacks* allocator) {
+ Instance& instance = GetDispatchParent(vkinstance);
+
+ // These checks allow us to call DestroyInstance_Bottom from any error
+ // path in CreateInstance_Bottom, before the driver instance is fully
+ // initialized.
+ if (instance.drv.instance != VK_NULL_HANDLE &&
+ instance.drv.dispatch.DestroyInstance) {
+ instance.drv.dispatch.DestroyInstance(instance.drv.instance, allocator);
+ }
+ if (instance.message) {
+ PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
+ DebugDestroyMessageCallback =
+ reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
+ vkGetInstanceProcAddr(vkinstance, "vkDbgDestroyMsgCallback"));
+ DebugDestroyMessageCallback(vkinstance, instance.message);
+ }
+ for (auto it = instance.active_layers.begin();
+ it != instance.active_layers.end(); ++it) {
+ DeactivateLayer(instance, it);
+ }
+ const VkAllocationCallbacks* alloc = instance.alloc;
+ instance.~Instance();
+ alloc->pfnFree(alloc->pUserData, &instance);
}
-VKAPI_ATTR
-VkResult EnumerateDeviceLayerPropertiesBottom(VkPhysicalDevice pdev,
- uint32_t* properties_count,
- VkLayerProperties* properties) {
- return GetVtbl(pdev)->instance->drv.vtbl.EnumerateDeviceLayerProperties(
- pdev, properties_count, properties);
-}
-
-VKAPI_ATTR
-void GetPhysicalDeviceSparseImageFormatPropertiesBottom(
- VkPhysicalDevice pdev,
- VkFormat format,
- VkImageType type,
- VkSampleCountFlagBits samples,
- VkImageUsageFlags usage,
- VkImageTiling tiling,
- uint32_t* properties_count,
- VkSparseImageFormatProperties* properties) {
- GetVtbl(pdev)
- ->instance->drv.vtbl.GetPhysicalDeviceSparseImageFormatProperties(
- pdev, format, type, samples, usage, tiling, properties_count,
- properties);
-}
-
-VKAPI_ATTR PFN_vkVoidFunction
-GetInstanceProcAddrBottom(VkInstance, const char*);
-
-const InstanceVtbl kBottomInstanceFunctions = {
- // clang-format off
- .instance = nullptr,
-
- .CreateInstance = CreateInstanceBottom,
- .DestroyInstance = DestroyInstanceBottom,
- .GetInstanceProcAddr = GetInstanceProcAddrBottom,
- .EnumeratePhysicalDevices = EnumeratePhysicalDevicesBottom,
-
- .GetPhysicalDeviceFeatures = GetPhysicalDeviceFeaturesBottom,
- .GetPhysicalDeviceFormatProperties = GetPhysicalDeviceFormatPropertiesBottom,
- .GetPhysicalDeviceImageFormatProperties = GetPhysicalDeviceImageFormatPropertiesBottom,
- .GetPhysicalDeviceProperties = GetPhysicalDevicePropertiesBottom,
- .GetPhysicalDeviceQueueFamilyProperties = GetPhysicalDeviceQueueFamilyPropertiesBottom,
- .GetPhysicalDeviceMemoryProperties = GetPhysicalDeviceMemoryPropertiesBottom,
- .CreateDevice = CreateDeviceBottom,
- .EnumerateDeviceExtensionProperties = EnumerateDeviceExtensionPropertiesBottom,
- .EnumerateDeviceLayerProperties = EnumerateDeviceLayerPropertiesBottom,
- .GetPhysicalDeviceSparseImageFormatProperties = GetPhysicalDeviceSparseImageFormatPropertiesBottom,
-
- .GetPhysicalDeviceSurfaceCapabilitiesKHR = GetPhysicalDeviceSurfaceCapabilitiesKHR,
- .GetPhysicalDeviceSurfaceFormatsKHR = GetPhysicalDeviceSurfaceFormatsKHR,
- .GetPhysicalDeviceSurfacePresentModesKHR = GetPhysicalDeviceSurfacePresentModesKHR,
- .CreateAndroidSurfaceKHR = CreateAndroidSurfaceKHR,
- .DestroySurfaceKHR = DestroySurfaceKHR,
- .GetPhysicalDeviceSurfaceSupportKHR = GetPhysicalDeviceSurfaceSupportKHR,
- // clang-format on
-};
-
-VKAPI_ATTR
-PFN_vkVoidFunction GetInstanceProcAddrBottom(VkInstance, const char* name) {
- // TODO: Possibly move this into the instance table
- // TODO: Possibly register the callbacks in the loader
- if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
- strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
+PFN_vkVoidFunction GetDeviceProcAddr_Bottom(VkDevice vkdevice,
+ const char* name) {
+ if (strcmp(name, "vkCreateDevice") == 0) {
+ // TODO(jessehall): Blegh, having this here is disgusting. The current
+ // layer init process can't call through the instance dispatch table's
+ // vkCreateDevice, because that goes through the instance layers rather
+ // than through the device layers. So we need to be able to get the
+ // vkCreateDevice pointer through the *device* layer chain.
+ //
+ // Because we've already created the driver device before calling
+ // through the layer vkCreateDevice functions, the loader bottom proc
+ // is a no-op.
return reinterpret_cast<PFN_vkVoidFunction>(Noop);
}
- if (strcmp(name, "vkCreateInstance") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkCreateInstance>(CreateInstanceBottom));
+
+ // VK_ANDROID_native_buffer should be hidden from applications and layers.
+ // TODO(jessehall): Generate this as part of GetLoaderBottomProcAddr.
+ PFN_vkVoidFunction pfn;
+ if (strcmp(name, "vkGetSwapchainGrallocUsageANDROID") == 0 ||
+ strcmp(name, "vkAcquireImageANDROID") == 0 ||
+ strcmp(name, "vkQueueSignalReleaseImageANDROID") == 0) {
+ return nullptr;
}
- return GetSpecificInstanceProcAddr(&kBottomInstanceFunctions, name);
+ if ((pfn = GetLoaderBottomProcAddr(name)))
+ return pfn;
+ return GetDispatchParent(vkdevice).get_device_proc_addr(vkdevice, name);
}
-} // namespace
-
// -----------------------------------------------------------------------------
-// Global functions. These are called directly from the loader entry points,
-// without going through a dispatch table.
+// Loader top functions. These are called directly from the loader entry
+// points or from the application (via vkGetInstanceProcAddr) without going
+// through a dispatch table.
-namespace vulkan {
-
-VkResult EnumerateInstanceExtensionProperties(
+VkResult EnumerateInstanceExtensionProperties_Top(
const char* /*layer_name*/,
uint32_t* count,
VkExtensionProperties* /*properties*/) {
@@ -970,8 +938,9 @@
return VK_SUCCESS;
}
-VkResult EnumerateInstanceLayerProperties(uint32_t* count,
- VkLayerProperties* /*properties*/) {
+VkResult EnumerateInstanceLayerProperties_Top(
+ uint32_t* count,
+ VkLayerProperties* /*properties*/) {
if (!EnsureInitialized())
return VK_ERROR_INITIALIZATION_FAILED;
@@ -982,9 +951,9 @@
return VK_SUCCESS;
}
-VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
- const VkAllocationCallbacks* allocator,
- VkInstance* out_instance) {
+VkResult CreateInstance_Top(const VkInstanceCreateInfo* create_info,
+ const VkAllocationCallbacks* allocator,
+ VkInstance* instance_out) {
VkResult result;
if (!EnsureInitialized())
@@ -1003,10 +972,6 @@
return VK_ERROR_OUT_OF_HOST_MEMORY;
Instance* instance = new (instance_mem) Instance(allocator);
- instance->vtbl_storage = kBottomInstanceFunctions;
- instance->vtbl_storage.instance = instance;
- instance->message = VK_NULL_HANDLE;
-
// Scan layers
CallbackAllocator<char> string_allocator(instance->alloc);
String dir_name("/data/local/debug/vulkan/", string_allocator);
@@ -1019,15 +984,14 @@
result = ActivateAllLayers(create_info, instance, instance);
if (result != VK_SUCCESS) {
- DestroyInstanceBottom(instance, allocator);
+ DestroyInstance_Bottom(instance->handle, allocator);
return result;
}
- void* base_object = static_cast<void*>(instance);
+ void* base_object = static_cast<void*>(instance->handle);
void* next_object = base_object;
VkLayerLinkedListElem* next_element;
- PFN_vkGetInstanceProcAddr next_get_proc_addr =
- kBottomInstanceFunctions.GetInstanceProcAddr;
+ PFN_vkGetInstanceProcAddr next_get_proc_addr = GetInstanceProcAddr_Bottom;
Vector<VkLayerLinkedListElem> elem_list(
instance->active_layers.size(),
CallbackAllocator<VkLayerLinkedListElem>(instance->alloc));
@@ -1058,11 +1022,16 @@
}
}
}
+ instance->get_instance_proc_addr = next_get_proc_addr;
- if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
- static_cast<VkInstance>(next_object),
- next_get_proc_addr, instance->vtbl_storage)) {
- DestroyInstanceBottom(instance, allocator);
+ // This is the magic call that initializes all the layer instances and
+ // allows them to create their instance_handle -> instance_data mapping.
+ next_get_proc_addr(static_cast<VkInstance>(next_object),
+ "vkGetInstanceProcAddr");
+
+ if (!LoadInstanceDispatchTable(static_cast<VkInstance>(base_object),
+ next_get_proc_addr, instance->dispatch)) {
+ DestroyInstance_Bottom(instance->handle, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -1079,9 +1048,11 @@
}
}
- *out_instance = instance;
- result = instance->vtbl_storage.CreateInstance(create_info, allocator,
- out_instance);
+ *instance_out = instance->handle;
+ PFN_vkCreateInstance create_instance =
+ reinterpret_cast<PFN_vkCreateInstance>(
+ next_get_proc_addr(instance->handle, "vkCreateInstance"));
+ result = create_instance(create_info, allocator, instance_out);
if (enable_callback)
FreeAllocatedCreateInfo(local_create_info, instance->alloc);
if (result <= 0) {
@@ -1095,154 +1066,133 @@
// - The layer must not call the next layer's DestroyInstance if that
// layer's CreateInstance wasn't called, or returned failure.
- // On failure, CreateInstanceBottom frees the instance struct, so it's
+ // On failure, CreateInstance_Bottom frees the instance struct, so it's
// already gone at this point. Nothing to do.
}
if (enable_logging) {
- PFN_vkDbgCreateMsgCallback DebugCreateMessageCallback;
- DebugCreateMessageCallback =
- reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
- vkGetInstanceProcAddr(instance, "vkDbgCreateMsgCallback"));
- DebugCreateMessageCallback(
- instance, VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
- LogDebugMessageCallback, NULL, &instance->message);
+ PFN_vkDbgCreateMsgCallback dbg_create_msg_callback;
+ dbg_create_msg_callback = reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
+ GetInstanceProcAddr_Top(instance->handle,
+ "vkDbgCreateMsgCallback"));
+ dbg_create_msg_callback(
+ instance->handle, VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
+ LogDebugMessageCallback, nullptr, &instance->message);
}
return result;
}
-PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
- if (!instance)
- return GetGlobalInstanceProcAddr(name);
- // TODO: Possibly move this into the instance table
+PFN_vkVoidFunction GetInstanceProcAddr_Top(VkInstance vkinstance,
+ const char* name) {
+ // vkGetInstanceProcAddr(NULL_HANDLE, ..) only works for global commands
+ if (!vkinstance)
+ return GetLoaderGlobalProcAddr(name);
+
+ const InstanceDispatchTable& dispatch = GetDispatchTable(vkinstance);
+ PFN_vkVoidFunction pfn;
+ // Always go through the loader-top function if there is one.
+ if ((pfn = GetLoaderTopProcAddr(name)))
+ return pfn;
+ // Otherwise, look up the handler in the instance dispatch table
+ if ((pfn = GetDispatchProcAddr(dispatch, name)))
+ return pfn;
+ // TODO(jessehall): Generate these into the instance dispatch table, and
+ // add loader-bottom procs for them.
if (strcmp(name, "vkDbgCreateMsgCallback") == 0 ||
strcmp(name, "vkDbgDestroyMsgCallback") == 0) {
- if (!instance->vtbl)
- return NULL;
- PFN_vkGetInstanceProcAddr gpa = instance->vtbl->GetInstanceProcAddr;
- return reinterpret_cast<PFN_vkVoidFunction>(gpa(instance, name));
+ return GetDispatchParent(vkinstance)
+ .get_instance_proc_addr(vkinstance, name);
}
- // For special-case functions we always return the loader entry
- if (strcmp(name, "vkGetInstanceProcAddr") == 0 ||
- strcmp(name, "vkGetDeviceProcAddr") == 0) {
- return GetGlobalInstanceProcAddr(name);
- }
- return GetSpecificInstanceProcAddr(instance->vtbl, name);
+ // Anything not handled already must be a device-dispatched function
+ // without a loader-top. We must return a function that will dispatch based
+ // on the dispatchable object parameter -- which is exactly what the
+ // exported functions do. So just return them here.
+ return GetLoaderExportProcAddr(name);
}
-PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name) {
+void DestroyInstance_Top(VkInstance instance,
+ const VkAllocationCallbacks* allocator) {
+ if (!instance)
+ return;
+ GetDispatchTable(instance).DestroyInstance(instance, allocator);
+}
+
+PFN_vkVoidFunction GetDeviceProcAddr_Top(VkDevice device, const char* name) {
+ PFN_vkVoidFunction pfn;
if (!device)
- return GetGlobalDeviceProcAddr(name);
- if (strcmp(name, "vkGetDeviceProcAddr") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr));
- }
- if (strcmp(name, "vkGetDeviceQueue") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue));
- }
- if (strcmp(name, "vkAllocateCommandBuffers") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkAllocateCommandBuffers>(AllocateCommandBuffers));
- }
- if (strcmp(name, "vkDestroyDevice") == 0) {
- return reinterpret_cast<PFN_vkVoidFunction>(
- static_cast<PFN_vkDestroyDevice>(DestroyDevice));
- }
- return GetSpecificDeviceProcAddr(GetVtbl(device), name);
+ return nullptr;
+ if ((pfn = GetLoaderTopProcAddr(name)))
+ return pfn;
+ return GetDispatchProcAddr(GetDispatchTable(device), name);
}
-void GetDeviceQueue(VkDevice drv_device,
- uint32_t family,
- uint32_t index,
- VkQueue* out_queue) {
- VkResult result;
- VkQueue queue;
- const DeviceVtbl* vtbl = GetVtbl(drv_device);
- vtbl->GetDeviceQueue(drv_device, family, index, &queue);
- hwvulkan_dispatch_t* dispatch =
- reinterpret_cast<hwvulkan_dispatch_t*>(queue);
- if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != vtbl)
- ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR, dispatch->magic);
- dispatch->vtbl = vtbl;
- *out_queue = queue;
+void GetDeviceQueue_Top(VkDevice vkdevice,
+ uint32_t family,
+ uint32_t index,
+ VkQueue* queue_out) {
+ const auto& table = GetDispatchTable(vkdevice);
+ table.GetDeviceQueue(vkdevice, family, index, queue_out);
+ hwvulkan_dispatch_t* queue_dispatch =
+ reinterpret_cast<hwvulkan_dispatch_t*>(*queue_out);
+ if (queue_dispatch->magic != HWVULKAN_DISPATCH_MAGIC &&
+ queue_dispatch->vtbl != &table)
+ ALOGE("invalid VkQueue dispatch magic: 0x%" PRIxPTR,
+ queue_dispatch->magic);
+ queue_dispatch->vtbl = &table;
}
-VkResult AllocateCommandBuffers(VkDevice device,
- const VkCommandBufferAllocateInfo* alloc_info,
- VkCommandBuffer* cmdbufs) {
- const DeviceVtbl* vtbl = GetVtbl(device);
- VkResult result = vtbl->AllocateCommandBuffers(device, alloc_info, cmdbufs);
+VkResult AllocateCommandBuffers_Top(
+ VkDevice vkdevice,
+ const VkCommandBufferAllocateInfo* alloc_info,
+ VkCommandBuffer* cmdbufs) {
+ const auto& table = GetDispatchTable(vkdevice);
+ VkResult result =
+ table.AllocateCommandBuffers(vkdevice, alloc_info, cmdbufs);
if (result != VK_SUCCESS)
return result;
for (uint32_t i = 0; i < alloc_info->bufferCount; i++) {
- hwvulkan_dispatch_t* dispatch =
+ hwvulkan_dispatch_t* cmdbuf_dispatch =
reinterpret_cast<hwvulkan_dispatch_t*>(cmdbufs[i]);
- ALOGE_IF(dispatch->magic != HWVULKAN_DISPATCH_MAGIC,
+ ALOGE_IF(cmdbuf_dispatch->magic != HWVULKAN_DISPATCH_MAGIC,
"invalid VkCommandBuffer dispatch magic: 0x%" PRIxPTR,
- dispatch->magic);
- dispatch->vtbl = vtbl;
+ cmdbuf_dispatch->magic);
+ cmdbuf_dispatch->vtbl = &table;
}
return VK_SUCCESS;
}
-void DestroyDevice(VkDevice drv_device,
- const VkAllocationCallbacks* /*allocator*/) {
- const DeviceVtbl* vtbl = GetVtbl(drv_device);
- Device* device = static_cast<Device*>(vtbl->device);
- for (auto it = device->active_layers.begin();
- it != device->active_layers.end(); ++it) {
- DeactivateLayer(device->instance, it);
+void DestroyDevice_Top(VkDevice vkdevice,
+ const VkAllocationCallbacks* /*allocator*/) {
+ if (!vkdevice)
+ return;
+ Device& device = GetDispatchParent(vkdevice);
+ // TODO(jessehall): This seems very wrong. We might close a layer library
+ // right before we call DestroyDevice in it.
+ for (auto it = device.active_layers.begin();
+ it != device.active_layers.end(); ++it) {
+ DeactivateLayer(*device.instance, it);
}
- vtbl->DestroyDevice(drv_device, device->instance->alloc);
- DestroyDevice(device);
+ device.dispatch.DestroyDevice(vkdevice, device.instance->alloc);
+ DestroyDevice(&device);
}
-void* AllocMem(VkInstance instance,
- size_t size,
- size_t align,
- VkSystemAllocationScope scope) {
- const VkAllocationCallbacks* alloc_cb = instance->alloc;
- return alloc_cb->pfnAllocation(alloc_cb->pUserData, size, align, scope);
+// -----------------------------------------------------------------------------
+
+const VkAllocationCallbacks* GetAllocator(VkInstance vkinstance) {
+ return GetDispatchParent(vkinstance).alloc;
}
-void FreeMem(VkInstance instance, void* ptr) {
- const VkAllocationCallbacks* alloc_cb = instance->alloc;
- alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
+const VkAllocationCallbacks* GetAllocator(VkDevice vkdevice) {
+ return GetDispatchParent(vkdevice).instance->alloc;
}
-void* AllocMem(VkDevice device,
- size_t size,
- size_t align,
- VkSystemAllocationScope scope) {
- const VkAllocationCallbacks* alloc_cb =
- static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
- return alloc_cb->pfnAllocation(alloc_cb->pUserData, size, align, scope);
+const DriverDispatchTable& GetDriverDispatch(VkDevice device) {
+ return GetDispatchParent(device).instance->drv.dispatch;
}
-void FreeMem(VkDevice device, void* ptr) {
- const VkAllocationCallbacks* alloc_cb =
- static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
- alloc_cb->pfnFree(alloc_cb->pUserData, ptr);
-}
-
-const DeviceVtbl& GetDriverVtbl(VkDevice device) {
- // TODO(jessehall): This actually returns the API-level vtbl for the
- // device, not the driver entry points. Given the current use -- getting
- // the driver's private swapchain-related functions -- that works, but is
- // misleading and likely to cause bugs. Fix as part of separating the
- // loader->driver interface from the app->loader interface.
- return static_cast<Device*>(GetVtbl(device)->device)->vtbl_storage;
-}
-
-const DeviceVtbl& GetDriverVtbl(VkQueue queue) {
- // TODO(jessehall): This actually returns the API-level vtbl for the
- // device, not the driver entry points. Given the current use -- getting
- // the driver's private swapchain-related functions -- that works, but is
- // misleading and likely to cause bugs. Fix as part of separating the
- // loader->driver interface from the app->loader interface.
- return static_cast<Device*>(GetVtbl(queue)->device)->vtbl_storage;
+const DriverDispatchTable& GetDriverDispatch(VkQueue queue) {
+ return GetDispatchParent(queue).instance->drv.dispatch;
}
} // namespace vulkan