Add functionality to make resident before locking resource

Change-Id: I0963c1edcb43f409e9dd62cb46a0da1f2b05667b
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski
2019-01-16 15:09:33 +01:00
committed by sys_ocldev
parent 72f17d6435
commit ad3bfd84cb
11 changed files with 357 additions and 36 deletions

View File

@@ -819,3 +819,177 @@ TEST_F(Wddm20Tests, givenNullTrimCallbackHandleWhenUnregisteringTrimCallbackThen
EXPECT_EQ(callbackBefore, gdi->getUnregisterTrimNotificationArg().Callback);
EXPECT_EQ(trimCallbackHandleBefore, gdi->getUnregisterTrimNotificationArg().Handle);
}
TEST_F(Wddm20Tests, givenAllocationThatDoesntNeedMakeResidentBeforeLockWhenLockThenDontStoreItOrCallMakeResident) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
EXPECT_FALSE(allocation.needsMakeResidentBeforeLock);
EXPECT_TRUE(wddm->temporaryResources.empty());
EXPECT_EQ(0u, wddm->makeResidentResult.called);
wddm->lockResource(&allocation);
EXPECT_TRUE(wddm->temporaryResources.empty());
EXPECT_EQ(0u, wddm->makeResidentResult.called);
wddm->unlockResource(&allocation);
}
TEST_F(Wddm20Tests, givenAllocationThatNeedsMakeResidentBeforeLockWhenLockThenCallBlockingMakeResident) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
allocation.needsMakeResidentBeforeLock = true;
wddm->lockResource(&allocation);
EXPECT_EQ(1u, wddm->applyBlockingMakeResidentResult.called);
}
TEST_F(Wddm20Tests, givenAllocationWhenApplyBlockingMakeResidentThenAcquireUniqueLock) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
wddm->applyBlockingMakeResident(&allocation);
EXPECT_EQ(1u, wddm->acquireLockResult.called);
EXPECT_EQ(reinterpret_cast<uint64_t>(&wddm->temporaryResourcesLock), wddm->acquireLockResult.uint64ParamPassed);
}
TEST_F(Wddm20Tests, givenAllocationWhenApplyBlockingMakeResidentThenCallMakeResidentAndStoreAllocation) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
wddm->applyBlockingMakeResident(&allocation);
EXPECT_EQ(1u, wddm->makeResidentResult.called);
EXPECT_EQ(allocation.handle, wddm->temporaryResources.back());
}
TEST_F(Wddm20Tests, givenAllocationWhenApplyBlockingMakeResidentThenWaitForCurrentPagingFenceValue) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
wddm->mockPagingFence = 0u;
wddm->currentPagingFenceValue = 3u;
wddm->applyBlockingMakeResident(&allocation);
EXPECT_EQ(1u, wddm->makeResidentResult.called);
EXPECT_EQ(3u, wddm->mockPagingFence);
EXPECT_EQ(3u, wddm->getPagingFenceAddressResult.called);
}
TEST_F(Wddm20Tests, givenAllocationWhenApplyBlockingMakeResidentAndMakeResidentCallFailsThenEvictTemporaryResourcesAndRetry) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
GmockWddm gmockWddm;
EXPECT_CALL(gmockWddm, makeResident(&allocation.handle, ::testing::_, ::testing::_, ::testing::_)).Times(2).WillRepeatedly(::testing::Return(false));
gmockWddm.applyBlockingMakeResident(&allocation);
EXPECT_EQ(1u, gmockWddm.evictAllTemporaryResourcesResult.called);
}
TEST_F(Wddm20Tests, whenApplyBlockingMakeResidentAndTemporaryResourcesAreEvictedSuccessfullyThenCallMakeResidentOneMoreTime) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(allocation.handle);
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillRepeatedly(::testing::Return(true));
EXPECT_CALL(gmockWddm, makeResident(&allocation.handle, ::testing::_, ::testing::_, ::testing::_)).Times(3).WillRepeatedly(::testing::Return(false));
gmockWddm.applyBlockingMakeResident(&allocation);
EXPECT_EQ(2u, gmockWddm.evictAllTemporaryResourcesResult.called);
}
TEST_F(Wddm20Tests, whenApplyBlockingMakeResidentAndMakeResidentStillFailsThenDontStoreTemporaryResource) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
allocation.handle = 0x2;
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(0x1);
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillRepeatedly(::testing::Return(true));
EXPECT_CALL(gmockWddm, makeResident(&allocation.handle, ::testing::_, ::testing::_, ::testing::_)).Times(3).WillRepeatedly(::testing::Return(false));
EXPECT_EQ(1u, gmockWddm.temporaryResources.size());
gmockWddm.applyBlockingMakeResident(&allocation);
EXPECT_EQ(0u, gmockWddm.temporaryResources.size());
}
TEST_F(Wddm20Tests, whenApplyBlockingMakeResidentAndMakeResidentPassesAfterEvictThenStoreTemporaryResource) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
allocation.handle = 0x2;
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(0x1);
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillRepeatedly(::testing::Return(true));
EXPECT_CALL(gmockWddm, makeResident(&allocation.handle, ::testing::_, ::testing::_, ::testing::_)).Times(2).WillOnce(::testing::Return(false)).WillOnce(::testing::Return(true));
EXPECT_EQ(1u, gmockWddm.temporaryResources.size());
gmockWddm.applyBlockingMakeResident(&allocation);
EXPECT_EQ(1u, gmockWddm.temporaryResources.size());
EXPECT_EQ(0x2, gmockWddm.temporaryResources.back());
}
TEST_F(Wddm20Tests, whenApplyBlockingMakeResidentAndMakeResidentPassesThenStoreTemporaryResource) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
allocation.handle = 0x2;
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(0x1);
EXPECT_CALL(gmockWddm, makeResident(&allocation.handle, ::testing::_, ::testing::_, ::testing::_)).Times(1).WillOnce(::testing::Return(true));
gmockWddm.applyBlockingMakeResident(&allocation);
EXPECT_EQ(2u, gmockWddm.temporaryResources.size());
EXPECT_EQ(0x2, gmockWddm.temporaryResources.back());
}
TEST_F(Wddm20Tests, givenNoTemporaryResourcesWhenEvictingAllTemporaryResourcesThenEvictionIsNotApplied) {
wddm->evictAllTemporaryResources();
EXPECT_EQ(EvictionStatus::NOT_APPLIED, wddm->evictAllTemporaryResourcesResult.status);
}
TEST_F(Wddm20Tests, whenEvictingAllTemporaryResourcesThenAcquireTemporaryResourcesLock) {
wddm->evictAllTemporaryResources();
EXPECT_EQ(1u, wddm->acquireLockResult.called);
EXPECT_EQ(reinterpret_cast<uint64_t>(&wddm->temporaryResourcesLock), wddm->acquireLockResult.uint64ParamPassed);
}
TEST_F(Wddm20Tests, whenEvictingAllTemporaryResourcesAndAllEvictionsSucceedThenReturnSuccess) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(allocation.handle);
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillOnce(::testing::Return(true));
gmockWddm.evictAllTemporaryResources();
EXPECT_EQ(1u, gmockWddm.evictAllTemporaryResourcesResult.called);
EXPECT_EQ(EvictionStatus::SUCCESS, gmockWddm.evictAllTemporaryResourcesResult.status);
}
TEST_F(Wddm20Tests, givenThreeAllocationsWhenEvictingAllTemporaryResourcesThenCallEvictForEachAllocationAndCleanList) {
GmockWddm gmockWddm;
constexpr uint32_t numAllocations = 3u;
for (auto i = 0u; i < numAllocations; i++) {
gmockWddm.temporaryResources.push_back(i);
}
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(3).WillRepeatedly(::testing::Return(true));
gmockWddm.evictAllTemporaryResources();
EXPECT_TRUE(gmockWddm.temporaryResources.empty());
}
TEST_F(Wddm20Tests, givenThreeAllocationsWhenEvictingAllTemporaryResourcesAndOneOfThemFailsThenReturnFail) {
GmockWddm gmockWddm;
constexpr uint32_t numAllocations = 3u;
for (auto i = 0u; i < numAllocations; i++) {
gmockWddm.temporaryResources.push_back(i);
}
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(3).WillOnce(::testing::Return(false)).WillRepeatedly(::testing::Return(true));
gmockWddm.evictAllTemporaryResources();
EXPECT_EQ(EvictionStatus::FAILED, gmockWddm.evictAllTemporaryResourcesResult.status);
}
TEST_F(Wddm20Tests, givenNoTemporaryResourcesWhenEvictingTemporaryResourceThenEvictionIsNotApplied) {
wddm->evictTemporaryResource(nullptr);
EXPECT_EQ(EvictionStatus::NOT_APPLIED, wddm->evictTemporaryResourceResult.status);
}
TEST_F(Wddm20Tests, whenEvictingTemporaryResourceThenAcquireTemporaryResourcesLock) {
wddm->evictTemporaryResource(nullptr);
EXPECT_EQ(1u, wddm->acquireLockResult.called);
EXPECT_EQ(reinterpret_cast<uint64_t>(&wddm->temporaryResourcesLock), wddm->acquireLockResult.uint64ParamPassed);
}
TEST_F(Wddm20Tests, whenEvictingNonExistingTemporaryResourceThenEvictIsNotAppliedAndTemporaryResourcesAreRestored) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
allocation.handle = 0x1;
wddm->temporaryResources.push_back(0x2);
EXPECT_FALSE(wddm->temporaryResources.empty());
wddm->evictTemporaryResource(&allocation);
EXPECT_FALSE(wddm->temporaryResources.empty());
EXPECT_EQ(EvictionStatus::NOT_APPLIED, wddm->evictTemporaryResourceResult.status);
}
TEST_F(Wddm20Tests, whenEvictingTemporaryResourceAndEvictFailsThenReturnFail) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(allocation.handle);
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillOnce(::testing::Return(false));
gmockWddm.evictTemporaryResource(&allocation);
EXPECT_TRUE(gmockWddm.temporaryResources.empty());
EXPECT_EQ(EvictionStatus::FAILED, gmockWddm.evictTemporaryResourceResult.status);
}
TEST_F(Wddm20Tests, whenEvictingTemporaryResourceAndEvictSucceedThenReturnSuccess) {
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(allocation.handle);
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillOnce(::testing::Return(true));
gmockWddm.evictTemporaryResource(&allocation);
EXPECT_TRUE(gmockWddm.temporaryResources.empty());
EXPECT_EQ(EvictionStatus::SUCCESS, gmockWddm.evictTemporaryResourceResult.status);
}
TEST_F(Wddm20Tests, whenEvictingTemporaryResourceThenOtherResourcesRemainOnTheList) {
wddm->temporaryResources.push_back(0x1);
wddm->temporaryResources.push_back(0x2);
wddm->temporaryResources.push_back(0x3);
WddmAllocation allocation{nullptr, 0, nullptr, MemoryPool::MemoryNull, 1u, false};
allocation.handle = 0x2;
wddm->evictTemporaryResource(&allocation);
EXPECT_EQ(2u, wddm->temporaryResources.size());
EXPECT_EQ(0x1, wddm->temporaryResources.front());
EXPECT_EQ(0x3, wddm->temporaryResources.back());
}

View File

@@ -1516,4 +1516,33 @@ TEST_F(MockWddmMemoryManagerTest, givenWddmAllocationWhenEnableMakeResidentOnMap
ASSERT_TRUE(result);
EXPECT_EQ(5u, wddm.getPagingFenceAddressResult.called);
}
TEST_F(WddmMemoryManagerSimpleTest, whenDestroyingLockedAllocationThatDoesntNeedMakeResidentBeforeLockThenDontEvictAllocationFromWddmTemporaryResources) {
auto allocation = static_cast<WddmAllocation *>(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize}));
allocation->setLocked(true);
EXPECT_FALSE(allocation->needsMakeResidentBeforeLock);
memoryManager->freeGraphicsMemory(allocation);
EXPECT_EQ(0u, wddm->evictTemporaryResourceResult.called);
}
TEST_F(WddmMemoryManagerSimpleTest, whenDestroyingNotLockedAllocationThatDoesntNeedMakeResidentBeforeLockThenDontEvictAllocationFromWddmTemporaryResources) {
auto allocation = static_cast<WddmAllocation *>(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize}));
allocation->setLocked(false);
EXPECT_FALSE(allocation->needsMakeResidentBeforeLock);
memoryManager->freeGraphicsMemory(allocation);
EXPECT_EQ(0u, wddm->evictTemporaryResourceResult.called);
}
TEST_F(WddmMemoryManagerSimpleTest, whenDestroyingLockedAllocationThatNeedsMakeResidentBeforeLockThenEvictAllocationFromWddmTemporaryResources) {
auto allocation = static_cast<WddmAllocation *>(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize}));
allocation->needsMakeResidentBeforeLock = true;
allocation->setLocked(true);
memoryManager->freeGraphicsMemory(allocation);
EXPECT_EQ(1u, wddm->evictTemporaryResourceResult.called);
}
TEST_F(WddmMemoryManagerSimpleTest, whenDestroyingNotLockedAllocationThatNeedsMakeResidentBeforeLockThenDontEvictAllocationFromWddmTemporaryResources) {
auto allocation = static_cast<WddmAllocation *>(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize}));
allocation->needsMakeResidentBeforeLock = true;
allocation->setLocked(false);
memoryManager->freeGraphicsMemory(allocation);
EXPECT_EQ(0u, wddm->evictTemporaryResourceResult.called);
}

