From 6e54911cddef507a4c3799a85ec2f811b8763542 Mon Sep 17 00:00:00 2001 From: Maciej Bielski Date: Wed, 14 May 2025 14:29:05 +0000 Subject: [PATCH] fix: do not evict explicitly resident allocations Related-To: NEO-13428 Signed-off-by: Maciej Bielski --- .../windows/wddm_residency_handler_tests.cpp | 147 +-------------- .../wddm_memory_operations_handler.cpp | 2 +- .../wddm_residency_allocations_container.cpp | 4 + .../wddm_residency_allocations_container.h | 2 + .../os_interface/windows/CMakeLists.txt | 1 + .../wddm_memory_operations_handler_tests.cpp | 174 ++++++++++++++++++ 6 files changed, 184 insertions(+), 146 deletions(-) create mode 100644 shared/test/unit_test/os_interface/windows/wddm_memory_operations_handler_tests.cpp diff --git a/opencl/test/unit_test/os_interface/windows/wddm_residency_handler_tests.cpp b/opencl/test/unit_test/os_interface/windows/wddm_residency_handler_tests.cpp index 1d7f59b372..287071094e 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm_residency_handler_tests.cpp +++ b/opencl/test/unit_test/os_interface/windows/wddm_residency_handler_tests.cpp @@ -5,17 +5,12 @@ * */ +#include "shared/source/execution_environment/root_device_environment.h" #include "shared/source/os_interface/windows/wddm_memory_operations_handler.h" -#include "shared/source/utilities/stackvec.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/helpers/ult_hw_config.h" #include "shared/test/common/helpers/variable_backup.h" -#include "shared/test/common/mocks/mock_allocation_properties.h" -#include "shared/test/common/mocks/mock_device.h" -#include "shared/test/common/mocks/mock_wddm.h" -#include "shared/test/common/mocks/windows/mock_wddm_allocation.h" -#include "shared/test/common/os_interface/windows/wddm_fixture.h" -#include "shared/test/common/test_macros/hw_test.h" +#include "shared/test/common/test_macros/test.h" #include "opencl/source/cl_device/cl_device.h" #include "opencl/source/mem_obj/mem_obj.h" @@ -24,144 +19,6 @@ using namespace NEO; -struct WddmMemoryOperationsHandlerTest : public WddmTest { - void SetUp() override { - WddmTest::SetUp(); - wddmMemoryOperationsHandler = std::make_unique(wddm); - wddmAllocation = std::make_unique(rootDeviceEnvironment->getGmmHelper()); - wddmFragmentedAllocation = std::make_unique(rootDeviceEnvironment->getGmmHelper()); - wddmAllocation->handle = 0x2u; - - osHandleStorageFirst = std::make_unique(); - osHandleStorageSecond = std::make_unique(); - - wddmFragmentedAllocation->fragmentsStorage.fragmentCount = 2; - wddmFragmentedAllocation->fragmentsStorage.fragmentStorageData[0].osHandleStorage = osHandleStorageFirst.get(); - static_cast(wddmFragmentedAllocation->fragmentsStorage.fragmentStorageData[0].osHandleStorage)->handle = 0x3u; - wddmFragmentedAllocation->fragmentsStorage.fragmentStorageData[1].osHandleStorage = osHandleStorageSecond.get(); - static_cast(wddmFragmentedAllocation->fragmentsStorage.fragmentStorageData[1].osHandleStorage)->handle = 0x4u; - - allocationPtr = wddmAllocation.get(); - - allocationData.push_back(wddmAllocation.get()); - allocationData.push_back(wddmFragmentedAllocation.get()); - } - - std::unique_ptr wddmMemoryOperationsHandler; - std::unique_ptr wddmAllocation; - std::unique_ptr wddmFragmentedAllocation; - std::unique_ptr osHandleStorageFirst; - std::unique_ptr osHandleStorageSecond; - GraphicsAllocation *allocationPtr; - StackVec allocationData; -}; - -TEST_F(WddmMemoryOperationsHandlerTest, givenRegularAllocationWhenMakingResidentAllocationThenMakeResidentIsCalledAndAllocationIsMarkedAsExplicitlyResident) { - wddmAllocation->setExplicitlyMadeResident(false); - EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(&allocationPtr, 1), false, false), MemoryOperationsStatus::success); - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::success); - EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); -} - -TEST_F(WddmMemoryOperationsHandlerTest, givenFragmentedAllocationWhenMakingResidentAllocationThenMakeResidentIsCalledAndAllocationIsMarkedAsExplicitlyResident) { - allocationPtr = wddmFragmentedAllocation.get(); - allocationPtr->setExplicitlyMadeResident(false); - - EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(&allocationPtr, 1), false, false), MemoryOperationsStatus::success); - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); - EXPECT_TRUE(allocationPtr->isExplicitlyMadeResident()); -} - -TEST_F(WddmMemoryOperationsHandlerTest, givenVariousAllocationsWhenMakingResidentAllocationThenMakeResidentCalled) { - - for (auto &allocation : allocationData) { - allocation->setExplicitlyMadeResident(false); - } - - EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(allocationData), false, false), MemoryOperationsStatus::success); - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::success); - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); - - for (auto &allocation : allocationData) { - EXPECT_TRUE(allocation->isExplicitlyMadeResident()); - } -} - -TEST_F(WddmMemoryOperationsHandlerTest, givenRegularAllocationWhenEvictingResidentAllocationThenEvictCalled) { - wddm->callBaseEvict = true; - allocationPtr->setExplicitlyMadeResident(false); - - EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(&allocationPtr, 1), false, false), MemoryOperationsStatus::success); - EXPECT_TRUE(allocationPtr->isExplicitlyMadeResident()); - - EXPECT_EQ(wddmMemoryOperationsHandler->evict(nullptr, *wddmAllocation), MemoryOperationsStatus::success); - EXPECT_FALSE(allocationPtr->isExplicitlyMadeResident()); - - EXPECT_EQ(0u, gdi->getEvictArg().Flags.EvictOnlyIfNecessary); - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::memoryNotFound); -} - -TEST_F(WddmMemoryOperationsHandlerTest, givenFragmentedAllocationWhenEvictingResidentAllocationThenEvictCalled) { - allocationPtr = wddmFragmentedAllocation.get(); - allocationPtr->setExplicitlyMadeResident(false); - - EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(&allocationPtr, 1), false, false), MemoryOperationsStatus::success); - EXPECT_TRUE(allocationPtr->isExplicitlyMadeResident()); - - EXPECT_EQ(wddmMemoryOperationsHandler->evict(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); - EXPECT_FALSE(allocationPtr->isExplicitlyMadeResident()); - - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::memoryNotFound); -} - -TEST_F(WddmMemoryOperationsHandlerTest, givenVariousAllocationsWhenEvictingResidentAllocationThenEvictCalled) { - for (auto &allocation : allocationData) { - allocation->setExplicitlyMadeResident(false); - } - wddm->evictResult.called = 0; - EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(allocationData), false, false), MemoryOperationsStatus::success); - EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); - EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); - - EXPECT_EQ(wddmMemoryOperationsHandler->evict(nullptr, *wddmAllocation), MemoryOperationsStatus::success); - EXPECT_FALSE(wddmAllocation->isExplicitlyMadeResident()); - EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); - EXPECT_EQ(1u, wddm->evictResult.called); - - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::memoryNotFound); - - EXPECT_EQ(wddmMemoryOperationsHandler->evict(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); - EXPECT_FALSE(wddmAllocation->isExplicitlyMadeResident()); - EXPECT_FALSE(wddmFragmentedAllocation->isExplicitlyMadeResident()); - EXPECT_EQ(2u, wddm->evictResult.called); - - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::memoryNotFound); -} - -TEST_F(WddmMemoryOperationsHandlerTest, givenVariousAllocationsWhenFreeResidentAllocationThenAllocationIsRemovedButEvictIsNotCalled) { - for (auto &allocation : allocationData) { - allocation->setExplicitlyMadeResident(false); - } - wddm->evictResult.called = 0; - EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(allocationData), false, false), MemoryOperationsStatus::success); - EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); - EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); - - EXPECT_EQ(wddmMemoryOperationsHandler->free(nullptr, *wddmAllocation), MemoryOperationsStatus::success); - EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); - EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); - EXPECT_EQ(0u, wddm->evictResult.called); - - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::memoryNotFound); - - EXPECT_EQ(wddmMemoryOperationsHandler->free(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); - EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); - EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); - EXPECT_EQ(0u, wddm->evictResult.called); - - EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::memoryNotFound); -} - TEST(WddmResidentBufferTests, whenBuffersIsCreatedWithMakeResidentFlagSetThenItIsMadeResidentUponCreation) { VariableBackup backup(&ultHwConfig); ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false; diff --git a/shared/source/os_interface/windows/wddm_memory_operations_handler.cpp b/shared/source/os_interface/windows/wddm_memory_operations_handler.cpp index cc8e40bca6..db9e79e0d6 100644 --- a/shared/source/os_interface/windows/wddm_memory_operations_handler.cpp +++ b/shared/source/os_interface/windows/wddm_memory_operations_handler.cpp @@ -15,7 +15,7 @@ namespace NEO { WddmMemoryOperationsHandler::WddmMemoryOperationsHandler(Wddm *wddm) : wddm(wddm) { - residentAllocations = std::make_unique(wddm); + residentAllocations = std::make_unique(wddm, false); } WddmMemoryOperationsHandler::~WddmMemoryOperationsHandler() = default; diff --git a/shared/source/os_interface/windows/wddm_residency_allocations_container.cpp b/shared/source/os_interface/windows/wddm_residency_allocations_container.cpp index 472a532987..1774e54772 100644 --- a/shared/source/os_interface/windows/wddm_residency_allocations_container.cpp +++ b/shared/source/os_interface/windows/wddm_residency_allocations_container.cpp @@ -66,6 +66,10 @@ MemoryOperationsStatus WddmResidentAllocationsContainer::makeResidentResource(co MemoryOperationsStatus WddmResidentAllocationsContainer::makeResidentResources(const D3DKMT_HANDLE *handles, const uint32_t count, size_t size, const bool forcePagingFence) { while (!wddm->makeResident(handles, count, false, nullptr, size)) { + if (!isEvictionOnMakeResidentAllowed) { + DEBUG_BREAK_IF(true); + return MemoryOperationsStatus::outOfMemory; + } if (evictAllResources() == MemoryOperationsStatus::success) { continue; } diff --git a/shared/source/os_interface/windows/wddm_residency_allocations_container.h b/shared/source/os_interface/windows/wddm_residency_allocations_container.h index 8fe0db35af..955d03f46b 100644 --- a/shared/source/os_interface/windows/wddm_residency_allocations_container.h +++ b/shared/source/os_interface/windows/wddm_residency_allocations_container.h @@ -19,6 +19,7 @@ class Wddm; class WddmResidentAllocationsContainer { public: WddmResidentAllocationsContainer(Wddm *wddm) : wddm(wddm) {} + WddmResidentAllocationsContainer(Wddm *wddm, bool evictionAllowed) : wddm(wddm), isEvictionOnMakeResidentAllowed(evictionAllowed) {} MOCKABLE_VIRTUAL ~WddmResidentAllocationsContainer(); MemoryOperationsStatus isAllocationResident(const D3DKMT_HANDLE &handle); @@ -39,6 +40,7 @@ class WddmResidentAllocationsContainer { Wddm *wddm; std::vector resourceHandles; SpinLock resourcesLock; + const bool isEvictionOnMakeResidentAllowed{true}; }; } // namespace NEO diff --git a/shared/test/unit_test/os_interface/windows/CMakeLists.txt b/shared/test/unit_test/os_interface/windows/CMakeLists.txt index 7bcfd682c9..fda79a5192 100644 --- a/shared/test/unit_test/os_interface/windows/CMakeLists.txt +++ b/shared/test/unit_test/os_interface/windows/CMakeLists.txt @@ -52,6 +52,7 @@ if(WIN32 OR(UNIX AND NOT DISABLE_WDDM_LINUX)) ${CMAKE_CURRENT_SOURCE_DIR}/wddm_preemption_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm_shared_allocations_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm_memory_manager_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/wddm_memory_operations_handler_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm_memory_operations_handler_with_aub_dump_tests.cpp ) endif() diff --git a/shared/test/unit_test/os_interface/windows/wddm_memory_operations_handler_tests.cpp b/shared/test/unit_test/os_interface/windows/wddm_memory_operations_handler_tests.cpp new file mode 100644 index 0000000000..c3444c3a8d --- /dev/null +++ b/shared/test/unit_test/os_interface/windows/wddm_memory_operations_handler_tests.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/windows/wddm_allocation.h" +#include "shared/source/os_interface/windows/wddm_memory_operations_handler.h" +#include "shared/test/common/mocks/windows/mock_wddm_allocation.h" +#include "shared/test/common/os_interface/windows/wddm_fixture.h" + +using namespace NEO; + +struct WddmMemoryOperationsHandlerTest : public WddmTest { + void SetUp() override { + WddmTest::SetUp(); + wddmMemoryOperationsHandler = std::make_unique(wddm); + wddmAllocation = std::make_unique(rootDeviceEnvironment->getGmmHelper()); + wddmFragmentedAllocation = std::make_unique(rootDeviceEnvironment->getGmmHelper()); + wddmAllocation->handle = 0x2u; + + osHandleStorageFirst = std::make_unique(); + osHandleStorageSecond = std::make_unique(); + + wddmFragmentedAllocation->fragmentsStorage.fragmentCount = 2; + wddmFragmentedAllocation->fragmentsStorage.fragmentStorageData[0].osHandleStorage = osHandleStorageFirst.get(); + static_cast(wddmFragmentedAllocation->fragmentsStorage.fragmentStorageData[0].osHandleStorage)->handle = 0x3u; + wddmFragmentedAllocation->fragmentsStorage.fragmentStorageData[1].osHandleStorage = osHandleStorageSecond.get(); + static_cast(wddmFragmentedAllocation->fragmentsStorage.fragmentStorageData[1].osHandleStorage)->handle = 0x4u; + + allocationPtr = wddmAllocation.get(); + + allocationData.push_back(wddmAllocation.get()); + allocationData.push_back(wddmFragmentedAllocation.get()); + } + + std::unique_ptr wddmMemoryOperationsHandler; + std::unique_ptr wddmAllocation; + std::unique_ptr wddmFragmentedAllocation; + std::unique_ptr osHandleStorageFirst; + std::unique_ptr osHandleStorageSecond; + GraphicsAllocation *allocationPtr; + StackVec allocationData; +}; + +TEST_F(WddmMemoryOperationsHandlerTest, givenRegularAllocationWhenMakingResidentAllocationThenMakeResidentIsCalledAndAllocationIsMarkedAsExplicitlyResident) { + wddmAllocation->setExplicitlyMadeResident(false); + EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(&allocationPtr, 1), false, false), MemoryOperationsStatus::success); + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::success); + EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); +} + +TEST_F(WddmMemoryOperationsHandlerTest, givenFragmentedAllocationWhenMakingResidentAllocationThenMakeResidentIsCalledAndAllocationIsMarkedAsExplicitlyResident) { + allocationPtr = wddmFragmentedAllocation.get(); + allocationPtr->setExplicitlyMadeResident(false); + + EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(&allocationPtr, 1), false, false), MemoryOperationsStatus::success); + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); + EXPECT_TRUE(allocationPtr->isExplicitlyMadeResident()); +} + +TEST_F(WddmMemoryOperationsHandlerTest, givenVariousAllocationsWhenMakingResidentAllocationThenMakeResidentCalled) { + + for (auto &allocation : allocationData) { + allocation->setExplicitlyMadeResident(false); + } + + EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(allocationData), false, false), MemoryOperationsStatus::success); + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::success); + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); + + for (auto &allocation : allocationData) { + EXPECT_TRUE(allocation->isExplicitlyMadeResident()); + } +} + +TEST_F(WddmMemoryOperationsHandlerTest, givenRegularAllocationWhenEvictingResidentAllocationThenEvictCalled) { + wddm->callBaseEvict = true; + allocationPtr->setExplicitlyMadeResident(false); + + EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(&allocationPtr, 1), false, false), MemoryOperationsStatus::success); + EXPECT_TRUE(allocationPtr->isExplicitlyMadeResident()); + + EXPECT_EQ(wddmMemoryOperationsHandler->evict(nullptr, *wddmAllocation), MemoryOperationsStatus::success); + EXPECT_FALSE(allocationPtr->isExplicitlyMadeResident()); + + EXPECT_EQ(0u, gdi->getEvictArg().Flags.EvictOnlyIfNecessary); + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::memoryNotFound); +} + +TEST_F(WddmMemoryOperationsHandlerTest, givenFragmentedAllocationWhenEvictingResidentAllocationThenEvictCalled) { + allocationPtr = wddmFragmentedAllocation.get(); + allocationPtr->setExplicitlyMadeResident(false); + + EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(&allocationPtr, 1), false, false), MemoryOperationsStatus::success); + EXPECT_TRUE(allocationPtr->isExplicitlyMadeResident()); + + EXPECT_EQ(wddmMemoryOperationsHandler->evict(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); + EXPECT_FALSE(allocationPtr->isExplicitlyMadeResident()); + + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::memoryNotFound); +} + +TEST_F(WddmMemoryOperationsHandlerTest, givenVariousAllocationsWhenEvictingResidentAllocationThenEvictCalled) { + for (auto &allocation : allocationData) { + allocation->setExplicitlyMadeResident(false); + } + wddm->evictResult.called = 0; + EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(allocationData), false, false), MemoryOperationsStatus::success); + EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); + EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); + + EXPECT_EQ(wddmMemoryOperationsHandler->evict(nullptr, *wddmAllocation), MemoryOperationsStatus::success); + EXPECT_FALSE(wddmAllocation->isExplicitlyMadeResident()); + EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); + EXPECT_EQ(1u, wddm->evictResult.called); + + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::memoryNotFound); + + EXPECT_EQ(wddmMemoryOperationsHandler->evict(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); + EXPECT_FALSE(wddmAllocation->isExplicitlyMadeResident()); + EXPECT_FALSE(wddmFragmentedAllocation->isExplicitlyMadeResident()); + EXPECT_EQ(2u, wddm->evictResult.called); + + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::memoryNotFound); +} + +TEST_F(WddmMemoryOperationsHandlerTest, givenVariousAllocationsWhenFreeResidentAllocationThenAllocationIsRemovedButEvictIsNotCalled) { + for (auto &allocation : allocationData) { + allocation->setExplicitlyMadeResident(false); + } + wddm->evictResult.called = 0; + EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(allocationData), false, false), MemoryOperationsStatus::success); + EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); + EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); + + EXPECT_EQ(wddmMemoryOperationsHandler->free(nullptr, *wddmAllocation), MemoryOperationsStatus::success); + EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); + EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); + EXPECT_EQ(0u, wddm->evictResult.called); + + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmAllocation), MemoryOperationsStatus::memoryNotFound); + + EXPECT_EQ(wddmMemoryOperationsHandler->free(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::success); + EXPECT_TRUE(wddmAllocation->isExplicitlyMadeResident()); + EXPECT_TRUE(wddmFragmentedAllocation->isExplicitlyMadeResident()); + EXPECT_EQ(0u, wddm->evictResult.called); + + EXPECT_EQ(wddmMemoryOperationsHandler->isResident(nullptr, *wddmFragmentedAllocation), MemoryOperationsStatus::memoryNotFound); +} + +struct WddmMemoryOperationsHandlerProxy : public WddmMemoryOperationsHandler { + using WddmMemoryOperationsHandler::residentAllocations; +}; +struct WddmResidentAllocationsContainerProxy : public WddmResidentAllocationsContainer { + using WddmResidentAllocationsContainer::isEvictionOnMakeResidentAllowed; + using WddmResidentAllocationsContainer::resourceHandles; +}; + +TEST_F(WddmMemoryOperationsHandlerTest, givenExplicitlyResidentAllocationsWhenMakeResidentFailsThenNoEvictionIsPerformedAndOOMReturned) { + for (auto &allocation : allocationData) { + allocation->setExplicitlyMadeResident(false); + } + wddm->evictResult.called = 0U; + wddm->makeResidentStatus = false; + + auto *resAlloc{static_cast(wddmMemoryOperationsHandler.get())->residentAllocations.get()}; + auto *residentAllocations{static_cast(resAlloc)}; + residentAllocations->resourceHandles.push_back(0x42); // avoid quick-return for an empty vector + + EXPECT_EQ(wddmMemoryOperationsHandler->makeResident(nullptr, ArrayRef(allocationData), false, false), MemoryOperationsStatus::outOfMemory); + EXPECT_EQ(wddm->evictResult.called, 0U); +}