15db71995Sopenharmony_ci/* 25db71995Sopenharmony_ci * Copyright (c) 2021-2023 The Khronos Group Inc. 35db71995Sopenharmony_ci * Copyright (c) 2021-2023 Valve Corporation 45db71995Sopenharmony_ci * Copyright (c) 2021-2023 LunarG, Inc. 55db71995Sopenharmony_ci * 65db71995Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 75db71995Sopenharmony_ci * of this software and/or associated documentation files (the "Materials"), to 85db71995Sopenharmony_ci * deal in the Materials without restriction, including without limitation the 95db71995Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 105db71995Sopenharmony_ci * sell copies of the Materials, and to permit persons to whom the Materials are 115db71995Sopenharmony_ci * furnished to do so, subject to the following conditions: 125db71995Sopenharmony_ci * 135db71995Sopenharmony_ci * The above copyright notice(s) and this permission notice shall be included in 145db71995Sopenharmony_ci * all copies or substantial portions of the Materials. 155db71995Sopenharmony_ci * 165db71995Sopenharmony_ci * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 175db71995Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 185db71995Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 195db71995Sopenharmony_ci * 205db71995Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 215db71995Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 225db71995Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 235db71995Sopenharmony_ci * USE OR OTHER DEALINGS IN THE MATERIALS. 245db71995Sopenharmony_ci * 255db71995Sopenharmony_ci * Author: Charles Giessen <charles@lunarg.com> 265db71995Sopenharmony_ci */ 275db71995Sopenharmony_ci 285db71995Sopenharmony_ci#include "test_environment.h" 295db71995Sopenharmony_ci 305db71995Sopenharmony_ci#include <mutex> 315db71995Sopenharmony_ci 325db71995Sopenharmony_cistruct MemoryTrackerSettings { 335db71995Sopenharmony_ci bool should_fail_on_allocation = false; 345db71995Sopenharmony_ci size_t fail_after_allocations = 0; // fail after this number of allocations in total 355db71995Sopenharmony_ci bool should_fail_after_set_number_of_calls = false; 365db71995Sopenharmony_ci size_t fail_after_calls = 0; // fail after this number of calls to alloc or realloc 375db71995Sopenharmony_ci}; 385db71995Sopenharmony_ci 395db71995Sopenharmony_ciclass MemoryTracker { 405db71995Sopenharmony_ci std::mutex main_mutex; 415db71995Sopenharmony_ci MemoryTrackerSettings settings{}; 425db71995Sopenharmony_ci VkAllocationCallbacks callbacks{}; 435db71995Sopenharmony_ci // Implementation internals 445db71995Sopenharmony_ci struct AllocationDetails { 455db71995Sopenharmony_ci std::unique_ptr<char[]> allocation; 465db71995Sopenharmony_ci size_t requested_size_bytes; 475db71995Sopenharmony_ci size_t actual_size_bytes; 485db71995Sopenharmony_ci size_t alignment; 495db71995Sopenharmony_ci VkSystemAllocationScope alloc_scope; 505db71995Sopenharmony_ci }; 515db71995Sopenharmony_ci const static size_t UNKNOWN_ALLOCATION = std::numeric_limits<size_t>::max(); 525db71995Sopenharmony_ci size_t allocation_count = 0; 535db71995Sopenharmony_ci size_t call_count = 0; 545db71995Sopenharmony_ci std::unordered_map<void*, AllocationDetails> allocations; 555db71995Sopenharmony_ci 565db71995Sopenharmony_ci void* allocate(size_t size, size_t alignment, VkSystemAllocationScope alloc_scope) { 575db71995Sopenharmony_ci if ((settings.should_fail_on_allocation && allocation_count == settings.fail_after_allocations) || 585db71995Sopenharmony_ci (settings.should_fail_after_set_number_of_calls && call_count == settings.fail_after_calls)) { 595db71995Sopenharmony_ci return nullptr; 605db71995Sopenharmony_ci } 615db71995Sopenharmony_ci call_count++; 625db71995Sopenharmony_ci allocation_count++; 635db71995Sopenharmony_ci AllocationDetails detail{nullptr, size, size + (alignment - 1), alignment, alloc_scope}; 645db71995Sopenharmony_ci detail.allocation = std::unique_ptr<char[]>(new char[detail.actual_size_bytes]); 655db71995Sopenharmony_ci if (!detail.allocation) { 665db71995Sopenharmony_ci abort(); 675db71995Sopenharmony_ci }; 685db71995Sopenharmony_ci uint64_t addr = (uint64_t)detail.allocation.get(); 695db71995Sopenharmony_ci addr += (alignment - 1); 705db71995Sopenharmony_ci addr &= ~(alignment - 1); 715db71995Sopenharmony_ci void* aligned_alloc = (void*)addr; 725db71995Sopenharmony_ci allocations.insert(std::make_pair(aligned_alloc, std::move(detail))); 735db71995Sopenharmony_ci return aligned_alloc; 745db71995Sopenharmony_ci } 755db71995Sopenharmony_ci void* reallocate(void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope alloc_scope) { 765db71995Sopenharmony_ci if (pOriginal == nullptr) { 775db71995Sopenharmony_ci return allocate(size, alignment, alloc_scope); 785db71995Sopenharmony_ci } 795db71995Sopenharmony_ci auto elem = allocations.find(pOriginal); 805db71995Sopenharmony_ci if (elem == allocations.end()) return nullptr; 815db71995Sopenharmony_ci size_t original_size = elem->second.requested_size_bytes; 825db71995Sopenharmony_ci 835db71995Sopenharmony_ci // We only care about the case where realloc is used to increase the size 845db71995Sopenharmony_ci if (size >= original_size && settings.should_fail_after_set_number_of_calls && call_count == settings.fail_after_calls) 855db71995Sopenharmony_ci return nullptr; 865db71995Sopenharmony_ci call_count++; 875db71995Sopenharmony_ci if (size == 0) { 885db71995Sopenharmony_ci allocations.erase(elem); 895db71995Sopenharmony_ci allocation_count--; 905db71995Sopenharmony_ci return nullptr; 915db71995Sopenharmony_ci } else if (size < original_size) { 925db71995Sopenharmony_ci return pOriginal; 935db71995Sopenharmony_ci } else { 945db71995Sopenharmony_ci void* new_alloc = allocate(size, alignment, alloc_scope); 955db71995Sopenharmony_ci if (new_alloc == nullptr) return nullptr; 965db71995Sopenharmony_ci allocation_count--; // allocate() increments this, we we don't want that 975db71995Sopenharmony_ci call_count--; // allocate() also increments this, we don't want that 985db71995Sopenharmony_ci memcpy(new_alloc, pOriginal, original_size); 995db71995Sopenharmony_ci allocations.erase(elem); 1005db71995Sopenharmony_ci return new_alloc; 1015db71995Sopenharmony_ci } 1025db71995Sopenharmony_ci } 1035db71995Sopenharmony_ci void free(void* pMemory) { 1045db71995Sopenharmony_ci if (pMemory == nullptr) return; 1055db71995Sopenharmony_ci auto elem = allocations.find(pMemory); 1065db71995Sopenharmony_ci if (elem == allocations.end()) return; 1075db71995Sopenharmony_ci allocations.erase(elem); 1085db71995Sopenharmony_ci assert(allocation_count != 0 && "Cant free when there are no valid allocations"); 1095db71995Sopenharmony_ci allocation_count--; 1105db71995Sopenharmony_ci } 1115db71995Sopenharmony_ci 1125db71995Sopenharmony_ci // Implementation of public functions 1135db71995Sopenharmony_ci void* impl_allocation(size_t size, size_t alignment, VkSystemAllocationScope allocationScope) noexcept { 1145db71995Sopenharmony_ci std::lock_guard<std::mutex> lg(main_mutex); 1155db71995Sopenharmony_ci void* addr = allocate(size, alignment, allocationScope); 1165db71995Sopenharmony_ci return addr; 1175db71995Sopenharmony_ci } 1185db71995Sopenharmony_ci void* impl_reallocation(void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) noexcept { 1195db71995Sopenharmony_ci std::lock_guard<std::mutex> lg(main_mutex); 1205db71995Sopenharmony_ci void* addr = reallocate(pOriginal, size, alignment, allocationScope); 1215db71995Sopenharmony_ci return addr; 1225db71995Sopenharmony_ci } 1235db71995Sopenharmony_ci void impl_free(void* pMemory) noexcept { 1245db71995Sopenharmony_ci std::lock_guard<std::mutex> lg(main_mutex); 1255db71995Sopenharmony_ci free(pMemory); 1265db71995Sopenharmony_ci } 1275db71995Sopenharmony_ci void impl_internal_allocation_notification([[maybe_unused]] size_t size, 1285db71995Sopenharmony_ci [[maybe_unused]] VkInternalAllocationType allocationType, 1295db71995Sopenharmony_ci [[maybe_unused]] VkSystemAllocationScope allocationScope) noexcept { 1305db71995Sopenharmony_ci std::lock_guard<std::mutex> lg(main_mutex); 1315db71995Sopenharmony_ci // TODO? 1325db71995Sopenharmony_ci } 1335db71995Sopenharmony_ci void impl_internal_free([[maybe_unused]] size_t size, [[maybe_unused]] VkInternalAllocationType allocationType, 1345db71995Sopenharmony_ci [[maybe_unused]] VkSystemAllocationScope allocationScope) noexcept { 1355db71995Sopenharmony_ci std::lock_guard<std::mutex> lg(main_mutex); 1365db71995Sopenharmony_ci // TODO? 1375db71995Sopenharmony_ci } 1385db71995Sopenharmony_ci 1395db71995Sopenharmony_ci public: 1405db71995Sopenharmony_ci MemoryTracker(MemoryTrackerSettings settings) noexcept : settings(settings) { 1415db71995Sopenharmony_ci allocations.reserve(3000); 1425db71995Sopenharmony_ci 1435db71995Sopenharmony_ci callbacks.pUserData = this; 1445db71995Sopenharmony_ci callbacks.pfnAllocation = public_allocation; 1455db71995Sopenharmony_ci callbacks.pfnReallocation = public_reallocation; 1465db71995Sopenharmony_ci callbacks.pfnFree = public_free; 1475db71995Sopenharmony_ci callbacks.pfnInternalAllocation = public_internal_allocation_notification; 1485db71995Sopenharmony_ci callbacks.pfnInternalFree = public_internal_free; 1495db71995Sopenharmony_ci } 1505db71995Sopenharmony_ci MemoryTracker() noexcept : MemoryTracker(MemoryTrackerSettings{}) {} 1515db71995Sopenharmony_ci 1525db71995Sopenharmony_ci VkAllocationCallbacks* get() noexcept { return &callbacks; } 1535db71995Sopenharmony_ci 1545db71995Sopenharmony_ci bool empty() noexcept { return allocation_count == 0; } 1555db71995Sopenharmony_ci 1565db71995Sopenharmony_ci // Static callbacks 1575db71995Sopenharmony_ci static VKAPI_ATTR void* VKAPI_CALL public_allocation(void* pUserData, size_t size, size_t alignment, 1585db71995Sopenharmony_ci VkSystemAllocationScope allocationScope) noexcept { 1595db71995Sopenharmony_ci return reinterpret_cast<MemoryTracker*>(pUserData)->impl_allocation(size, alignment, allocationScope); 1605db71995Sopenharmony_ci } 1615db71995Sopenharmony_ci static VKAPI_ATTR void* VKAPI_CALL public_reallocation(void* pUserData, void* pOriginal, size_t size, size_t alignment, 1625db71995Sopenharmony_ci VkSystemAllocationScope allocationScope) noexcept { 1635db71995Sopenharmony_ci return reinterpret_cast<MemoryTracker*>(pUserData)->impl_reallocation(pOriginal, size, alignment, allocationScope); 1645db71995Sopenharmony_ci } 1655db71995Sopenharmony_ci static VKAPI_ATTR void VKAPI_CALL public_free(void* pUserData, void* pMemory) noexcept { 1665db71995Sopenharmony_ci reinterpret_cast<MemoryTracker*>(pUserData)->impl_free(pMemory); 1675db71995Sopenharmony_ci } 1685db71995Sopenharmony_ci static VKAPI_ATTR void VKAPI_CALL public_internal_allocation_notification(void* pUserData, size_t size, 1695db71995Sopenharmony_ci VkInternalAllocationType allocationType, 1705db71995Sopenharmony_ci VkSystemAllocationScope allocationScope) noexcept { 1715db71995Sopenharmony_ci reinterpret_cast<MemoryTracker*>(pUserData)->impl_internal_allocation_notification(size, allocationType, allocationScope); 1725db71995Sopenharmony_ci } 1735db71995Sopenharmony_ci static VKAPI_ATTR void VKAPI_CALL public_internal_free(void* pUserData, size_t size, VkInternalAllocationType allocationType, 1745db71995Sopenharmony_ci VkSystemAllocationScope allocationScope) noexcept { 1755db71995Sopenharmony_ci reinterpret_cast<MemoryTracker*>(pUserData)->impl_internal_free(size, allocationType, allocationScope); 1765db71995Sopenharmony_ci } 1775db71995Sopenharmony_ci}; 1785db71995Sopenharmony_ci 1795db71995Sopenharmony_ci// Test making sure the allocation functions are called to allocate and cleanup everything during 1805db71995Sopenharmony_ci// a CreateInstance/DestroyInstance call pair. 1815db71995Sopenharmony_ciTEST(Allocation, Instance) { 1825db71995Sopenharmony_ci FrameworkEnvironment env{}; 1835db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); 1845db71995Sopenharmony_ci 1855db71995Sopenharmony_ci MemoryTracker tracker; 1865db71995Sopenharmony_ci { 1875db71995Sopenharmony_ci InstWrapper inst{env.vulkan_functions, tracker.get()}; 1885db71995Sopenharmony_ci ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); 1895db71995Sopenharmony_ci } 1905db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 1915db71995Sopenharmony_ci} 1925db71995Sopenharmony_ci 1935db71995Sopenharmony_ci// Test making sure the allocation functions are called to allocate and cleanup everything during 1945db71995Sopenharmony_ci// a CreateInstance/DestroyInstance call pair with a call to GetInstanceProcAddr. 1955db71995Sopenharmony_ciTEST(Allocation, GetInstanceProcAddr) { 1965db71995Sopenharmony_ci FrameworkEnvironment env{}; 1975db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); 1985db71995Sopenharmony_ci 1995db71995Sopenharmony_ci MemoryTracker tracker; 2005db71995Sopenharmony_ci { 2015db71995Sopenharmony_ci InstWrapper inst{env.vulkan_functions, tracker.get()}; 2025db71995Sopenharmony_ci ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); 2035db71995Sopenharmony_ci 2045db71995Sopenharmony_ci auto* pfnCreateDevice = inst->vkGetInstanceProcAddr(inst, "vkCreateDevice"); 2055db71995Sopenharmony_ci auto* pfnDestroyDevice = inst->vkGetInstanceProcAddr(inst, "vkDestroyDevice"); 2065db71995Sopenharmony_ci ASSERT_TRUE(pfnCreateDevice != nullptr && pfnDestroyDevice != nullptr); 2075db71995Sopenharmony_ci } 2085db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 2095db71995Sopenharmony_ci} 2105db71995Sopenharmony_ci 2115db71995Sopenharmony_ci// Test making sure the allocation functions are called to allocate and cleanup everything during 2125db71995Sopenharmony_ci// a vkEnumeratePhysicalDevices call pair. 2135db71995Sopenharmony_ciTEST(Allocation, EnumeratePhysicalDevices) { 2145db71995Sopenharmony_ci FrameworkEnvironment env{}; 2155db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).add_physical_device("physical_device_0"); 2165db71995Sopenharmony_ci 2175db71995Sopenharmony_ci MemoryTracker tracker; 2185db71995Sopenharmony_ci { 2195db71995Sopenharmony_ci InstWrapper inst{env.vulkan_functions, tracker.get()}; 2205db71995Sopenharmony_ci ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); 2215db71995Sopenharmony_ci uint32_t physical_count = 1; 2225db71995Sopenharmony_ci uint32_t returned_physical_count = 0; 2235db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr)); 2245db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 2255db71995Sopenharmony_ci 2265db71995Sopenharmony_ci VkPhysicalDevice physical_device; 2275db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, &physical_device)); 2285db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 2295db71995Sopenharmony_ci } 2305db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 2315db71995Sopenharmony_ci} 2325db71995Sopenharmony_ci 2335db71995Sopenharmony_ci// Test making sure the allocation functions are called to allocate and cleanup everything from 2345db71995Sopenharmony_ci// vkCreateInstance, to vkCreateDevicce, and then through their destructors. With special 2355db71995Sopenharmony_ci// allocators used on both the instance and device. 2365db71995Sopenharmony_ciTEST(Allocation, InstanceAndDevice) { 2375db71995Sopenharmony_ci FrameworkEnvironment env{}; 2385db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) 2395db71995Sopenharmony_ci .add_physical_device(PhysicalDevice{"physical_device_0"} 2405db71995Sopenharmony_ci .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false}) 2415db71995Sopenharmony_ci .finish()); 2425db71995Sopenharmony_ci 2435db71995Sopenharmony_ci MemoryTracker tracker; 2445db71995Sopenharmony_ci { 2455db71995Sopenharmony_ci InstWrapper inst{env.vulkan_functions, tracker.get()}; 2465db71995Sopenharmony_ci ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); 2475db71995Sopenharmony_ci 2485db71995Sopenharmony_ci uint32_t physical_count = 1; 2495db71995Sopenharmony_ci uint32_t returned_physical_count = 0; 2505db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr)); 2515db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 2525db71995Sopenharmony_ci 2535db71995Sopenharmony_ci VkPhysicalDevice physical_device; 2545db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, &physical_device)); 2555db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 2565db71995Sopenharmony_ci 2575db71995Sopenharmony_ci uint32_t family_count = 1; 2585db71995Sopenharmony_ci uint32_t returned_family_count = 0; 2595db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &returned_family_count, nullptr); 2605db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 2615db71995Sopenharmony_ci 2625db71995Sopenharmony_ci VkQueueFamilyProperties family; 2635db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &returned_family_count, &family); 2645db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 2655db71995Sopenharmony_ci ASSERT_EQ(family.queueFlags, static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT)); 2665db71995Sopenharmony_ci ASSERT_EQ(family.queueCount, family_count); 2675db71995Sopenharmony_ci ASSERT_EQ(family.timestampValidBits, 0U); 2685db71995Sopenharmony_ci 2695db71995Sopenharmony_ci DeviceCreateInfo dev_create_info; 2705db71995Sopenharmony_ci dev_create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); 2715db71995Sopenharmony_ci 2725db71995Sopenharmony_ci VkDevice device; 2735db71995Sopenharmony_ci ASSERT_EQ(inst->vkCreateDevice(physical_device, dev_create_info.get(), tracker.get(), &device), VK_SUCCESS); 2745db71995Sopenharmony_ci 2755db71995Sopenharmony_ci VkQueue queue; 2765db71995Sopenharmony_ci inst->vkGetDeviceQueue(device, 0, 0, &queue); 2775db71995Sopenharmony_ci 2785db71995Sopenharmony_ci inst->vkDestroyDevice(device, tracker.get()); 2795db71995Sopenharmony_ci } 2805db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 2815db71995Sopenharmony_ci} 2825db71995Sopenharmony_ci// Test making sure the allocation functions are called to allocate and cleanup everything from 2835db71995Sopenharmony_ci// vkCreateInstance, to vkCreateDevicce, and then through their destructors. With special 2845db71995Sopenharmony_ci// allocators used on only the instance and not the device. 2855db71995Sopenharmony_ciTEST(Allocation, InstanceButNotDevice) { 2865db71995Sopenharmony_ci FrameworkEnvironment env{}; 2875db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) 2885db71995Sopenharmony_ci .add_physical_device(PhysicalDevice{"physical_device_0"} 2895db71995Sopenharmony_ci .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false}) 2905db71995Sopenharmony_ci .finish()); 2915db71995Sopenharmony_ci 2925db71995Sopenharmony_ci MemoryTracker tracker; 2935db71995Sopenharmony_ci { 2945db71995Sopenharmony_ci InstWrapper inst{env.vulkan_functions, tracker.get()}; 2955db71995Sopenharmony_ci ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); 2965db71995Sopenharmony_ci 2975db71995Sopenharmony_ci uint32_t physical_count = 1; 2985db71995Sopenharmony_ci uint32_t returned_physical_count = 0; 2995db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr)); 3005db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 3015db71995Sopenharmony_ci 3025db71995Sopenharmony_ci VkPhysicalDevice physical_device; 3035db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, &physical_device)); 3045db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 3055db71995Sopenharmony_ci 3065db71995Sopenharmony_ci uint32_t family_count = 1; 3075db71995Sopenharmony_ci uint32_t returned_family_count = 0; 3085db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &returned_family_count, nullptr); 3095db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 3105db71995Sopenharmony_ci 3115db71995Sopenharmony_ci VkQueueFamilyProperties family; 3125db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &returned_family_count, &family); 3135db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 3145db71995Sopenharmony_ci ASSERT_EQ(family.queueFlags, static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT)); 3155db71995Sopenharmony_ci ASSERT_EQ(family.queueCount, family_count); 3165db71995Sopenharmony_ci ASSERT_EQ(family.timestampValidBits, 0U); 3175db71995Sopenharmony_ci 3185db71995Sopenharmony_ci DeviceCreateInfo dev_create_info; 3195db71995Sopenharmony_ci dev_create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); 3205db71995Sopenharmony_ci 3215db71995Sopenharmony_ci VkDevice device; 3225db71995Sopenharmony_ci ASSERT_EQ(inst->vkCreateDevice(physical_device, dev_create_info.get(), nullptr, &device), VK_SUCCESS); 3235db71995Sopenharmony_ci VkQueue queue; 3245db71995Sopenharmony_ci inst->vkGetDeviceQueue(device, 0, 0, &queue); 3255db71995Sopenharmony_ci 3265db71995Sopenharmony_ci inst->vkDestroyDevice(device, nullptr); 3275db71995Sopenharmony_ci } 3285db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 3295db71995Sopenharmony_ci} 3305db71995Sopenharmony_ci 3315db71995Sopenharmony_ci// Test making sure the allocation functions are called to allocate and cleanup everything from 3325db71995Sopenharmony_ci// vkCreateInstance, to vkCreateDevicce, and then through their destructors. With special 3335db71995Sopenharmony_ci// allocators used on only the device and not the instance. 3345db71995Sopenharmony_ciTEST(Allocation, DeviceButNotInstance) { 3355db71995Sopenharmony_ci FrameworkEnvironment env{}; 3365db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) 3375db71995Sopenharmony_ci .add_physical_device(PhysicalDevice{"physical_device_0"} 3385db71995Sopenharmony_ci .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false}) 3395db71995Sopenharmony_ci .finish()); 3405db71995Sopenharmony_ci 3415db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 3425db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 3435db71995Sopenharmony_ci .set_name(layer_name) 3445db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 3455db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 3465db71995Sopenharmony_ci "test_layer.json"); 3475db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 3485db71995Sopenharmony_ci 3495db71995Sopenharmony_ci MemoryTracker tracker; 3505db71995Sopenharmony_ci { 3515db71995Sopenharmony_ci InstWrapper inst{env.vulkan_functions}; 3525db71995Sopenharmony_ci ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); 3535db71995Sopenharmony_ci 3545db71995Sopenharmony_ci uint32_t physical_count = 1; 3555db71995Sopenharmony_ci uint32_t returned_physical_count = 0; 3565db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr)); 3575db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 3585db71995Sopenharmony_ci 3595db71995Sopenharmony_ci VkPhysicalDevice physical_device; 3605db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, &physical_device)); 3615db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 3625db71995Sopenharmony_ci 3635db71995Sopenharmony_ci uint32_t family_count = 1; 3645db71995Sopenharmony_ci uint32_t returned_family_count = 0; 3655db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &returned_family_count, nullptr); 3665db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 3675db71995Sopenharmony_ci 3685db71995Sopenharmony_ci VkQueueFamilyProperties family; 3695db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &returned_family_count, &family); 3705db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 3715db71995Sopenharmony_ci ASSERT_EQ(family.queueFlags, static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT)); 3725db71995Sopenharmony_ci ASSERT_EQ(family.queueCount, family_count); 3735db71995Sopenharmony_ci ASSERT_EQ(family.timestampValidBits, 0U); 3745db71995Sopenharmony_ci 3755db71995Sopenharmony_ci DeviceCreateInfo dev_create_info; 3765db71995Sopenharmony_ci dev_create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); 3775db71995Sopenharmony_ci 3785db71995Sopenharmony_ci VkDevice device; 3795db71995Sopenharmony_ci ASSERT_EQ(inst->vkCreateDevice(physical_device, dev_create_info.get(), tracker.get(), &device), VK_SUCCESS); 3805db71995Sopenharmony_ci 3815db71995Sopenharmony_ci VkQueue queue; 3825db71995Sopenharmony_ci inst->vkGetDeviceQueue(device, 0, 0, &queue); 3835db71995Sopenharmony_ci 3845db71995Sopenharmony_ci inst->vkDestroyDevice(device, tracker.get()); 3855db71995Sopenharmony_ci } 3865db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 3875db71995Sopenharmony_ci} 3885db71995Sopenharmony_ci 3895db71995Sopenharmony_ci// Test failure during vkCreateInstance to make sure we don't leak memory if 3905db71995Sopenharmony_ci// one of the out-of-memory conditions trigger. 3915db71995Sopenharmony_ciTEST(Allocation, CreateInstanceIntentionalAllocFail) { 3925db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 3935db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); 3945db71995Sopenharmony_ci 3955db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 3965db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 3975db71995Sopenharmony_ci .set_name(layer_name) 3985db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 3995db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 4005db71995Sopenharmony_ci "test_layer.json"); 4015db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 4025db71995Sopenharmony_ci 4035db71995Sopenharmony_ci size_t fail_index = 0; 4045db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 4055db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) { 4065db71995Sopenharmony_ci MemoryTracker tracker({false, 0, true, fail_index}); 4075db71995Sopenharmony_ci 4085db71995Sopenharmony_ci VkInstance instance; 4095db71995Sopenharmony_ci InstanceCreateInfo inst_create_info{}; 4105db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 4115db71995Sopenharmony_ci if (result == VK_SUCCESS) { 4125db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 4135db71995Sopenharmony_ci } 4145db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 4155db71995Sopenharmony_ci fail_index++; 4165db71995Sopenharmony_ci } 4175db71995Sopenharmony_ci} 4185db71995Sopenharmony_ci 4195db71995Sopenharmony_ci// Test failure during vkCreateInstance to make sure we don't leak memory if 4205db71995Sopenharmony_ci// one of the out-of-memory conditions trigger and there are invalid jsons in the same folder 4215db71995Sopenharmony_ciTEST(Allocation, CreateInstanceIntentionalAllocFailInvalidManifests) { 4225db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 4235db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); 4245db71995Sopenharmony_ci 4255db71995Sopenharmony_ci std::vector<std::string> invalid_jsons; 4265db71995Sopenharmony_ci invalid_jsons.push_back(","); 4275db71995Sopenharmony_ci invalid_jsons.push_back("{},[]"); 4285db71995Sopenharmony_ci invalid_jsons.push_back("{ \"foo\":\"bar\", }"); 4295db71995Sopenharmony_ci invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [], },"); 4305db71995Sopenharmony_ci invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": [{},] },"); 4315db71995Sopenharmony_ci invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\"} },"); 4325db71995Sopenharmony_ci invalid_jsons.push_back("{\"\":\"bar\", \"baz\": {}"); 4335db71995Sopenharmony_ci invalid_jsons.push_back("{\"foo\":\"bar\", \"baz\": {\"fee\":1234, true, \"ab\":\"bc\"} },"); 4345db71995Sopenharmony_ci 4355db71995Sopenharmony_ci for (size_t i = 0; i < invalid_jsons.size(); i++) { 4365db71995Sopenharmony_ci auto file_name = std::string("invalid_implicit_layer_") + std::to_string(i) + ".json"; 4375db71995Sopenharmony_ci fs::path new_path = env.get_folder(ManifestLocation::implicit_layer).write_manifest(file_name, invalid_jsons[i]); 4385db71995Sopenharmony_ci env.platform_shim->add_manifest(ManifestCategory::implicit_layer, new_path); 4395db71995Sopenharmony_ci } 4405db71995Sopenharmony_ci 4415db71995Sopenharmony_ci const char* layer_name = "VkLayerImplicit0"; 4425db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 4435db71995Sopenharmony_ci .set_name(layer_name) 4445db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 4455db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 4465db71995Sopenharmony_ci "test_layer.json"); 4475db71995Sopenharmony_ci 4485db71995Sopenharmony_ci size_t fail_index = 0; 4495db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 4505db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) { 4515db71995Sopenharmony_ci MemoryTracker tracker({false, 0, true, fail_index}); 4525db71995Sopenharmony_ci 4535db71995Sopenharmony_ci VkInstance instance; 4545db71995Sopenharmony_ci InstanceCreateInfo inst_create_info{}; 4555db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 4565db71995Sopenharmony_ci if (result == VK_SUCCESS) { 4575db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 4585db71995Sopenharmony_ci } 4595db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 4605db71995Sopenharmony_ci fail_index++; 4615db71995Sopenharmony_ci } 4625db71995Sopenharmony_ci} 4635db71995Sopenharmony_ci 4645db71995Sopenharmony_ci// Test failure during vkCreateInstance & surface creation to make sure we don't leak memory if 4655db71995Sopenharmony_ci// one of the out-of-memory conditions trigger. 4665db71995Sopenharmony_ciTEST(Allocation, CreateSurfaceIntentionalAllocFail) { 4675db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 4685db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).setup_WSI(); 4695db71995Sopenharmony_ci 4705db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 4715db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 4725db71995Sopenharmony_ci .set_name(layer_name) 4735db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 4745db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 4755db71995Sopenharmony_ci "test_layer.json"); 4765db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 4775db71995Sopenharmony_ci 4785db71995Sopenharmony_ci size_t fail_index = 0; 4795db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 4805db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) { 4815db71995Sopenharmony_ci MemoryTracker tracker({false, 0, true, fail_index}); 4825db71995Sopenharmony_ci 4835db71995Sopenharmony_ci VkInstance instance; 4845db71995Sopenharmony_ci InstanceCreateInfo inst_create_info{}; 4855db71995Sopenharmony_ci inst_create_info.setup_WSI(); 4865db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 4875db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 4885db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 4895db71995Sopenharmony_ci fail_index++; 4905db71995Sopenharmony_ci continue; 4915db71995Sopenharmony_ci } 4925db71995Sopenharmony_ci 4935db71995Sopenharmony_ci VkSurfaceKHR surface{}; 4945db71995Sopenharmony_ci result = create_surface(&env.vulkan_functions, instance, surface); 4955db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 4965db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 4975db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 4985db71995Sopenharmony_ci fail_index++; 4995db71995Sopenharmony_ci continue; 5005db71995Sopenharmony_ci } 5015db71995Sopenharmony_ci env.vulkan_functions.vkDestroySurfaceKHR(instance, surface, tracker.get()); 5025db71995Sopenharmony_ci 5035db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 5045db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 5055db71995Sopenharmony_ci fail_index++; 5065db71995Sopenharmony_ci } 5075db71995Sopenharmony_ci} 5085db71995Sopenharmony_ci 5095db71995Sopenharmony_ci// Test failure during vkCreateInstance to make sure we don't leak memory if 5105db71995Sopenharmony_ci// one of the out-of-memory conditions trigger. 5115db71995Sopenharmony_ciTEST(Allocation, CreateInstanceIntentionalAllocFailWithSettingsFilePresent) { 5125db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 5135db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); 5145db71995Sopenharmony_ci 5155db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 5165db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 5175db71995Sopenharmony_ci .set_name(layer_name) 5185db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 5195db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 5205db71995Sopenharmony_ci "test_layer.json"); 5215db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 5225db71995Sopenharmony_ci 5235db71995Sopenharmony_ci env.update_loader_settings( 5245db71995Sopenharmony_ci env.loader_settings.add_app_specific_setting(AppSpecificSettings{}.add_stderr_log_filter("all").add_layer_configuration( 5255db71995Sopenharmony_ci LoaderSettingsLayerConfiguration{} 5265db71995Sopenharmony_ci .set_name(layer_name) 5275db71995Sopenharmony_ci .set_control("auto") 5285db71995Sopenharmony_ci .set_path(env.get_shimmed_layer_manifest_path(0).str())))); 5295db71995Sopenharmony_ci 5305db71995Sopenharmony_ci size_t fail_index = 0; 5315db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 5325db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) { 5335db71995Sopenharmony_ci MemoryTracker tracker({false, 0, true, fail_index}); 5345db71995Sopenharmony_ci 5355db71995Sopenharmony_ci VkInstance instance; 5365db71995Sopenharmony_ci InstanceCreateInfo inst_create_info{}; 5375db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 5385db71995Sopenharmony_ci if (result == VK_SUCCESS) { 5395db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 5405db71995Sopenharmony_ci } 5415db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 5425db71995Sopenharmony_ci fail_index++; 5435db71995Sopenharmony_ci } 5445db71995Sopenharmony_ci} 5455db71995Sopenharmony_ci 5465db71995Sopenharmony_ci// Test failure during vkCreateInstance & surface creation to make sure we don't leak memory if 5475db71995Sopenharmony_ci// one of the out-of-memory conditions trigger. 5485db71995Sopenharmony_ciTEST(Allocation, CreateSurfaceIntentionalAllocFailWithSettingsFilePresent) { 5495db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 5505db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)).setup_WSI(); 5515db71995Sopenharmony_ci 5525db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 5535db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 5545db71995Sopenharmony_ci .set_name(layer_name) 5555db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 5565db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 5575db71995Sopenharmony_ci "test_layer.json"); 5585db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 5595db71995Sopenharmony_ci env.update_loader_settings( 5605db71995Sopenharmony_ci env.loader_settings.add_app_specific_setting(AppSpecificSettings{}.add_stderr_log_filter("all").add_layer_configuration( 5615db71995Sopenharmony_ci LoaderSettingsLayerConfiguration{} 5625db71995Sopenharmony_ci .set_name(layer_name) 5635db71995Sopenharmony_ci .set_control("auto") 5645db71995Sopenharmony_ci .set_path(env.get_shimmed_layer_manifest_path(0).str())))); 5655db71995Sopenharmony_ci 5665db71995Sopenharmony_ci size_t fail_index = 0; 5675db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 5685db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) { 5695db71995Sopenharmony_ci MemoryTracker tracker({false, 0, true, fail_index}); 5705db71995Sopenharmony_ci 5715db71995Sopenharmony_ci VkInstance instance; 5725db71995Sopenharmony_ci InstanceCreateInfo inst_create_info{}; 5735db71995Sopenharmony_ci inst_create_info.setup_WSI(); 5745db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 5755db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 5765db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 5775db71995Sopenharmony_ci fail_index++; 5785db71995Sopenharmony_ci continue; 5795db71995Sopenharmony_ci } 5805db71995Sopenharmony_ci 5815db71995Sopenharmony_ci VkSurfaceKHR surface{}; 5825db71995Sopenharmony_ci result = create_surface(&env.vulkan_functions, instance, surface); 5835db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 5845db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 5855db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 5865db71995Sopenharmony_ci fail_index++; 5875db71995Sopenharmony_ci continue; 5885db71995Sopenharmony_ci } 5895db71995Sopenharmony_ci env.vulkan_functions.vkDestroySurfaceKHR(instance, surface, tracker.get()); 5905db71995Sopenharmony_ci 5915db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 5925db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 5935db71995Sopenharmony_ci fail_index++; 5945db71995Sopenharmony_ci } 5955db71995Sopenharmony_ci} 5965db71995Sopenharmony_ci 5975db71995Sopenharmony_ci// Test failure during vkCreateInstance to make sure we don't leak memory if 5985db71995Sopenharmony_ci// one of the out-of-memory conditions trigger. 5995db71995Sopenharmony_ciTEST(Allocation, DriverEnvVarIntentionalAllocFail) { 6005db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 6015db71995Sopenharmony_ci env.add_icd(TestICDDetails{TEST_ICD_PATH_VERSION_2}.set_discovery_type(ManifestDiscoveryType::env_var)); 6025db71995Sopenharmony_ci 6035db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 6045db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 6055db71995Sopenharmony_ci .set_name(layer_name) 6065db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 6075db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 6085db71995Sopenharmony_ci "test_layer.json"); 6095db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 6105db71995Sopenharmony_ci 6115db71995Sopenharmony_ci env.env_var_vk_icd_filenames.add_to_list((fs::path("totally_made_up") / "path_to_fake" / "jason_file.json").str()); 6125db71995Sopenharmony_ci size_t fail_index = 0; 6135db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 6145db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) { 6155db71995Sopenharmony_ci MemoryTracker tracker({false, 0, true, fail_index}); 6165db71995Sopenharmony_ci 6175db71995Sopenharmony_ci VkInstance instance; 6185db71995Sopenharmony_ci InstanceCreateInfo inst_create_info{}; 6195db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 6205db71995Sopenharmony_ci if (result == VK_SUCCESS) { 6215db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 6225db71995Sopenharmony_ci } 6235db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 6245db71995Sopenharmony_ci fail_index++; 6255db71995Sopenharmony_ci } 6265db71995Sopenharmony_ci} 6275db71995Sopenharmony_ci 6285db71995Sopenharmony_ci// Test failure during vkCreateDevice to make sure we don't leak memory if 6295db71995Sopenharmony_ci// one of the out-of-memory conditions trigger. 6305db71995Sopenharmony_ci// Use 2 physical devices so that anything which copies a list of devices item by item 6315db71995Sopenharmony_ci// may fail. 6325db71995Sopenharmony_ciTEST(Allocation, CreateDeviceIntentionalAllocFail) { 6335db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 6345db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)) 6355db71995Sopenharmony_ci .add_physical_device(PhysicalDevice{"physical_device_0"} 6365db71995Sopenharmony_ci .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false}) 6375db71995Sopenharmony_ci .finish()) 6385db71995Sopenharmony_ci .add_physical_device(PhysicalDevice{"physical_device_1"} 6395db71995Sopenharmony_ci .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false}) 6405db71995Sopenharmony_ci .finish()); 6415db71995Sopenharmony_ci 6425db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 6435db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 6445db71995Sopenharmony_ci .set_name(layer_name) 6455db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 6465db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 6475db71995Sopenharmony_ci "test_layer.json"); 6485db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 6495db71995Sopenharmony_ci 6505db71995Sopenharmony_ci InstWrapper inst{env.vulkan_functions}; 6515db71995Sopenharmony_ci ASSERT_NO_FATAL_FAILURE(inst.CheckCreate()); 6525db71995Sopenharmony_ci 6535db71995Sopenharmony_ci uint32_t physical_count = 2; 6545db71995Sopenharmony_ci uint32_t returned_physical_count = 0; 6555db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, nullptr)); 6565db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 6575db71995Sopenharmony_ci 6585db71995Sopenharmony_ci VkPhysicalDevice physical_devices[2]; 6595db71995Sopenharmony_ci ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst.inst, &returned_physical_count, physical_devices)); 6605db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 6615db71995Sopenharmony_ci 6625db71995Sopenharmony_ci uint32_t family_count = 1; 6635db71995Sopenharmony_ci uint32_t returned_family_count = 0; 6645db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[0], &returned_family_count, nullptr); 6655db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 6665db71995Sopenharmony_ci 6675db71995Sopenharmony_ci VkQueueFamilyProperties family; 6685db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[0], &returned_family_count, &family); 6695db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 6705db71995Sopenharmony_ci ASSERT_EQ(family.queueFlags, static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT)); 6715db71995Sopenharmony_ci ASSERT_EQ(family.queueCount, family_count); 6725db71995Sopenharmony_ci ASSERT_EQ(family.timestampValidBits, 0U); 6735db71995Sopenharmony_ci 6745db71995Sopenharmony_ci size_t fail_index = 0; 6755db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 6765db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 6775db71995Sopenharmony_ci MemoryTracker tracker({false, 0, true, fail_index}); 6785db71995Sopenharmony_ci 6795db71995Sopenharmony_ci DeviceCreateInfo dev_create_info; 6805db71995Sopenharmony_ci dev_create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); 6815db71995Sopenharmony_ci 6825db71995Sopenharmony_ci VkDevice device; 6835db71995Sopenharmony_ci result = inst->vkCreateDevice(physical_devices[0], dev_create_info.get(), tracker.get(), &device); 6845db71995Sopenharmony_ci if (result == VK_SUCCESS || fail_index > 10000) { 6855db71995Sopenharmony_ci VkQueue queue; 6865db71995Sopenharmony_ci inst->vkGetDeviceQueue(device, 0, 0, &queue); 6875db71995Sopenharmony_ci 6885db71995Sopenharmony_ci inst->vkDestroyDevice(device, tracker.get()); 6895db71995Sopenharmony_ci break; 6905db71995Sopenharmony_ci } 6915db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 6925db71995Sopenharmony_ci fail_index++; 6935db71995Sopenharmony_ci } 6945db71995Sopenharmony_ci} 6955db71995Sopenharmony_ci 6965db71995Sopenharmony_ci// Test failure during vkCreateInstance and vkCreateDevice to make sure we don't 6975db71995Sopenharmony_ci// leak memory if one of the out-of-memory conditions trigger. 6985db71995Sopenharmony_ci// Includes drivers with several instance extensions, drivers that will fail to load, directly loaded drivers 6995db71995Sopenharmony_ciTEST(Allocation, CreateInstanceDeviceIntentionalAllocFail) { 7005db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 7015db71995Sopenharmony_ci uint32_t num_physical_devices = 4; 7025db71995Sopenharmony_ci uint32_t num_implicit_layers = 3; 7035db71995Sopenharmony_ci for (uint32_t i = 0; i < num_physical_devices; i++) { 7045db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2) 7055db71995Sopenharmony_ci .icd_manifest.set_is_portability_driver(false) 7065db71995Sopenharmony_ci .set_library_arch(sizeof(void*) == 8 ? "64" : "32")) 7075db71995Sopenharmony_ci .set_icd_api_version(VK_API_VERSION_1_1) 7085db71995Sopenharmony_ci .add_instance_extension("VK_KHR_get_physical_device_properties2") 7095db71995Sopenharmony_ci .add_physical_device("physical_device_0") 7105db71995Sopenharmony_ci .physical_devices.at(0) 7115db71995Sopenharmony_ci .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false}) 7125db71995Sopenharmony_ci .add_extensions({"VK_EXT_one", "VK_EXT_two", "VK_EXT_three", "VK_EXT_four", "VK_EXT_five"}); 7135db71995Sopenharmony_ci } 7145db71995Sopenharmony_ci 7155db71995Sopenharmony_ci env.add_icd(TestICDDetails(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE).set_is_fake(true)); 7165db71995Sopenharmony_ci 7175db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_7).set_discovery_type(ManifestDiscoveryType::none)); 7185db71995Sopenharmony_ci 7195db71995Sopenharmony_ci VkDirectDriverLoadingInfoLUNARG ddl_info{}; 7205db71995Sopenharmony_ci ddl_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG; 7215db71995Sopenharmony_ci ddl_info.pfnGetInstanceProcAddr = env.icds.back().icd_library.get_symbol("vk_icdGetInstanceProcAddr"); 7225db71995Sopenharmony_ci 7235db71995Sopenharmony_ci VkDirectDriverLoadingListLUNARG ddl_list{}; 7245db71995Sopenharmony_ci ddl_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG; 7255db71995Sopenharmony_ci ddl_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG; 7265db71995Sopenharmony_ci ddl_list.driverCount = 1; 7275db71995Sopenharmony_ci ddl_list.pDrivers = &ddl_info; 7285db71995Sopenharmony_ci 7295db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_ImplicitAllocFail"; 7305db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 7315db71995Sopenharmony_ci .set_name(layer_name) 7325db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 7335db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 7345db71995Sopenharmony_ci "test_layer.json"); 7355db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 7365db71995Sopenharmony_ci for (uint32_t i = 1; i < num_implicit_layers + 1; i++) { 7375db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 7385db71995Sopenharmony_ci .set_name("VK_LAYER_Implicit1" + std::to_string(i)) 7395db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 7405db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 7415db71995Sopenharmony_ci "test_layer_" + std::to_string(i) + ".json"); 7425db71995Sopenharmony_ci } 7435db71995Sopenharmony_ci std::fstream custom_json_file{COMPLEX_JSON_FILE, std::ios_base::in}; 7445db71995Sopenharmony_ci ASSERT_TRUE(custom_json_file.is_open()); 7455db71995Sopenharmony_ci std::stringstream custom_json_file_contents; 7465db71995Sopenharmony_ci custom_json_file_contents << custom_json_file.rdbuf(); 7475db71995Sopenharmony_ci 7485db71995Sopenharmony_ci fs::path new_path = env.get_folder(ManifestLocation::explicit_layer) 7495db71995Sopenharmony_ci .write_manifest("VK_LAYER_complex_file.json", custom_json_file_contents.str()); 7505db71995Sopenharmony_ci env.platform_shim->add_manifest(ManifestCategory::explicit_layer, new_path); 7515db71995Sopenharmony_ci 7525db71995Sopenharmony_ci size_t fail_index = 0; 7535db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 7545db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) { 7555db71995Sopenharmony_ci MemoryTracker tracker{{false, 0, true, fail_index}}; 7565db71995Sopenharmony_ci fail_index++; // applies to the next loop 7575db71995Sopenharmony_ci 7585db71995Sopenharmony_ci VkInstance instance; 7595db71995Sopenharmony_ci InstanceCreateInfo inst_create_info{}; 7605db71995Sopenharmony_ci inst_create_info.add_extension(VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME); 7615db71995Sopenharmony_ci inst_create_info.instance_info.pNext = reinterpret_cast<const void*>(&ddl_list); 7625db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 7635db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 7645db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 7655db71995Sopenharmony_ci continue; 7665db71995Sopenharmony_ci } 7675db71995Sopenharmony_ci ASSERT_EQ(result, VK_SUCCESS); 7685db71995Sopenharmony_ci 7695db71995Sopenharmony_ci uint32_t returned_physical_count = 0; 7705db71995Sopenharmony_ci result = env.vulkan_functions.vkEnumeratePhysicalDevices(instance, &returned_physical_count, nullptr); 7715db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 7725db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 7735db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 7745db71995Sopenharmony_ci continue; 7755db71995Sopenharmony_ci } 7765db71995Sopenharmony_ci ASSERT_EQ(result, VK_SUCCESS); 7775db71995Sopenharmony_ci ASSERT_EQ(num_physical_devices, returned_physical_count); 7785db71995Sopenharmony_ci 7795db71995Sopenharmony_ci std::vector<VkPhysicalDevice> physical_devices; 7805db71995Sopenharmony_ci physical_devices.resize(returned_physical_count); 7815db71995Sopenharmony_ci result = env.vulkan_functions.vkEnumeratePhysicalDevices(instance, &returned_physical_count, physical_devices.data()); 7825db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 7835db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 7845db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 7855db71995Sopenharmony_ci continue; 7865db71995Sopenharmony_ci } 7875db71995Sopenharmony_ci ASSERT_EQ(result, VK_SUCCESS); 7885db71995Sopenharmony_ci ASSERT_EQ(num_physical_devices, returned_physical_count); 7895db71995Sopenharmony_ci for (uint32_t i = 0; i < returned_physical_count; i++) { 7905db71995Sopenharmony_ci uint32_t family_count = 1; 7915db71995Sopenharmony_ci uint32_t returned_family_count = 0; 7925db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices.at(i), &returned_family_count, nullptr); 7935db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 7945db71995Sopenharmony_ci 7955db71995Sopenharmony_ci VkQueueFamilyProperties family; 7965db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices.at(i), &returned_family_count, &family); 7975db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 7985db71995Sopenharmony_ci ASSERT_EQ(family.queueFlags, static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT)); 7995db71995Sopenharmony_ci ASSERT_EQ(family.queueCount, family_count); 8005db71995Sopenharmony_ci ASSERT_EQ(family.timestampValidBits, 0U); 8015db71995Sopenharmony_ci 8025db71995Sopenharmony_ci DeviceCreateInfo dev_create_info; 8035db71995Sopenharmony_ci dev_create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); 8045db71995Sopenharmony_ci 8055db71995Sopenharmony_ci VkDevice device; 8065db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateDevice(physical_devices.at(i), dev_create_info.get(), tracker.get(), &device); 8075db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 8085db71995Sopenharmony_ci break; 8095db71995Sopenharmony_ci } 8105db71995Sopenharmony_ci ASSERT_EQ(result, VK_SUCCESS); 8115db71995Sopenharmony_ci 8125db71995Sopenharmony_ci VkQueue queue; 8135db71995Sopenharmony_ci env.vulkan_functions.vkGetDeviceQueue(device, 0, 0, &queue); 8145db71995Sopenharmony_ci 8155db71995Sopenharmony_ci env.vulkan_functions.vkDestroyDevice(device, tracker.get()); 8165db71995Sopenharmony_ci } 8175db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 8185db71995Sopenharmony_ci 8195db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 8205db71995Sopenharmony_ci } 8215db71995Sopenharmony_ci} 8225db71995Sopenharmony_ci 8235db71995Sopenharmony_ci// Test failure during vkCreateInstance when a driver of the wrong architecture is present 8245db71995Sopenharmony_ci// to make sure the loader uses the valid ICD and doesn't report incompatible driver just because 8255db71995Sopenharmony_ci// an incompatible driver exists 8265db71995Sopenharmony_ciTEST(TryLoadWrongBinaries, CreateInstanceIntentionalAllocFail) { 8275db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 8285db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); 8295db71995Sopenharmony_ci env.add_icd(TestICDDetails(CURRENT_PLATFORM_DUMMY_BINARY_WRONG_TYPE).set_is_fake(true)); 8305db71995Sopenharmony_ci 8315db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 8325db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 8335db71995Sopenharmony_ci .set_name(layer_name) 8345db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 8355db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 8365db71995Sopenharmony_ci "test_layer.json"); 8375db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 8385db71995Sopenharmony_ci 8395db71995Sopenharmony_ci size_t fail_index = 0; 8405db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 8415db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) { 8425db71995Sopenharmony_ci MemoryTracker tracker({false, 0, true, fail_index}); 8435db71995Sopenharmony_ci 8445db71995Sopenharmony_ci VkInstance instance; 8455db71995Sopenharmony_ci InstanceCreateInfo inst_create_info{}; 8465db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 8475db71995Sopenharmony_ci if (result == VK_SUCCESS) { 8485db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 8495db71995Sopenharmony_ci } 8505db71995Sopenharmony_ci ASSERT_NE(result, VK_ERROR_INCOMPATIBLE_DRIVER); 8515db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 8525db71995Sopenharmony_ci fail_index++; 8535db71995Sopenharmony_ci } 8545db71995Sopenharmony_ci} 8555db71995Sopenharmony_ci 8565db71995Sopenharmony_ci// Test failure during vkCreateInstance and vkCreateDevice to make sure we don't 8575db71995Sopenharmony_ci// leak memory if one of the out-of-memory conditions trigger. 8585db71995Sopenharmony_ciTEST(Allocation, EnumeratePhysicalDevicesIntentionalAllocFail) { 8595db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 8605db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); 8615db71995Sopenharmony_ci 8625db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 8635db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 8645db71995Sopenharmony_ci .set_name(layer_name) 8655db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 8665db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 8675db71995Sopenharmony_ci "test_layer.json"); 8685db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 8695db71995Sopenharmony_ci 8705db71995Sopenharmony_ci size_t fail_index = 0; 8715db71995Sopenharmony_ci bool reached_the_end = false; 8725db71995Sopenharmony_ci uint32_t starting_physical_dev_count = 3; 8735db71995Sopenharmony_ci while (!reached_the_end && fail_index <= 100) { 8745db71995Sopenharmony_ci fail_index++; // applies to the next loop 8755db71995Sopenharmony_ci uint32_t physical_dev_count = starting_physical_dev_count; 8765db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 8775db71995Sopenharmony_ci auto& driver = env.reset_icd(); 8785db71995Sopenharmony_ci 8795db71995Sopenharmony_ci for (uint32_t i = 0; i < physical_dev_count; i++) { 8805db71995Sopenharmony_ci driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i)) 8815db71995Sopenharmony_ci .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false}); 8825db71995Sopenharmony_ci } 8835db71995Sopenharmony_ci MemoryTracker tracker{{false, 0, true, fail_index}}; 8845db71995Sopenharmony_ci InstanceCreateInfo inst_create_info; 8855db71995Sopenharmony_ci VkInstance instance; 8865db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 8875db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 8885db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 8895db71995Sopenharmony_ci continue; 8905db71995Sopenharmony_ci } 8915db71995Sopenharmony_ci 8925db71995Sopenharmony_ci uint32_t returned_physical_count = 0; 8935db71995Sopenharmony_ci result = env.vulkan_functions.vkEnumeratePhysicalDevices(instance, &returned_physical_count, nullptr); 8945db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 8955db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 8965db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 8975db71995Sopenharmony_ci continue; 8985db71995Sopenharmony_ci } 8995db71995Sopenharmony_ci ASSERT_EQ(physical_dev_count, returned_physical_count); 9005db71995Sopenharmony_ci 9015db71995Sopenharmony_ci for (uint32_t i = 0; i < 2; i++) { 9025db71995Sopenharmony_ci driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(physical_dev_count)) 9035db71995Sopenharmony_ci .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false}); 9045db71995Sopenharmony_ci physical_dev_count += 1; 9055db71995Sopenharmony_ci } 9065db71995Sopenharmony_ci 9075db71995Sopenharmony_ci std::vector<VkPhysicalDevice> physical_devices{physical_dev_count, VK_NULL_HANDLE}; 9085db71995Sopenharmony_ci result = env.vulkan_functions.vkEnumeratePhysicalDevices(instance, &returned_physical_count, physical_devices.data()); 9095db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 9105db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 9115db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 9125db71995Sopenharmony_ci continue; 9135db71995Sopenharmony_ci } 9145db71995Sopenharmony_ci if (result == VK_INCOMPLETE) { 9155db71995Sopenharmony_ci result = env.vulkan_functions.vkEnumeratePhysicalDevices(instance, &returned_physical_count, nullptr); 9165db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 9175db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 9185db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 9195db71995Sopenharmony_ci continue; 9205db71995Sopenharmony_ci } 9215db71995Sopenharmony_ci physical_devices.resize(returned_physical_count); 9225db71995Sopenharmony_ci result = env.vulkan_functions.vkEnumeratePhysicalDevices(instance, &returned_physical_count, physical_devices.data()); 9235db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 9245db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 9255db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 9265db71995Sopenharmony_ci continue; 9275db71995Sopenharmony_ci } 9285db71995Sopenharmony_ci } 9295db71995Sopenharmony_ci ASSERT_EQ(physical_dev_count, returned_physical_count); 9305db71995Sopenharmony_ci 9315db71995Sopenharmony_ci std::array<VkDevice, 5> devices; 9325db71995Sopenharmony_ci for (uint32_t i = 0; i < returned_physical_count; i++) { 9335db71995Sopenharmony_ci uint32_t family_count = 1; 9345db71995Sopenharmony_ci uint32_t returned_family_count = 0; 9355db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &returned_family_count, nullptr); 9365db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 9375db71995Sopenharmony_ci 9385db71995Sopenharmony_ci VkQueueFamilyProperties family; 9395db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &returned_family_count, &family); 9405db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 9415db71995Sopenharmony_ci ASSERT_EQ(family.queueFlags, static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT)); 9425db71995Sopenharmony_ci ASSERT_EQ(family.queueCount, family_count); 9435db71995Sopenharmony_ci ASSERT_EQ(family.timestampValidBits, 0U); 9445db71995Sopenharmony_ci 9455db71995Sopenharmony_ci DeviceCreateInfo dev_create_info; 9465db71995Sopenharmony_ci dev_create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); 9475db71995Sopenharmony_ci 9485db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateDevice(physical_devices[i], dev_create_info.get(), tracker.get(), &devices[i]); 9495db71995Sopenharmony_ci 9505db71995Sopenharmony_ci VkQueue queue; 9515db71995Sopenharmony_ci if (result == VK_SUCCESS) { 9525db71995Sopenharmony_ci env.vulkan_functions.vkGetDeviceQueue(devices[i], 0, 0, &queue); 9535db71995Sopenharmony_ci } 9545db71995Sopenharmony_ci } 9555db71995Sopenharmony_ci for (uint32_t i = 0; i < returned_physical_count; i++) { 9565db71995Sopenharmony_ci if (result == VK_SUCCESS) { 9575db71995Sopenharmony_ci env.vulkan_functions.vkDestroyDevice(devices[i], tracker.get()); 9585db71995Sopenharmony_ci } 9595db71995Sopenharmony_ci } 9605db71995Sopenharmony_ci 9615db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 9625db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 9635db71995Sopenharmony_ci reached_the_end = true; 9645db71995Sopenharmony_ci } 9655db71995Sopenharmony_ci} 9665db71995Sopenharmony_ci#if defined(WIN32) 9675db71995Sopenharmony_ci// Test failure during vkCreateInstance and vkCreateDevice to make sure we don't 9685db71995Sopenharmony_ci// leak memory if one of the out-of-memory conditions trigger. 9695db71995Sopenharmony_ciTEST(Allocation, CreateInstanceDeviceWithDXGIDriverIntentionalAllocFail) { 9705db71995Sopenharmony_ci FrameworkEnvironment env{FrameworkSettings{}.set_log_filter("error,warn")}; 9715db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6).set_discovery_type(ManifestDiscoveryType::null_dir)); 9725db71995Sopenharmony_ci env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2)); 9735db71995Sopenharmony_ci 9745db71995Sopenharmony_ci for (uint32_t i = 0; i < 2; i++) { 9755db71995Sopenharmony_ci auto& driver = env.get_test_icd(i); 9765db71995Sopenharmony_ci driver.physical_devices.emplace_back(std::string("physical_device_") + std::to_string(i)) 9775db71995Sopenharmony_ci .add_queue_family_properties({{VK_QUEUE_GRAPHICS_BIT, 1, 0, {1, 1, 1}}, false}); 9785db71995Sopenharmony_ci } 9795db71995Sopenharmony_ci 9805db71995Sopenharmony_ci const char* layer_name = "VK_LAYER_implicit"; 9815db71995Sopenharmony_ci env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{} 9825db71995Sopenharmony_ci .set_name(layer_name) 9835db71995Sopenharmony_ci .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2) 9845db71995Sopenharmony_ci .set_disable_environment("DISABLE_ENV")), 9855db71995Sopenharmony_ci "test_layer.json"); 9865db71995Sopenharmony_ci env.get_test_layer().set_do_spurious_allocations_in_create_instance(true).set_do_spurious_allocations_in_create_device(true); 9875db71995Sopenharmony_ci 9885db71995Sopenharmony_ci auto& known_driver = known_driver_list.at(2); // which drive this test pretends to be 9895db71995Sopenharmony_ci DXGI_ADAPTER_DESC1 desc1{}; 9905db71995Sopenharmony_ci desc1.VendorId = known_driver.vendor_id; 9915db71995Sopenharmony_ci desc1.AdapterLuid = _LUID{10, 1000}; 9925db71995Sopenharmony_ci env.platform_shim->add_dxgi_adapter(GpuType::discrete, desc1); 9935db71995Sopenharmony_ci env.get_test_icd(0).set_adapterLUID(desc1.AdapterLuid); 9945db71995Sopenharmony_ci 9955db71995Sopenharmony_ci env.platform_shim->add_d3dkmt_adapter(D3DKMT_Adapter{0, _LUID{10, 1000}}.add_driver_manifest_path(env.get_icd_manifest_path())); 9965db71995Sopenharmony_ci 9975db71995Sopenharmony_ci size_t fail_index = 0; 9985db71995Sopenharmony_ci VkResult result = VK_ERROR_OUT_OF_HOST_MEMORY; 9995db71995Sopenharmony_ci while (result == VK_ERROR_OUT_OF_HOST_MEMORY && fail_index <= 10000) { 10005db71995Sopenharmony_ci MemoryTracker tracker({false, 0, true, fail_index}); 10015db71995Sopenharmony_ci fail_index++; // applies to the next loop 10025db71995Sopenharmony_ci 10035db71995Sopenharmony_ci VkInstance instance; 10045db71995Sopenharmony_ci InstanceCreateInfo inst_create_info{}; 10055db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateInstance(inst_create_info.get(), tracker.get(), &instance); 10065db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 10075db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 10085db71995Sopenharmony_ci continue; 10095db71995Sopenharmony_ci } 10105db71995Sopenharmony_ci 10115db71995Sopenharmony_ci uint32_t physical_count = 2; 10125db71995Sopenharmony_ci uint32_t returned_physical_count = 0; 10135db71995Sopenharmony_ci result = env.vulkan_functions.vkEnumeratePhysicalDevices(instance, &returned_physical_count, nullptr); 10145db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_INCOMPLETE) { 10155db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 10165db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 10175db71995Sopenharmony_ci continue; 10185db71995Sopenharmony_ci } 10195db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 10205db71995Sopenharmony_ci 10215db71995Sopenharmony_ci std::array<VkPhysicalDevice, 2> physical_devices; 10225db71995Sopenharmony_ci result = env.vulkan_functions.vkEnumeratePhysicalDevices(instance, &returned_physical_count, physical_devices.data()); 10235db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_INCOMPLETE) { 10245db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 10255db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 10265db71995Sopenharmony_ci continue; 10275db71995Sopenharmony_ci } 10285db71995Sopenharmony_ci ASSERT_EQ(physical_count, returned_physical_count); 10295db71995Sopenharmony_ci 10305db71995Sopenharmony_ci std::array<VkDevice, 2> devices; 10315db71995Sopenharmony_ci for (uint32_t i = 0; i < returned_physical_count; i++) { 10325db71995Sopenharmony_ci uint32_t family_count = 1; 10335db71995Sopenharmony_ci uint32_t returned_family_count = 0; 10345db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &returned_family_count, nullptr); 10355db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 10365db71995Sopenharmony_ci 10375db71995Sopenharmony_ci VkQueueFamilyProperties family; 10385db71995Sopenharmony_ci env.vulkan_functions.vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[i], &returned_family_count, &family); 10395db71995Sopenharmony_ci ASSERT_EQ(returned_family_count, family_count); 10405db71995Sopenharmony_ci ASSERT_EQ(family.queueFlags, static_cast<VkQueueFlags>(VK_QUEUE_GRAPHICS_BIT)); 10415db71995Sopenharmony_ci ASSERT_EQ(family.queueCount, family_count); 10425db71995Sopenharmony_ci ASSERT_EQ(family.timestampValidBits, 0U); 10435db71995Sopenharmony_ci 10445db71995Sopenharmony_ci DeviceCreateInfo dev_create_info; 10455db71995Sopenharmony_ci dev_create_info.add_device_queue(DeviceQueueCreateInfo{}.add_priority(0.0f)); 10465db71995Sopenharmony_ci 10475db71995Sopenharmony_ci result = env.vulkan_functions.vkCreateDevice(physical_devices[i], dev_create_info.get(), tracker.get(), &devices[i]); 10485db71995Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) { 10495db71995Sopenharmony_ci devices[i] = VK_NULL_HANDLE; 10505db71995Sopenharmony_ci } else { 10515db71995Sopenharmony_ci VkQueue queue; 10525db71995Sopenharmony_ci env.vulkan_functions.vkGetDeviceQueue(devices[i], 0, 0, &queue); 10535db71995Sopenharmony_ci } 10545db71995Sopenharmony_ci } 10555db71995Sopenharmony_ci for (uint32_t i = 0; i < returned_physical_count; i++) { 10565db71995Sopenharmony_ci if (devices[i] != VK_NULL_HANDLE) { 10575db71995Sopenharmony_ci env.vulkan_functions.vkDestroyDevice(devices[i], tracker.get()); 10585db71995Sopenharmony_ci } 10595db71995Sopenharmony_ci } 10605db71995Sopenharmony_ci env.vulkan_functions.vkDestroyInstance(instance, tracker.get()); 10615db71995Sopenharmony_ci 10625db71995Sopenharmony_ci ASSERT_TRUE(tracker.empty()); 10635db71995Sopenharmony_ci } 10645db71995Sopenharmony_ci} 10655db71995Sopenharmony_ci#endif 1066