View File

@@ -75,35 +75,6 @@ class MockWddmMemoryManagerFixture : public GmmEnvironmentFixture {
typedef ::Test<MockWddmMemoryManagerFixture> WddmMemoryManagerResidencyTest;
class GmockWddm : public Wddm {
public:
using Wddm::device;
GmockWddm() {
virtualAllocAddress = OCLRT::windowsMinAddress;
}
~GmockWddm() = default;
bool virtualFreeWrapper(void *ptr, size_t size, uint32_t flags) {
return true;
}
void *virtualAllocWrapper(void *inPtr, size_t size, uint32_t flags, uint32_t type) {
void *tmp = reinterpret_cast<void *>(virtualAllocAddress);
size += MemoryConstants::pageSize;
size -= size % MemoryConstants::pageSize;
virtualAllocAddress += size;
return tmp;
}
uintptr_t virtualAllocAddress;
MOCK_METHOD4(makeResident, bool(D3DKMT_HANDLE *handles, uint32_t count, bool cantTrimFurther, uint64_t *numberOfBytesToTrim));
MOCK_METHOD1(createAllocationsAndMapGpuVa, NTSTATUS(OsHandleStorage &osHandles));
NTSTATUS baseCreateAllocationAndMapGpuVa(OsHandleStorage &osHandles) {
return Wddm::createAllocationsAndMapGpuVa(osHandles);
}
};
class WddmMemoryManagerFixtureWithGmockWddm : public GmmEnvironmentFixture {
public:
MockWddmMemoryManager *memoryManager = nullptr;

View File

@@ -76,11 +76,6 @@ struct WddmResidencyControllerWithGdiTest : ::testing::Test {
};
struct WddmResidencyControllerWithMockWddmTest : public WddmResidencyControllerTest {
struct GmockWddm : Wddm {
using Wddm::gdi;
MOCK_METHOD4(makeResident, bool(D3DKMT_HANDLE *handles, uint32_t count, bool cantTrimFurther, uint64_t *numberOfBytesToTrim));
};
void SetUp() {
executionEnvironment = std::make_unique<ExecutionEnvironment>();
executionEnvironment->initGmm(*platformDevices);