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:
parent
72f17d6435
commit
ad3bfd84cb
|
@ -637,6 +637,11 @@ bool Wddm::openNTHandle(HANDLE handle, WddmAllocation *alloc) {
|
|||
}
|
||||
|
||||
void *Wddm::lockResource(WddmAllocation *wddmAllocation) {
|
||||
|
||||
if (wddmAllocation->needsMakeResidentBeforeLock) {
|
||||
applyBlockingMakeResident(wddmAllocation);
|
||||
}
|
||||
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||||
D3DKMT_LOCK2 lock2 = {};
|
||||
|
||||
|
@ -947,4 +952,60 @@ bool Wddm::init(PreemptionMode preemptionMode) {
|
|||
}
|
||||
return initialized;
|
||||
}
|
||||
|
||||
EvictionStatus Wddm::evictAllTemporaryResources() {
|
||||
decltype(temporaryResources) resourcesToEvict;
|
||||
auto &lock = acquireLock(temporaryResourcesLock);
|
||||
temporaryResources.swap(resourcesToEvict);
|
||||
if (resourcesToEvict.empty()) {
|
||||
return EvictionStatus::NOT_APPLIED;
|
||||
}
|
||||
uint64_t sizeToTrim = 0;
|
||||
bool error = false;
|
||||
for (auto &handle : resourcesToEvict) {
|
||||
if (!evict(&handle, 1, sizeToTrim)) {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
return error ? EvictionStatus::FAILED : EvictionStatus::SUCCESS;
|
||||
}
|
||||
|
||||
EvictionStatus Wddm::evictTemporaryResource(WddmAllocation *allocation) {
|
||||
auto &lock = acquireLock(temporaryResourcesLock);
|
||||
auto position = std::find(temporaryResources.begin(), temporaryResources.end(), allocation->handle);
|
||||
if (position == temporaryResources.end()) {
|
||||
return EvictionStatus::NOT_APPLIED;
|
||||
}
|
||||
*position = temporaryResources.back();
|
||||
temporaryResources.pop_back();
|
||||
uint64_t sizeToTrim = 0;
|
||||
if (!evict(&allocation->handle, 1, sizeToTrim)) {
|
||||
return EvictionStatus::FAILED;
|
||||
}
|
||||
return EvictionStatus::SUCCESS;
|
||||
}
|
||||
void Wddm::applyBlockingMakeResident(WddmAllocation *allocation) {
|
||||
bool madeResident = false;
|
||||
while (!(madeResident = makeResident(&allocation->handle, 1, false, nullptr))) {
|
||||
if (evictAllTemporaryResources() == EvictionStatus::SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
if (!makeResident(&allocation->handle, 1, false, nullptr)) {
|
||||
DEBUG_BREAK_IF(true);
|
||||
return;
|
||||
};
|
||||
break;
|
||||
}
|
||||
DEBUG_BREAK_IF(!madeResident);
|
||||
auto &lock = acquireLock(temporaryResourcesLock);
|
||||
temporaryResources.push_back(allocation->handle);
|
||||
lock.unlock();
|
||||
while (currentPagingFenceValue > *getPagingFenceAddress())
|
||||
;
|
||||
}
|
||||
|
||||
std::unique_lock<SpinLock> Wddm::acquireLock(SpinLock &lock) {
|
||||
return std::unique_lock<SpinLock>{lock};
|
||||
}
|
||||
|
||||
} // namespace OCLRT
|
||||
|
|
|
@ -19,9 +19,11 @@
|
|||
#include "runtime/utilities/debug_settings_reader.h"
|
||||
#include "runtime/gmm_helper/gmm_lib.h"
|
||||
#include "runtime/helpers/hw_info.h"
|
||||
#include "runtime/utilities/spinlock.h"
|
||||
#include "gmm_memory.h"
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
|
||||
namespace OCLRT {
|
||||
|
||||
|
@ -40,6 +42,13 @@ enum class WddmInterfaceVersion {
|
|||
Wddm23 = 23,
|
||||
};
|
||||
|
||||
enum class EvictionStatus {
|
||||
SUCCESS,
|
||||
FAILED,
|
||||
NOT_APPLIED,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
class Wddm {
|
||||
public:
|
||||
typedef HRESULT(WINAPI *CreateDXGIFactoryFcn)(REFIID riid, void **ppFactory);
|
||||
|
@ -142,6 +151,10 @@ class Wddm {
|
|||
MOCKABLE_VIRTUAL uint64_t *getPagingFenceAddress() {
|
||||
return pagingFenceAddress;
|
||||
}
|
||||
MOCKABLE_VIRTUAL EvictionStatus evictAllTemporaryResources();
|
||||
MOCKABLE_VIRTUAL EvictionStatus evictTemporaryResource(WddmAllocation *allocation);
|
||||
MOCKABLE_VIRTUAL void applyBlockingMakeResident(WddmAllocation *allocation);
|
||||
MOCKABLE_VIRTUAL std::unique_lock<SpinLock> acquireLock(SpinLock &lock);
|
||||
|
||||
protected:
|
||||
bool initialized = false;
|
||||
|
@ -192,5 +205,7 @@ class Wddm {
|
|||
|
||||
std::unique_ptr<KmDafListener> kmDafListener;
|
||||
std::unique_ptr<WddmInterface> wddmInterface;
|
||||
std::vector<D3DKMT_HANDLE> temporaryResources;
|
||||
SpinLock temporaryResourcesLock;
|
||||
};
|
||||
} // namespace OCLRT
|
||||
|
|
|
@ -80,6 +80,7 @@ class WddmAllocation : public GraphicsAllocation {
|
|||
this->reservedAddressSpace = reserveMem;
|
||||
}
|
||||
void setGpuAddress(uint64_t graphicsAddress) { this->gpuAddress = graphicsAddress; }
|
||||
bool needsMakeResidentBeforeLock = false;
|
||||
|
||||
std::string getAllocationInfoString() const {
|
||||
std::stringstream ss;
|
||||
|
|
|
@ -301,6 +301,11 @@ void WddmMemoryManager::freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation
|
|||
return;
|
||||
}
|
||||
|
||||
if (input->isLocked() && input->needsMakeResidentBeforeLock) {
|
||||
auto evictionStatus = wddm->evictTemporaryResource(input);
|
||||
DEBUG_BREAK_IF(evictionStatus == EvictionStatus::FAILED);
|
||||
}
|
||||
|
||||
for (auto &osContext : this->registeredOsContexts) {
|
||||
if (osContext) {
|
||||
auto &residencyController = osContext->get()->getResidencyController();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2018 Intel Corporation
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
|
@ -346,6 +346,11 @@ bool WddmResidencyController::makeResidentResidencyAllocations(ResidencyContaine
|
|||
this->setMemoryBudgetExhausted();
|
||||
const bool trimmingDone = this->trimResidencyToBudget(bytesToTrim);
|
||||
if (!trimmingDone) {
|
||||
auto evictionStatus = wddm.evictAllTemporaryResources();
|
||||
if (evictionStatus == EvictionStatus::SUCCESS) {
|
||||
continue;
|
||||
}
|
||||
DEBUG_BREAK_IF(evictionStatus != EvictionStatus::NOT_APPLIED);
|
||||
result = wddm.makeResident(handlesForResidency.get(), totalHandlesCount, true, &bytesToTrim);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -225,6 +225,29 @@ VOID *WddmMock::registerTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback
|
|||
return Wddm::registerTrimCallback(callback, residencyController);
|
||||
}
|
||||
|
||||
EvictionStatus WddmMock::evictAllTemporaryResources() {
|
||||
evictAllTemporaryResourcesResult.called++;
|
||||
evictAllTemporaryResourcesResult.status = Wddm::evictAllTemporaryResources();
|
||||
return evictAllTemporaryResourcesResult.status;
|
||||
}
|
||||
|
||||
EvictionStatus WddmMock::evictTemporaryResource(WddmAllocation *allocation) {
|
||||
evictTemporaryResourceResult.called++;
|
||||
evictTemporaryResourceResult.status = Wddm::evictTemporaryResource(allocation);
|
||||
return evictTemporaryResourceResult.status;
|
||||
}
|
||||
|
||||
void WddmMock::applyBlockingMakeResident(WddmAllocation *allocation) {
|
||||
applyBlockingMakeResidentResult.called++;
|
||||
return Wddm::applyBlockingMakeResident(allocation);
|
||||
}
|
||||
|
||||
std::unique_lock<SpinLock> WddmMock::acquireLock(SpinLock &lock) {
|
||||
acquireLockResult.called++;
|
||||
acquireLockResult.uint64ParamPassed = reinterpret_cast<uint64_t>(&lock);
|
||||
return Wddm::acquireLock(lock);
|
||||
}
|
||||
|
||||
GmmMemory *WddmMock::getGmmMemory() const {
|
||||
return gmmMemory.get();
|
||||
}
|
||||
|
@ -234,3 +257,11 @@ uint64_t *WddmMock::getPagingFenceAddress() {
|
|||
mockPagingFence++;
|
||||
return &mockPagingFence;
|
||||
}
|
||||
|
||||
void *GmockWddm::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;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "runtime/os_interface/windows/wddm/wddm.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
|
@ -27,6 +28,9 @@ struct MakeResidentCall : public CallResult {
|
|||
std::vector<D3DKMT_HANDLE> handlePack;
|
||||
uint32_t handleCount = 0;
|
||||
};
|
||||
struct EvictCallResult : public CallResult {
|
||||
EvictionStatus status = EvictionStatus::UNKNOWN;
|
||||
};
|
||||
struct KmDafLockCall : public CallResult {
|
||||
std::vector<GraphicsAllocation *> lockedAllocations;
|
||||
};
|
||||
|
@ -43,6 +47,8 @@ class WddmMock : public Wddm {
|
|||
using Wddm::gmmMemory;
|
||||
using Wddm::pagingFenceAddress;
|
||||
using Wddm::pagingQueue;
|
||||
using Wddm::temporaryResources;
|
||||
using Wddm::temporaryResourcesLock;
|
||||
using Wddm::wddmInterface;
|
||||
|
||||
WddmMock() : Wddm(){};
|
||||
|
@ -77,6 +83,10 @@ class WddmMock : public Wddm {
|
|||
int virtualFree(void *ptr, size_t size, unsigned long flags) override;
|
||||
void releaseReservedAddress(void *reservedAddress) override;
|
||||
VOID *registerTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, WddmResidencyController &residencyController) override;
|
||||
EvictionStatus evictAllTemporaryResources() override;
|
||||
EvictionStatus evictTemporaryResource(WddmAllocation *allocation) override;
|
||||
void applyBlockingMakeResident(WddmAllocation *allocation) override;
|
||||
std::unique_lock<SpinLock> acquireLock(SpinLock &lock) override;
|
||||
bool reserveValidAddressRange(size_t size, void *&reservedMem);
|
||||
GmmMemory *getGmmMemory() const;
|
||||
PLATFORM *getGfxPlatform() { return gfxPlatform.get(); }
|
||||
|
@ -111,6 +121,10 @@ class WddmMock : public Wddm {
|
|||
WddmMockHelpers::CallResult waitFromCpuResult;
|
||||
WddmMockHelpers::CallResult releaseReservedAddressResult;
|
||||
WddmMockHelpers::CallResult reserveValidAddressRangeResult;
|
||||
WddmMockHelpers::EvictCallResult evictAllTemporaryResourcesResult;
|
||||
WddmMockHelpers::EvictCallResult evictTemporaryResourceResult;
|
||||
WddmMockHelpers::CallResult applyBlockingMakeResidentResult;
|
||||
WddmMockHelpers::CallResult acquireLockResult;
|
||||
WddmMockHelpers::CallResult registerTrimCallbackResult;
|
||||
WddmMockHelpers::CallResult getPagingFenceAddressResult;
|
||||
|
||||
|
@ -122,6 +136,26 @@ class WddmMock : public Wddm {
|
|||
std::set<void *> reservedAddresses;
|
||||
uintptr_t virtualAllocAddress = OCLRT::windowsMinAddress;
|
||||
bool kmDafEnabled = false;
|
||||
uint64_t mockPagingFence;
|
||||
uint64_t mockPagingFence = 0u;
|
||||
};
|
||||
|
||||
struct GmockWddm : WddmMock {
|
||||
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);
|
||||
uintptr_t virtualAllocAddress;
|
||||
MOCK_METHOD4(makeResident, bool(D3DKMT_HANDLE *handles, uint32_t count, bool cantTrimFurther, uint64_t *numberOfBytesToTrim));
|
||||
MOCK_METHOD3(evict, bool(D3DKMT_HANDLE *handles, uint32_t num, uint64_t &sizeToTrim));
|
||||
MOCK_METHOD1(createAllocationsAndMapGpuVa, NTSTATUS(OsHandleStorage &osHandles));
|
||||
|
||||
NTSTATUS baseCreateAllocationAndMapGpuVa(OsHandleStorage &osHandles) {
|
||||
return Wddm::createAllocationsAndMapGpuVa(osHandles);
|
||||
}
|
||||
};
|
||||
} // namespace OCLRT
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue