mirror of
https://gitee.com/openharmony/third_party_vulkan-loader
synced 2024-11-28 09:50:44 +00:00
test: Remove Allocation tests from old test suite
loader_alloc_callback_tests.cpp now contain all of the removed tests. Change-Id: Ia99df3a8f86d40f0d5e89a62b7b0a5f9bebafb7c
This commit is contained in:
parent
b70cf11abb
commit
0a1a346b0b
@ -258,148 +258,6 @@ struct EnumerateInstanceLayerProperties : public CommandLine {};
|
||||
struct EnumerateInstanceExtensionProperties : public CommandLine {};
|
||||
struct ImplicitLayer : public CommandLine {};
|
||||
|
||||
// Allocation tracking utilities
|
||||
struct AllocTrack {
|
||||
bool active;
|
||||
bool was_allocated;
|
||||
void *aligned_start_addr;
|
||||
char *actual_start_addr;
|
||||
size_t requested_size_bytes;
|
||||
size_t actual_size_bytes;
|
||||
VkSystemAllocationScope alloc_scope;
|
||||
uint64_t user_data;
|
||||
|
||||
AllocTrack()
|
||||
: active(false),
|
||||
was_allocated(false),
|
||||
aligned_start_addr(nullptr),
|
||||
actual_start_addr(nullptr),
|
||||
requested_size_bytes(0),
|
||||
actual_size_bytes(0),
|
||||
alloc_scope(VK_SYSTEM_ALLOCATION_SCOPE_COMMAND),
|
||||
user_data(0) {}
|
||||
};
|
||||
|
||||
// Global vector to track allocations. This will be resized before each test and emptied after.
|
||||
// However, we have to globally define it so the allocation callback functions work properly.
|
||||
std::vector<AllocTrack> g_allocated_vector;
|
||||
bool g_intentional_fail_enabled = false;
|
||||
uint32_t g_intentional_fail_index = 0;
|
||||
uint32_t g_intentional_fail_count = 0;
|
||||
|
||||
void FreeAllocTracker() { g_allocated_vector.clear(); }
|
||||
|
||||
void InitAllocTracker(size_t size, uint32_t intentional_fail_index = UINT32_MAX) {
|
||||
if (g_allocated_vector.size() > 0) {
|
||||
FreeAllocTracker();
|
||||
}
|
||||
g_allocated_vector.resize(size);
|
||||
if (intentional_fail_index != UINT32_MAX) {
|
||||
g_intentional_fail_enabled = true;
|
||||
g_intentional_fail_index = intentional_fail_index;
|
||||
g_intentional_fail_count = 0;
|
||||
} else {
|
||||
g_intentional_fail_enabled = false;
|
||||
g_intentional_fail_index = 0;
|
||||
g_intentional_fail_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsAllocTrackerEmpty() {
|
||||
bool success = true;
|
||||
bool was_allocated = false;
|
||||
char print_command[1024];
|
||||
sprintf(print_command, "\t%%04d\t%%p (%%p) : 0x%%%s (0x%%%s) : scope %%d : user_data 0x%%%s\n", PRIxLEAST64, PRIxLEAST64,
|
||||
PRIxLEAST64);
|
||||
for (uint32_t iii = 0; iii < g_allocated_vector.size(); iii++) {
|
||||
if (g_allocated_vector[iii].active) {
|
||||
if (success) {
|
||||
printf("ERROR: Allocations still remain!\n");
|
||||
}
|
||||
printf(print_command, iii, g_allocated_vector[iii].aligned_start_addr, g_allocated_vector[iii].actual_start_addr,
|
||||
g_allocated_vector[iii].requested_size_bytes, g_allocated_vector[iii].actual_size_bytes,
|
||||
g_allocated_vector[iii].alloc_scope, g_allocated_vector[iii].user_data);
|
||||
success = false;
|
||||
} else if (!was_allocated && g_allocated_vector[iii].was_allocated) {
|
||||
was_allocated = true;
|
||||
}
|
||||
}
|
||||
if (!g_intentional_fail_enabled && !was_allocated) {
|
||||
printf("No allocations ever generated!");
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void *VKAPI_CALL AllocCallbackFunc(void *pUserData, size_t size, size_t alignment,
|
||||
VkSystemAllocationScope allocationScope) {
|
||||
if (g_intentional_fail_enabled) {
|
||||
if (++g_intentional_fail_count >= g_intentional_fail_index) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
for (uint32_t iii = 0; iii < g_allocated_vector.size(); iii++) {
|
||||
if (!g_allocated_vector[iii].active) {
|
||||
g_allocated_vector[iii].requested_size_bytes = size;
|
||||
g_allocated_vector[iii].actual_size_bytes = size + (alignment - 1);
|
||||
g_allocated_vector[iii].aligned_start_addr = NULL;
|
||||
g_allocated_vector[iii].actual_start_addr = new char[g_allocated_vector[iii].actual_size_bytes];
|
||||
if (g_allocated_vector[iii].actual_start_addr != NULL) {
|
||||
uint64_t addr = (uint64_t)g_allocated_vector[iii].actual_start_addr;
|
||||
addr += (alignment - 1);
|
||||
addr &= ~(alignment - 1);
|
||||
g_allocated_vector[iii].aligned_start_addr = (void *)addr;
|
||||
g_allocated_vector[iii].alloc_scope = allocationScope;
|
||||
g_allocated_vector[iii].user_data = (uint64_t)pUserData;
|
||||
g_allocated_vector[iii].active = true;
|
||||
g_allocated_vector[iii].was_allocated = true;
|
||||
}
|
||||
return g_allocated_vector[iii].aligned_start_addr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL FreeCallbackFunc(void *pUserData, void *pMemory) {
|
||||
for (uint32_t iii = 0; iii < g_allocated_vector.size(); iii++) {
|
||||
if (g_allocated_vector[iii].active && g_allocated_vector[iii].aligned_start_addr == pMemory) {
|
||||
delete[] g_allocated_vector[iii].actual_start_addr;
|
||||
g_allocated_vector[iii].active = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VKAPI_ATTR void *VKAPI_CALL ReallocCallbackFunc(void *pUserData, void *pOriginal, size_t size, size_t alignment,
|
||||
VkSystemAllocationScope allocationScope) {
|
||||
if (pOriginal != NULL) {
|
||||
for (uint32_t iii = 0; iii < g_allocated_vector.size(); iii++) {
|
||||
if (g_allocated_vector[iii].active && g_allocated_vector[iii].aligned_start_addr == pOriginal) {
|
||||
if (size == 0) {
|
||||
FreeCallbackFunc(pUserData, pOriginal);
|
||||
return nullptr;
|
||||
} else if (size < g_allocated_vector[iii].requested_size_bytes) {
|
||||
return pOriginal;
|
||||
} else {
|
||||
void *pNew = AllocCallbackFunc(pUserData, size, alignment, allocationScope);
|
||||
if (pNew != NULL) {
|
||||
size_t copy_size = size;
|
||||
if (g_allocated_vector[iii].requested_size_bytes < size) {
|
||||
copy_size = g_allocated_vector[iii].requested_size_bytes;
|
||||
}
|
||||
memcpy(pNew, pOriginal, copy_size);
|
||||
FreeCallbackFunc(pUserData, pOriginal);
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
} else {
|
||||
return AllocCallbackFunc(pUserData, size, alignment, allocationScope);
|
||||
}
|
||||
}
|
||||
|
||||
void test_create_device(VkPhysicalDevice physical) {
|
||||
uint32_t familyCount = 0;
|
||||
VkResult result;
|
||||
@ -1038,479 +896,6 @@ TEST(WrapObjects, Insert) {
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
}
|
||||
|
||||
// Test making sure the allocation functions are called to allocate and cleanup everything during
|
||||
// a CreateInstance/DestroyInstance call pair.
|
||||
TEST(Allocation, Instance) {
|
||||
auto const info = VK::InstanceCreateInfo();
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkAllocationCallbacks alloc_callbacks = {};
|
||||
alloc_callbacks.pUserData = (void *)0x00000001;
|
||||
alloc_callbacks.pfnAllocation = AllocCallbackFunc;
|
||||
alloc_callbacks.pfnReallocation = ReallocCallbackFunc;
|
||||
alloc_callbacks.pfnFree = FreeCallbackFunc;
|
||||
|
||||
InitAllocTracker(2048);
|
||||
|
||||
VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
alloc_callbacks.pUserData = (void *)0x00000002;
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
|
||||
// Make sure everything's been freed
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
FreeAllocTracker();
|
||||
}
|
||||
|
||||
// Test making sure the allocation functions are called to allocate and cleanup everything during
|
||||
// a CreateInstance/DestroyInstance call pair with a call to GetInstanceProcAddr.
|
||||
TEST(Allocation, GetInstanceProcAddr) {
|
||||
auto const info = VK::InstanceCreateInfo();
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkAllocationCallbacks alloc_callbacks = {};
|
||||
alloc_callbacks.pUserData = (void *)0x00000010;
|
||||
alloc_callbacks.pfnAllocation = AllocCallbackFunc;
|
||||
alloc_callbacks.pfnReallocation = ReallocCallbackFunc;
|
||||
alloc_callbacks.pfnFree = FreeCallbackFunc;
|
||||
|
||||
InitAllocTracker(2048);
|
||||
|
||||
VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
void *pfnCreateDevice = (void *)vkGetInstanceProcAddr(instance, "vkCreateDevice");
|
||||
void *pfnDestroyDevice = (void *)vkGetInstanceProcAddr(instance, "vkDestroyDevice");
|
||||
ASSERT_TRUE(pfnCreateDevice != NULL && pfnDestroyDevice != NULL);
|
||||
|
||||
alloc_callbacks.pUserData = (void *)0x00000011;
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
|
||||
// Make sure everything's been freed
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
FreeAllocTracker();
|
||||
}
|
||||
|
||||
// Test making sure the allocation functions are called to allocate and cleanup everything during
|
||||
// a vkEnumeratePhysicalDevices call pair.
|
||||
TEST(Allocation, EnumeratePhysicalDevices) {
|
||||
auto const info = VK::InstanceCreateInfo();
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkAllocationCallbacks alloc_callbacks = {};
|
||||
alloc_callbacks.pUserData = (void *)0x00000021;
|
||||
alloc_callbacks.pfnAllocation = AllocCallbackFunc;
|
||||
alloc_callbacks.pfnReallocation = ReallocCallbackFunc;
|
||||
alloc_callbacks.pfnFree = FreeCallbackFunc;
|
||||
|
||||
InitAllocTracker(2048);
|
||||
|
||||
VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
uint32_t physicalCount = 0;
|
||||
alloc_callbacks.pUserData = (void *)0x00000022;
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
|
||||
alloc_callbacks.pUserData = (void *)0x00000023;
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
alloc_callbacks.pUserData = (void *)0x00000024;
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
|
||||
// Make sure everything's been freed
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
FreeAllocTracker();
|
||||
}
|
||||
|
||||
// Test making sure the allocation functions are called to allocate and cleanup everything from
|
||||
// vkCreateInstance, to vkCreateDevicce, and then through their destructors. With special
|
||||
// allocators used on both the instance and device.
|
||||
TEST(Allocation, InstanceAndDevice) {
|
||||
auto const info = VK::InstanceCreateInfo();
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkAllocationCallbacks alloc_callbacks = {};
|
||||
alloc_callbacks.pUserData = (void *)0x00000031;
|
||||
alloc_callbacks.pfnAllocation = AllocCallbackFunc;
|
||||
alloc_callbacks.pfnReallocation = ReallocCallbackFunc;
|
||||
alloc_callbacks.pfnFree = FreeCallbackFunc;
|
||||
|
||||
InitAllocTracker(2048);
|
||||
|
||||
VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
uint32_t physicalCount = 0;
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
for (uint32_t p = 0; p < physicalCount; ++p) {
|
||||
uint32_t familyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr);
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get());
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
for (uint32_t q = 0; q < familyCount; ++q) {
|
||||
if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float const priorities[] = {0.0f}; // Temporary required due to MSVC bug.
|
||||
VkDeviceQueueCreateInfo const queueInfo[1]{
|
||||
VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)};
|
||||
|
||||
auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo);
|
||||
|
||||
VkDevice device;
|
||||
alloc_callbacks.pUserData = (void *)0x00000032;
|
||||
result = vkCreateDevice(physical[p], deviceInfo, &alloc_callbacks, &device);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
alloc_callbacks.pUserData = (void *)0x00000033;
|
||||
vkDestroyDevice(device, &alloc_callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
alloc_callbacks.pUserData = (void *)0x00000034;
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
|
||||
// Make sure everything's been freed
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
FreeAllocTracker();
|
||||
}
|
||||
|
||||
// Test making sure the allocation functions are called to allocate and cleanup everything from
|
||||
// vkCreateInstance, to vkCreateDevicce, and then through their destructors. With special
|
||||
// allocators used on only the instance and not the device.
|
||||
TEST(Allocation, InstanceButNotDevice) {
|
||||
auto const info = VK::InstanceCreateInfo();
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkAllocationCallbacks alloc_callbacks = {};
|
||||
alloc_callbacks.pUserData = (void *)0x00000041;
|
||||
alloc_callbacks.pfnAllocation = AllocCallbackFunc;
|
||||
alloc_callbacks.pfnReallocation = ReallocCallbackFunc;
|
||||
alloc_callbacks.pfnFree = FreeCallbackFunc;
|
||||
|
||||
InitAllocTracker(2048);
|
||||
|
||||
VkResult result = vkCreateInstance(info, &alloc_callbacks, &instance);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
uint32_t physicalCount = 0;
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
for (uint32_t p = 0; p < physicalCount; ++p) {
|
||||
uint32_t familyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr);
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get());
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
for (uint32_t q = 0; q < familyCount; ++q) {
|
||||
if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float const priorities[] = {0.0f}; // Temporary required due to MSVC bug.
|
||||
VkDeviceQueueCreateInfo const queueInfo[1]{
|
||||
VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)};
|
||||
|
||||
auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo);
|
||||
|
||||
VkDevice device;
|
||||
result = vkCreateDevice(physical[p], deviceInfo, NULL, &device);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
vkDestroyDevice(device, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
alloc_callbacks.pUserData = (void *)0x00000042;
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
|
||||
// Make sure everything's been freed
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
FreeAllocTracker();
|
||||
}
|
||||
|
||||
// Test making sure the allocation functions are called to allocate and cleanup everything from
|
||||
// vkCreateInstance, to vkCreateDevicce, and then through their destructors. With special
|
||||
// allocators used on only the device and not the instance.
|
||||
TEST(Allocation, DeviceButNotInstance) {
|
||||
auto const info = VK::InstanceCreateInfo();
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkAllocationCallbacks alloc_callbacks = {};
|
||||
alloc_callbacks.pfnAllocation = AllocCallbackFunc;
|
||||
alloc_callbacks.pfnReallocation = ReallocCallbackFunc;
|
||||
alloc_callbacks.pfnFree = FreeCallbackFunc;
|
||||
|
||||
InitAllocTracker(2048);
|
||||
|
||||
VkResult result = vkCreateInstance(info, NULL, &instance);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
uint32_t physicalCount = 0;
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
for (uint32_t p = 0; p < physicalCount; ++p) {
|
||||
uint32_t familyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr);
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get());
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
for (uint32_t q = 0; q < familyCount; ++q) {
|
||||
if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float const priorities[] = {0.0f}; // Temporary required due to MSVC bug.
|
||||
VkDeviceQueueCreateInfo const queueInfo[1]{
|
||||
VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)};
|
||||
|
||||
auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo);
|
||||
|
||||
VkDevice device;
|
||||
alloc_callbacks.pUserData = (void *)0x00000051;
|
||||
result = vkCreateDevice(physical[p], deviceInfo, &alloc_callbacks, &device);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
alloc_callbacks.pUserData = (void *)0x00000052;
|
||||
vkDestroyDevice(device, &alloc_callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
vkDestroyInstance(instance, NULL);
|
||||
|
||||
// Make sure everything's been freed
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
FreeAllocTracker();
|
||||
}
|
||||
|
||||
// Test failure during vkCreateInstance to make sure we don't leak memory if
|
||||
// one of the out-of-memory conditions trigger.
|
||||
TEST(Allocation, CreateInstanceIntentionalAllocFail) {
|
||||
auto const info = VK::InstanceCreateInfo();
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkAllocationCallbacks alloc_callbacks = {};
|
||||
alloc_callbacks.pfnAllocation = AllocCallbackFunc;
|
||||
alloc_callbacks.pfnReallocation = ReallocCallbackFunc;
|
||||
alloc_callbacks.pfnFree = FreeCallbackFunc;
|
||||
|
||||
VkResult result;
|
||||
uint32_t fail_index = 1;
|
||||
do {
|
||||
InitAllocTracker(9999, fail_index);
|
||||
|
||||
result = vkCreateInstance(info, &alloc_callbacks, &instance);
|
||||
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
|
||||
if (!IsAllocTrackerEmpty()) {
|
||||
std::cout << "Failed on index " << fail_index << '\n';
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
}
|
||||
}
|
||||
fail_index++;
|
||||
// Make sure we don't overrun the memory
|
||||
ASSERT_LT(fail_index, 9999u);
|
||||
|
||||
FreeAllocTracker();
|
||||
} while (result == VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
}
|
||||
|
||||
// Test failure during vkCreateDevice to make sure we don't leak memory if
|
||||
// one of the out-of-memory conditions trigger.
|
||||
TEST(Allocation, CreateDeviceIntentionalAllocFail) {
|
||||
auto const info = VK::InstanceCreateInfo();
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
VkAllocationCallbacks alloc_callbacks = {};
|
||||
alloc_callbacks.pfnAllocation = AllocCallbackFunc;
|
||||
alloc_callbacks.pfnReallocation = ReallocCallbackFunc;
|
||||
alloc_callbacks.pfnFree = FreeCallbackFunc;
|
||||
|
||||
VkResult result = vkCreateInstance(info, NULL, &instance);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
uint32_t physicalCount = 0;
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
ASSERT_GT(physicalCount, 0u);
|
||||
|
||||
for (uint32_t p = 0; p < physicalCount; ++p) {
|
||||
uint32_t familyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr);
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get());
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
for (uint32_t q = 0; q < familyCount; ++q) {
|
||||
if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float const priorities[] = {0.0f}; // Temporary required due to MSVC bug.
|
||||
VkDeviceQueueCreateInfo const queueInfo[1]{
|
||||
VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)};
|
||||
|
||||
auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo);
|
||||
|
||||
uint32_t fail_index = 1;
|
||||
do {
|
||||
InitAllocTracker(9999, fail_index);
|
||||
|
||||
result = vkCreateDevice(physical[p], deviceInfo, &alloc_callbacks, &device);
|
||||
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
|
||||
if (!IsAllocTrackerEmpty()) {
|
||||
std::cout << "Failed on index " << fail_index << '\n';
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
}
|
||||
}
|
||||
fail_index++;
|
||||
// Make sure we don't overrun the memory
|
||||
ASSERT_LT(fail_index, 9999u);
|
||||
|
||||
FreeAllocTracker();
|
||||
} while (result == VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
vkDestroyDevice(device, &alloc_callbacks);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vkDestroyInstance(instance, NULL);
|
||||
}
|
||||
|
||||
// Test failure during vkCreateInstance and vkCreateDevice to make sure we don't
|
||||
// leak memory if one of the out-of-memory conditions trigger.
|
||||
TEST(Allocation, CreateInstanceDeviceIntentionalAllocFail) {
|
||||
auto const info = VK::InstanceCreateInfo();
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
VkAllocationCallbacks alloc_callbacks = {};
|
||||
alloc_callbacks.pfnAllocation = AllocCallbackFunc;
|
||||
alloc_callbacks.pfnReallocation = ReallocCallbackFunc;
|
||||
alloc_callbacks.pfnFree = FreeCallbackFunc;
|
||||
|
||||
VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
uint32_t fail_index = 0;
|
||||
uint32_t physicalCount = 0;
|
||||
while (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
|
||||
InitAllocTracker(9999, ++fail_index);
|
||||
ASSERT_LT(fail_index, 9999u);
|
||||
|
||||
result = vkCreateInstance(info, &alloc_callbacks, &instance);
|
||||
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
|
||||
if (!IsAllocTrackerEmpty()) {
|
||||
std::cout << "Failed on index " << fail_index << '\n';
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
}
|
||||
FreeAllocTracker();
|
||||
continue;
|
||||
}
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
physicalCount = 0;
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
|
||||
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
if (!IsAllocTrackerEmpty()) {
|
||||
std::cout << "Failed on index " << fail_index << '\n';
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
}
|
||||
FreeAllocTracker();
|
||||
continue;
|
||||
}
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
|
||||
result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
|
||||
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
if (!IsAllocTrackerEmpty()) {
|
||||
std::cout << "Failed on index " << fail_index << '\n';
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
}
|
||||
FreeAllocTracker();
|
||||
continue;
|
||||
}
|
||||
ASSERT_EQ(result, VK_SUCCESS);
|
||||
|
||||
uint32_t familyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[0], &familyCount, nullptr);
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physical[0], &familyCount, family.get());
|
||||
ASSERT_GT(familyCount, 0u);
|
||||
|
||||
uint32_t queue_index = 0;
|
||||
for (uint32_t q = 0; q < familyCount; ++q) {
|
||||
if (family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
queue_index = q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float const priorities[] = {0.0f}; // Temporary required due to MSVC bug.
|
||||
VkDeviceQueueCreateInfo const queueInfo[1]{
|
||||
VK::DeviceQueueCreateInfo().queueFamilyIndex(queue_index).queueCount(1).pQueuePriorities(priorities)};
|
||||
|
||||
auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo);
|
||||
|
||||
result = vkCreateDevice(physical[0], deviceInfo, &alloc_callbacks, &device);
|
||||
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
if (!IsAllocTrackerEmpty()) {
|
||||
std::cout << "Failed on index " << fail_index << '\n';
|
||||
ASSERT_EQ(true, IsAllocTrackerEmpty());
|
||||
}
|
||||
FreeAllocTracker();
|
||||
continue;
|
||||
}
|
||||
vkDestroyDevice(device, &alloc_callbacks);
|
||||
vkDestroyInstance(instance, &alloc_callbacks);
|
||||
FreeAllocTracker();
|
||||
}
|
||||
}
|
||||
|
||||
// Used by run_loader_tests.sh to test that calling vkEnumeratePhysicalDeviceGroupsKHR without first querying
|
||||
// the count, works. And, that it also returns only physical devices made available by the standard
|
||||
// enumerate call
|
||||
|
Loading…
Reference in New Issue
Block a user