vulkan: Update from version 0.186.0 to 0.188.0
Change-Id: Ida08d51f4e892202b594072d1e765ba5c55444db
(cherry picked from commit 2ca0449bdeecd0257c7473f663896b00d0082def)
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index a44026f..10877c5 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -22,8 +22,8 @@
#include <dirent.h>
#include <dlfcn.h>
#include <inttypes.h>
-#include <malloc.h>
#include <pthread.h>
+#include <stdlib.h>
#include <string.h>
// standard C++ headers
#include <algorithm>
@@ -58,7 +58,13 @@
// Define Handle typedef to be void* as returned from dlopen.
typedef void* SharedLibraryHandle;
-// Custom versions of std classes that use the vulkan alloc callback.
+// Standard-library allocator that delegates to VkAllocCallbacks.
+//
+// TODO(jessehall): This class currently always uses
+// VK_SYSTEM_ALLOC_SCOPE_INSTANCE. The scope to use could be a template
+// parameter or a constructor parameter. The former would help catch bugs
+// where we use the wrong scope, e.g. adding a command-scope string to an
+// instance-scope vector. But that might also be pretty annoying to deal with.
template <class T>
class CallbackAllocator {
public:
@@ -73,7 +79,7 @@
T* allocate(std::size_t n) {
void* mem = alloc->pfnAlloc(alloc->pUserData, n * sizeof(T), alignof(T),
- VK_SYSTEM_ALLOC_TYPE_INTERNAL);
+ VK_SYSTEM_ALLOC_SCOPE_INSTANCE);
return static_cast<T*>(mem);
}
@@ -208,8 +214,43 @@
return *reinterpret_cast<DeviceVtbl**>(queue);
}
-void* DefaultAlloc(void*, size_t size, size_t alignment, VkSystemAllocType) {
- return memalign(alignment, size);
+void* DefaultAlloc(void*, size_t size, size_t alignment, VkSystemAllocScope) {
+ void* ptr = nullptr;
+ // Vulkan requires 'alignment' to be a power of two, but posix_memalign
+ // additionally requires that it be at least sizeof(void*).
+ return posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size) == 0
+ ? ptr
+ : nullptr;
+}
+
+void* DefaultRealloc(void*,
+ void* ptr,
+ size_t size,
+ size_t alignment,
+ VkSystemAllocScope) {
+ if (size == 0) {
+ free(ptr);
+ return nullptr;
+ }
+
+ // TODO(jessehall): Right now we never shrink allocations; if the new
+ // request is smaller than the existing chunk, we just continue using it.
+ // Right now the loader never reallocs, so this doesn't matter. If that
+ // changes, or if this code is copied into some other project, this should
+ // probably have a heuristic to allocate-copy-free when doing so will save
+ // "enough" space.
+ size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
+ if (size <= old_size)
+ return ptr;
+
+ void* new_ptr = nullptr;
+ if (posix_memalign(&new_ptr, alignment, size) != 0)
+ return nullptr;
+ if (ptr) {
+ memcpy(new_ptr, ptr, std::min(old_size, size));
+ free(ptr);
+ }
+ return new_ptr;
}
void DefaultFree(void*, void* pMem) {
@@ -219,6 +260,7 @@
const VkAllocCallbacks kDefaultAllocCallbacks = {
.pUserData = nullptr,
.pfnAlloc = DefaultAlloc,
+ .pfnRealloc = DefaultRealloc,
.pfnFree = DefaultFree,
};
@@ -418,7 +460,7 @@
}
}
// Load app layers
- for (uint32_t i = 0; i < create_info->layerCount; ++i) {
+ for (uint32_t i = 0; i < create_info->enabledLayerNameCount; ++i) {
String layer_name(create_info->ppEnabledLayerNames[i],
string_allocator);
auto element = instance->layers.find(layer_name);
@@ -439,17 +481,18 @@
bool AddExtensionToCreateInfo(TCreateInfo& local_create_info,
const char* extension_name,
const VkAllocCallbacks* alloc) {
- for (uint32_t i = 0; i < local_create_info.extensionCount; ++i) {
+ for (uint32_t i = 0; i < local_create_info.enabledExtensionNameCount; ++i) {
if (!strcmp(extension_name,
local_create_info.ppEnabledExtensionNames[i])) {
return false;
}
}
- uint32_t extension_count = local_create_info.extensionCount;
- local_create_info.extensionCount++;
+ uint32_t extension_count = local_create_info.enabledExtensionNameCount;
+ local_create_info.enabledExtensionNameCount++;
void* mem = alloc->pfnAlloc(
- alloc->pUserData, local_create_info.extensionCount * sizeof(char*),
- alignof(char*), VK_SYSTEM_ALLOC_TYPE_INTERNAL);
+ alloc->pUserData,
+ local_create_info.enabledExtensionNameCount * sizeof(char*),
+ alignof(char*), VK_SYSTEM_ALLOC_SCOPE_INSTANCE);
if (mem) {
const char** enabled_extensions = static_cast<const char**>(mem);
for (uint32_t i = 0; i < extension_count; ++i) {
@@ -461,7 +504,7 @@
} else {
ALOGW("%s extension cannot be enabled: memory allocation failed",
extension_name);
- local_create_info.extensionCount--;
+ local_create_info.enabledExtensionNameCount--;
return false;
}
return true;
@@ -537,12 +580,14 @@
// "Bottom" functions. These are called at the end of the instance dispatch
// chain.
-void DestroyInstanceBottom(VkInstance instance) {
+void DestroyInstanceBottom(VkInstance instance,
+ const VkAllocCallbacks* 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);
+ instance->drv.vtbl.DestroyInstance(instance->drv.vtbl.instance,
+ allocator);
}
if (instance->message) {
PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
@@ -561,21 +606,22 @@
}
VkResult CreateInstanceBottom(const VkInstanceCreateInfo* create_info,
+ const VkAllocCallbacks* allocator,
VkInstance* instance_ptr) {
Instance* instance = *instance_ptr;
VkResult result;
- result =
- g_hwdevice->CreateInstance(create_info, &instance->drv.vtbl.instance);
+ result = g_hwdevice->CreateInstance(create_info, instance->alloc,
+ &instance->drv.vtbl.instance);
if (result != VK_SUCCESS) {
- DestroyInstanceBottom(instance);
+ DestroyInstanceBottom(instance, allocator);
return result;
}
if (!LoadInstanceVtbl(
instance->drv.vtbl.instance, instance->drv.vtbl.instance,
g_hwdevice->GetInstanceProcAddr, instance->drv.vtbl)) {
- DestroyInstanceBottom(instance);
+ DestroyInstanceBottom(instance, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -587,7 +633,7 @@
"vkGetDeviceProcAddr"));
if (!instance->drv.GetDeviceProcAddr) {
ALOGE("missing instance proc: \"%s\"", "vkGetDeviceProcAddr");
- DestroyInstanceBottom(instance);
+ DestroyInstanceBottom(instance, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -600,7 +646,7 @@
} else {
ALOGE("invalid VkInstance dispatch magic: 0x%" PRIxPTR,
dispatch->magic);
- DestroyInstanceBottom(instance);
+ DestroyInstanceBottom(instance, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -608,7 +654,7 @@
result = instance->drv.vtbl.EnumeratePhysicalDevices(
instance->drv.vtbl.instance, &num_physical_devices, nullptr);
if (result != VK_SUCCESS) {
- DestroyInstanceBottom(instance);
+ DestroyInstanceBottom(instance, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
num_physical_devices = std::min(num_physical_devices, kMaxPhysicalDevices);
@@ -616,7 +662,7 @@
instance->drv.vtbl.instance, &num_physical_devices,
instance->physical_devices);
if (result != VK_SUCCESS) {
- DestroyInstanceBottom(instance);
+ DestroyInstanceBottom(instance, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
for (uint32_t i = 0; i < num_physical_devices; i++) {
@@ -625,7 +671,7 @@
if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC) {
ALOGE("invalid VkPhysicalDevice dispatch magic: 0x%" PRIxPTR,
dispatch->magic);
- DestroyInstanceBottom(instance);
+ DestroyInstanceBottom(instance, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
dispatch->vtbl = instance->vtbl;
@@ -696,13 +742,21 @@
VkResult CreateDeviceBottom(VkPhysicalDevice pdev,
const VkDeviceCreateInfo* create_info,
+ const VkAllocCallbacks* allocator,
VkDevice* out_device) {
Instance& instance = *static_cast<Instance*>(GetVtbl(pdev)->instance);
VkResult result;
- void* mem = instance.alloc->pfnAlloc(instance.alloc->pUserData,
- sizeof(Device), alignof(Device),
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ if (!allocator) {
+ if (instance.alloc)
+ allocator = instance.alloc;
+ else
+ allocator = &kDefaultAllocCallbacks;
+ }
+
+ void* mem =
+ allocator->pfnAlloc(allocator->pUserData, sizeof(Device),
+ alignof(Device), VK_SYSTEM_ALLOC_SCOPE_DEVICE);
if (!mem)
return VK_ERROR_OUT_OF_HOST_MEMORY;
Device* device = new (mem) Device(&instance);
@@ -714,7 +768,8 @@
}
VkDevice drv_device;
- result = instance.drv.vtbl.CreateDevice(pdev, create_info, &drv_device);
+ result = instance.drv.vtbl.CreateDevice(pdev, create_info, allocator,
+ &drv_device);
if (result != VK_SUCCESS) {
DestroyDevice(device);
return result;
@@ -727,7 +782,7 @@
PFN_vkDestroyDevice destroy_device =
reinterpret_cast<PFN_vkDestroyDevice>(
instance.drv.GetDeviceProcAddr(drv_device, "vkDestroyDevice"));
- destroy_device(drv_device);
+ destroy_device(drv_device, allocator);
DestroyDevice(device);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -778,7 +833,7 @@
reinterpret_cast<PFN_vkCreateDevice>(
device->vtbl_storage.GetDeviceProcAddr(drv_device,
"vkCreateDevice"));
- layer_createDevice(pdev, create_info, &drv_device);
+ 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.
@@ -896,23 +951,25 @@
}
VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
+ const VkAllocCallbacks* allocator,
VkInstance* out_instance) {
VkResult result;
if (!EnsureInitialized())
return VK_ERROR_INITIALIZATION_FAILED;
+ if (!allocator)
+ allocator = &kDefaultAllocCallbacks;
+
VkInstanceCreateInfo local_create_info = *create_info;
- if (!local_create_info.pAllocCb)
- local_create_info.pAllocCb = &kDefaultAllocCallbacks;
create_info = &local_create_info;
- void* instance_mem = create_info->pAllocCb->pfnAlloc(
- create_info->pAllocCb->pUserData, sizeof(Instance), alignof(Instance),
- VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
+ void* instance_mem =
+ allocator->pfnAlloc(allocator->pUserData, sizeof(Instance),
+ alignof(Instance), VK_SYSTEM_ALLOC_SCOPE_INSTANCE);
if (!instance_mem)
return VK_ERROR_OUT_OF_HOST_MEMORY;
- Instance* instance = new (instance_mem) Instance(create_info->pAllocCb);
+ Instance* instance = new (instance_mem) Instance(allocator);
instance->vtbl_storage = kBottomInstanceFunctions;
instance->vtbl_storage.instance = instance;
@@ -930,7 +987,7 @@
result = ActivateAllLayers(create_info, instance, instance);
if (result != VK_SUCCESS) {
- DestroyInstanceBottom(instance);
+ DestroyInstanceBottom(instance, allocator);
return result;
}
@@ -973,7 +1030,7 @@
if (!LoadInstanceVtbl(static_cast<VkInstance>(base_object),
static_cast<VkInstance>(next_object),
next_get_proc_addr, instance->vtbl_storage)) {
- DestroyInstanceBottom(instance);
+ DestroyInstanceBottom(instance, allocator);
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -988,7 +1045,8 @@
}
*out_instance = instance;
- result = instance->vtbl_storage.CreateInstance(create_info, out_instance);
+ result = instance->vtbl_storage.CreateInstance(create_info, allocator,
+ out_instance);
if (enable_callback)
FreeAllocatedCreateInfo(local_create_info, instance->alloc);
if (result <= 0) {
@@ -1079,7 +1137,7 @@
VkResult result = vtbl->AllocCommandBuffers(device, alloc_info, cmdbuffers);
if (result != VK_SUCCESS)
return result;
- for (uint32_t i = 0; i < alloc_info->count; i++) {
+ for (uint32_t i = 0; i < alloc_info->bufferCount; i++) {
hwvulkan_dispatch_t* dispatch =
reinterpret_cast<hwvulkan_dispatch_t*>(cmdbuffers[i]);
ALOGE_IF(dispatch->magic != HWVULKAN_DISPATCH_MAGIC,
@@ -1090,14 +1148,15 @@
return VK_SUCCESS;
}
-VkResult DestroyDevice(VkDevice drv_device) {
+VkResult DestroyDevice(VkDevice drv_device,
+ const VkAllocCallbacks* /*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);
}
- vtbl->DestroyDevice(drv_device);
+ vtbl->DestroyDevice(drv_device, device->instance->alloc);
DestroyDevice(device);
return VK_SUCCESS;
}
@@ -1105,9 +1164,9 @@
void* AllocMem(VkInstance instance,
size_t size,
size_t align,
- VkSystemAllocType type) {
+ VkSystemAllocScope scope) {
const VkAllocCallbacks* alloc_cb = instance->alloc;
- return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, type);
+ return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, scope);
}
void FreeMem(VkInstance instance, void* ptr) {
@@ -1118,10 +1177,10 @@
void* AllocMem(VkDevice device,
size_t size,
size_t align,
- VkSystemAllocType type) {
+ VkSystemAllocScope scope) {
const VkAllocCallbacks* alloc_cb =
static_cast<Device*>(GetVtbl(device)->device)->instance->alloc;
- return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, type);
+ return alloc_cb->pfnAlloc(alloc_cb->pUserData, size, align, scope);
}
void FreeMem(VkDevice device, void* ptr) {