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