Add residency mechanism to OS interface

Change-Id: I323ca856d3c901bdc4d5961cdefa42685b53d4d9
Signed-off-by: Zbigniew Zdanowicz <zbigniew.zdanowicz@intel.com>
This commit is contained in:
Zbigniew Zdanowicz
2019-07-12 16:50:14 +02:00
committed by sys_ocldev
parent 775336df92
commit f01c1d2d49
64 changed files with 742 additions and 253 deletions

View File

@ -10,11 +10,12 @@
#include "runtime/gmm_helper/gmm_lib.h"
#include "runtime/os_interface/windows/os_time_win.h"
#include <d3d10_1.h>
#include <d3d9types.h>
#include "Windows.h"
#include "d3d10.h"
#include "umKmInc/sharedata.h"
#include <d3d10.h>
#include <d3dkmthk.h>
#define DECL_FUNCTIONS() \

View File

@ -85,6 +85,8 @@ if(WIN32)
${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_interface23.h
${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm.h
${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_residency_allocations_container.h
${CMAKE_CURRENT_SOURCE_DIR}/wddm_mock_helpers.h
${IGDRCL_SRC_tests_mock_wddm}
)
else()
@ -115,4 +117,4 @@ target_compile_definitions(igdrcl_mocks PRIVATE MOCKABLE_VIRTUAL=virtual $<TARGE
set_target_properties(igdrcl_mocks PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(igdrcl_mocks PROPERTIES FOLDER "test mocks")
create_project_source_tree(igdrcl_mocks)
create_project_source_tree(igdrcl_mocks ${IGDRCL_SOURCE_DIR})

View File

@ -11,11 +11,16 @@
#include "runtime/os_interface/windows/gdi_interface.h"
#include "runtime/os_interface/windows/wddm_allocation.h"
#include "unit_tests/mock_gdi/mock_gdi.h"
#include "unit_tests/mocks/mock_wddm_residency_allocations_container.h"
#include "gtest/gtest.h"
using namespace NEO;
WddmMock::WddmMock() : Wddm() {
this->temporaryResources = std::make_unique<MockWddmResidentAllocationsContainer>(this);
}
WddmMock::~WddmMock() {
EXPECT_EQ(0, reservedAddresses.size());
}
@ -250,33 +255,6 @@ 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(const D3DKMT_HANDLE &handle) {
evictTemporaryResourceResult.called++;
evictTemporaryResourceResult.status = Wddm::evictTemporaryResource(handle);
return evictTemporaryResourceResult.status;
}
void WddmMock::applyBlockingMakeResident(const D3DKMT_HANDLE &handle) {
applyBlockingMakeResidentResult.called++;
return Wddm::applyBlockingMakeResident(handle);
}
void WddmMock::removeTemporaryResource(const D3DKMT_HANDLE &handle) {
removeTemporaryResourceResult.called++;
return Wddm::removeTemporaryResource(handle);
}
std::unique_lock<SpinLock> WddmMock::acquireLock(SpinLock &lock) {
acquireLockResult.called++;
acquireLockResult.uint64ParamPassed = reinterpret_cast<uint64_t>(&lock);
return Wddm::acquireLock(lock);
}
D3DGPU_VIRTUAL_ADDRESS WddmMock::reserveGpuVirtualAddress(D3DGPU_VIRTUAL_ADDRESS minimumAddress, D3DGPU_VIRTUAL_ADDRESS maximumAddress, D3DGPU_SIZE_T size) {
reserveGpuVirtualAddressResult.called++;
return Wddm::reserveGpuVirtualAddress(minimumAddress, maximumAddress, size);

View File

@ -9,7 +9,9 @@
#include "runtime/memory_manager/host_ptr_defines.h"
#include "runtime/os_interface/windows/wddm/wddm.h"
#include "runtime/os_interface/windows/wddm_residency_allocations_container.h"
#include "runtime/os_interface/windows/windows_defs.h"
#include "unit_tests/mocks/wddm_mock_helpers.h"
#include "gmock/gmock.h"
@ -19,33 +21,6 @@
namespace NEO {
class GraphicsAllocation;
namespace WddmMockHelpers {
struct CallResult {
uint32_t called = 0;
uint64_t uint64ParamPassed = -1;
bool success = false;
uint64_t commandBufferSubmitted = 0u;
void *commandHeaderSubmitted = nullptr;
void *cpuPtrPassed = nullptr;
};
struct MakeResidentCall : CallResult {
std::vector<D3DKMT_HANDLE> handlePack;
uint32_t handleCount = 0;
};
struct EvictCallResult : CallResult {
EvictionStatus status = EvictionStatus::UNKNOWN;
};
struct KmDafLockCall : CallResult {
std::vector<D3DKMT_HANDLE> lockedAllocations;
};
struct WaitFromCpuResult : CallResult {
const MonitoredFence *monitoredFence = nullptr;
};
struct FreeGpuVirtualAddressCall : CallResult {
uint64_t sizePassed = -1;
};
} // namespace WddmMockHelpers
class WddmMock : public Wddm {
public:
using Wddm::adapter;
@ -59,10 +34,9 @@ class WddmMock : public Wddm {
using Wddm::pagingFenceAddress;
using Wddm::pagingQueue;
using Wddm::temporaryResources;
using Wddm::temporaryResourcesLock;
using Wddm::wddmInterface;
WddmMock() : Wddm(){};
WddmMock();
~WddmMock();
bool makeResident(const D3DKMT_HANDLE *handles, uint32_t count, bool cantTrimFurther, uint64_t *numberOfBytesToTrim) override;
@ -98,11 +72,6 @@ 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(const D3DKMT_HANDLE &handle) override;
void applyBlockingMakeResident(const D3DKMT_HANDLE &handle) override;
void removeTemporaryResource(const D3DKMT_HANDLE &handle) override;
std::unique_lock<SpinLock> acquireLock(SpinLock &lock) override;
D3DGPU_VIRTUAL_ADDRESS reserveGpuVirtualAddress(D3DGPU_VIRTUAL_ADDRESS minimumAddress, D3DGPU_VIRTUAL_ADDRESS maximumAddress, D3DGPU_SIZE_T size) override;
bool reserveValidAddressRange(size_t size, void *&reservedMem);
PLATFORM *getGfxPlatform() { return gfxPlatform.get(); }
@ -137,11 +106,6 @@ class WddmMock : public Wddm {
WddmMockHelpers::WaitFromCpuResult waitFromCpuResult;
WddmMockHelpers::CallResult releaseReservedAddressResult;
WddmMockHelpers::CallResult reserveValidAddressRangeResult;
WddmMockHelpers::EvictCallResult evictAllTemporaryResourcesResult;
WddmMockHelpers::EvictCallResult evictTemporaryResourceResult;
WddmMockHelpers::CallResult applyBlockingMakeResidentResult;
WddmMockHelpers::CallResult removeTemporaryResourceResult;
WddmMockHelpers::CallResult acquireLockResult;
WddmMockHelpers::CallResult registerTrimCallbackResult;
WddmMockHelpers::CallResult getPagingFenceAddressResult;
WddmMockHelpers::CallResult reserveGpuVirtualAddressResult;

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "runtime/os_interface/windows/wddm_residency_allocations_container.h"
#include "unit_tests/mocks/wddm_mock_helpers.h"
namespace NEO {
class Wddm;
class MockWddmResidentAllocationsContainer : public WddmResidentAllocationsContainer {
public:
using WddmResidentAllocationsContainer::resourceHandles;
using WddmResidentAllocationsContainer::resourcesLock;
MockWddmResidentAllocationsContainer(Wddm *wddm) : WddmResidentAllocationsContainer(wddm) {}
virtual ~MockWddmResidentAllocationsContainer() = default;
bool makeResidentResource(const D3DKMT_HANDLE &handle) override {
makeResidentResult.called++;
makeResidentResult.success = WddmResidentAllocationsContainer::makeResidentResource(handle);
return makeResidentResult.success;
}
EvictionStatus evictAllResources() override {
evictAllResourcesResult.called++;
evictAllResourcesResult.status = WddmResidentAllocationsContainer::evictAllResources();
return evictAllResourcesResult.status;
}
EvictionStatus evictResource(const D3DKMT_HANDLE &handle) override {
evictResourceResult.called++;
evictResourceResult.status = WddmResidentAllocationsContainer::evictResource(handle);
return evictResourceResult.status;
}
std::unique_lock<SpinLock> acquireLock(SpinLock &lock) override {
acquireLockResult.called++;
acquireLockResult.uint64ParamPassed = reinterpret_cast<uint64_t>(&lock);
return WddmResidentAllocationsContainer::acquireLock(lock);
}
void removeResource(const D3DKMT_HANDLE &handle) override {
removeResourceResult.called++;
WddmResidentAllocationsContainer::removeResource(handle);
}
WddmMockHelpers::CallResult makeResidentResult;
WddmMockHelpers::CallResult acquireLockResult;
WddmMockHelpers::CallResult removeResourceResult;
WddmMockHelpers::EvictCallResult evictAllResourcesResult;
WddmMockHelpers::EvictCallResult evictResourceResult;
};
} // namespace NEO

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "core/memory_manager/eviction_status.h"
#include "runtime/os_interface/windows/windows_defs.h"
#include <vector>
namespace NEO {
namespace WddmMockHelpers {
struct CallResult {
uint32_t called = 0;
uint64_t uint64ParamPassed = -1;
bool success = false;
uint64_t commandBufferSubmitted = 0u;
void *commandHeaderSubmitted = nullptr;
void *cpuPtrPassed = nullptr;
};
struct MakeResidentCall : CallResult {
std::vector<D3DKMT_HANDLE> handlePack;
uint32_t handleCount = 0;
};
struct EvictCallResult : CallResult {
EvictionStatus status = EvictionStatus::UNKNOWN;
};
struct KmDafLockCall : CallResult {
std::vector<D3DKMT_HANDLE> lockedAllocations;
};
struct WaitFromCpuResult : CallResult {
const MonitoredFence *monitoredFence = nullptr;
};
struct FreeGpuVirtualAddressCall : CallResult {
uint64_t sizePassed = -1;
};
} // namespace WddmMockHelpers
} // namespace NEO

View File

@ -27,6 +27,7 @@ set(IGDRCL_SRCS_tests_os_interface_linux
${CMAKE_CURRENT_SOURCE_DIR}/drm_mock.h
${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/drm_mock.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drm_neo_create.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drm_residency_handler_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drm_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hw_info_config_linux_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/hw_info_config_linux_tests.h

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "runtime/os_interface/linux/drm_residency_handler.h"
#include "test.h"
#include "unit_tests/mocks/mock_graphics_allocation.h"
#include <memory>
using namespace NEO;
struct DrmResidencyHandlerTest : public ::testing::Test {
void SetUp() {
drmResidencyHandler = std::make_unique<DrmResidencyHandler>();
}
MockGraphicsAllocation graphicsAllocation;
std::unique_ptr<DrmResidencyHandler> drmResidencyHandler;
};
TEST_F(DrmResidencyHandlerTest, whenMakingResidentAllocaionExpectMakeResidentFail) {
EXPECT_FALSE(drmResidencyHandler->makeResident(graphicsAllocation));
EXPECT_FALSE(drmResidencyHandler->isResident(graphicsAllocation));
}
TEST_F(DrmResidencyHandlerTest, whenEvictingResidentAllocationExpectEvictFalse) {
EXPECT_FALSE(drmResidencyHandler->makeResident(graphicsAllocation));
EXPECT_FALSE(drmResidencyHandler->evict(graphicsAllocation));
EXPECT_FALSE(drmResidencyHandler->isResident(graphicsAllocation));
}

View File

@ -24,4 +24,9 @@ TEST(OsInterfaceTest, GivenLinuxOsInterfaceWhenDeviceHandleQueriedthenZeroIsRetu
EXPECT_EQ(0u, osInterface.getDeviceHandle());
}
TEST(OsInterfaceTest, GivenLinuxOsInterfaceWhenResidencyInterfaceRetrievedThenCreatedObjectReturned) {
OSInterface osInterface;
EXPECT_NE(nullptr, osInterface.getResidencyInterface());
}
} // namespace NEO

View File

@ -41,6 +41,7 @@ set(IGDRCL_SRCS_tests_os_interface_windows
${CMAKE_CURRENT_SOURCE_DIR}/wddm_memory_manager_allocate_in_device_pool_tests.inl
${CMAKE_CURRENT_SOURCE_DIR}/wddm_preemption_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/wddm_residency_controller_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/wddm_residency_handler_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_registry_reader.cpp
)
if(WIN32)

View File

@ -11,6 +11,7 @@
#include "runtime/os_interface/windows/os_context_win.h"
#include "runtime/os_interface/windows/os_interface.h"
#include "runtime/os_interface/windows/wddm/wddm.h"
#include "runtime/os_interface/windows/wddm_residency_handler.h"
#include "runtime/sharings/gl/gl_arb_sync_event.h"
#include "runtime/sharings/gl/gl_sharing.h"
#include "unit_tests/mocks/gl/mock_gl_sharing.h"

View File

@ -21,7 +21,7 @@ TEST_F(OsInterfaceTest, GivenWindowsWhenCreateEentIsCalledThenValidEventHandleIs
EXPECT_EQ(TRUE, ret);
}
TEST(OsContextTest, givenWddmWhenCreateOsContextAfterInitWddmThenOsContextIsInitializedAndTrimCallbackIsRegistered) {
TEST(OsContextTest, givenWddmWhenCreateOsContextAfterInitWddmThenOsContextIsInitializedTrimCallbackIsRegisteredResidencyHandlerCreated) {
auto wddm = new WddmMock;
OSInterface osInterface;
osInterface.get()->setWddm(wddm);
@ -33,4 +33,5 @@ TEST(OsContextTest, givenWddmWhenCreateOsContextAfterInitWddmThenOsContextIsInit
EXPECT_TRUE(osContext->isInitialized());
EXPECT_EQ(osContext->getWddm(), wddm);
EXPECT_EQ(1u, wddm->registerTrimCallbackResult.called);
EXPECT_NE(nullptr, osInterface.getResidencyInterface());
}

View File

@ -757,164 +757,176 @@ TEST_F(Wddm20Tests, givenNullTrimCallbackHandleWhenUnregisteringTrimCallbackThen
using WddmLockWithMakeResidentTests = Wddm20Tests;
TEST_F(WddmLockWithMakeResidentTests, givenAllocationThatDoesntNeedMakeResidentBeforeLockWhenLockThenDontStoreItOrCallMakeResident) {
EXPECT_TRUE(wddm->temporaryResources.empty());
EXPECT_TRUE(mockTemporaryResources->resourceHandles.empty());
EXPECT_EQ(0u, wddm->makeResidentResult.called);
wddm->lockResource(ALLOCATION_HANDLE, false);
EXPECT_TRUE(wddm->temporaryResources.empty());
EXPECT_TRUE(mockTemporaryResources->resourceHandles.empty());
EXPECT_EQ(0u, wddm->makeResidentResult.called);
wddm->unlockResource(ALLOCATION_HANDLE);
}
TEST_F(WddmLockWithMakeResidentTests, givenAllocationThatNeedsMakeResidentBeforeLockWhenLockThenCallBlockingMakeResident) {
wddm->lockResource(ALLOCATION_HANDLE, true);
EXPECT_EQ(1u, wddm->applyBlockingMakeResidentResult.called);
EXPECT_EQ(1u, mockTemporaryResources->makeResidentResult.called);
}
TEST_F(WddmLockWithMakeResidentTests, givenAllocationWhenApplyBlockingMakeResidentThenAcquireUniqueLock) {
wddm->applyBlockingMakeResident(ALLOCATION_HANDLE);
EXPECT_EQ(1u, wddm->acquireLockResult.called);
EXPECT_EQ(reinterpret_cast<uint64_t>(&wddm->temporaryResourcesLock), wddm->acquireLockResult.uint64ParamPassed);
wddm->temporaryResources->makeResidentResource(ALLOCATION_HANDLE);
EXPECT_EQ(1u, mockTemporaryResources->acquireLockResult.called);
EXPECT_EQ(reinterpret_cast<uint64_t>(&mockTemporaryResources->resourcesLock), mockTemporaryResources->acquireLockResult.uint64ParamPassed);
}
TEST_F(WddmLockWithMakeResidentTests, givenAllocationWhenApplyBlockingMakeResidentThenCallMakeResidentAndStoreAllocation) {
wddm->applyBlockingMakeResident(ALLOCATION_HANDLE);
wddm->temporaryResources->makeResidentResource(ALLOCATION_HANDLE);
EXPECT_EQ(1u, wddm->makeResidentResult.called);
EXPECT_EQ(ALLOCATION_HANDLE, wddm->temporaryResources.back());
EXPECT_EQ(ALLOCATION_HANDLE, mockTemporaryResources->resourceHandles.back());
}
TEST_F(WddmLockWithMakeResidentTests, givenAllocationWhenApplyBlockingMakeResidentThenWaitForCurrentPagingFenceValue) {
wddm->mockPagingFence = 0u;
wddm->currentPagingFenceValue = 3u;
wddm->applyBlockingMakeResident(ALLOCATION_HANDLE);
wddm->temporaryResources->makeResidentResource(ALLOCATION_HANDLE);
EXPECT_EQ(1u, wddm->makeResidentResult.called);
EXPECT_EQ(3u, wddm->mockPagingFence);
EXPECT_EQ(3u, wddm->getPagingFenceAddressResult.called);
}
TEST_F(WddmLockWithMakeResidentTests, givenAllocationWhenApplyBlockingMakeResidentAndMakeResidentCallFailsThenEvictTemporaryResourcesAndRetry) {
MockWddmAllocation allocation;
allocation.handle = 0x3;
GmockWddm gmockWddm;
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
EXPECT_CALL(gmockWddm, makeResident(&allocation.handle, ::testing::_, ::testing::_, ::testing::_)).Times(2).WillRepeatedly(::testing::Return(false));
gmockWddm.applyBlockingMakeResident(allocation.handle);
EXPECT_EQ(1u, gmockWddm.evictAllTemporaryResourcesResult.called);
gmockWddm.temporaryResources->makeResidentResource(allocation.handle);
EXPECT_EQ(1u, mockTemporaryResources->evictAllResourcesResult.called);
}
TEST_F(WddmLockWithMakeResidentTests, whenApplyBlockingMakeResidentAndTemporaryResourcesAreEvictedSuccessfullyThenCallMakeResidentOneMoreTime) {
MockWddmAllocation allocation;
allocation.handle = 0x3;
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(allocation.handle);
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
mockTemporaryResources->resourceHandles.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.handle);
EXPECT_EQ(2u, gmockWddm.evictAllTemporaryResourcesResult.called);
gmockWddm.temporaryResources->makeResidentResource(allocation.handle);
EXPECT_EQ(2u, mockTemporaryResources->evictAllResourcesResult.called);
}
TEST_F(WddmLockWithMakeResidentTests, whenApplyBlockingMakeResidentAndMakeResidentStillFailsThenDontStoreTemporaryResource) {
MockWddmAllocation allocation;
allocation.handle = 0x2;
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(0x1);
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
mockTemporaryResources->resourceHandles.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.handle);
EXPECT_EQ(0u, gmockWddm.temporaryResources.size());
EXPECT_EQ(1u, mockTemporaryResources->resourceHandles.size());
gmockWddm.temporaryResources->makeResidentResource(allocation.handle);
EXPECT_EQ(0u, mockTemporaryResources->resourceHandles.size());
}
TEST_F(WddmLockWithMakeResidentTests, whenApplyBlockingMakeResidentAndMakeResidentPassesAfterEvictThenStoreTemporaryResource) {
MockWddmAllocation allocation;
allocation.handle = 0x2;
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(0x1);
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
mockTemporaryResources->resourceHandles.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.handle);
EXPECT_EQ(1u, gmockWddm.temporaryResources.size());
EXPECT_EQ(0x2, gmockWddm.temporaryResources.back());
EXPECT_EQ(1u, mockTemporaryResources->resourceHandles.size());
gmockWddm.temporaryResources->makeResidentResource(allocation.handle);
EXPECT_EQ(1u, mockTemporaryResources->resourceHandles.size());
EXPECT_EQ(0x2, mockTemporaryResources->resourceHandles.back());
}
TEST_F(WddmLockWithMakeResidentTests, whenApplyBlockingMakeResidentAndMakeResidentPassesThenStoreTemporaryResource) {
MockWddmAllocation allocation;
allocation.handle = 0x2;
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(0x1);
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
mockTemporaryResources->resourceHandles.push_back(0x1);
EXPECT_CALL(gmockWddm, makeResident(&allocation.handle, ::testing::_, ::testing::_, ::testing::_)).Times(1).WillOnce(::testing::Return(true));
gmockWddm.applyBlockingMakeResident(allocation.handle);
EXPECT_EQ(2u, gmockWddm.temporaryResources.size());
EXPECT_EQ(0x2, gmockWddm.temporaryResources.back());
gmockWddm.temporaryResources->makeResidentResource(allocation.handle);
EXPECT_EQ(2u, mockTemporaryResources->resourceHandles.size());
EXPECT_EQ(0x2, mockTemporaryResources->resourceHandles.back());
}
TEST_F(WddmLockWithMakeResidentTests, givenNoTemporaryResourcesWhenEvictingAllTemporaryResourcesThenEvictionIsNotApplied) {
wddm->evictAllTemporaryResources();
EXPECT_EQ(EvictionStatus::NOT_APPLIED, wddm->evictAllTemporaryResourcesResult.status);
wddm->getTemporaryResourcesContainer()->evictAllResources();
EXPECT_EQ(EvictionStatus::NOT_APPLIED, mockTemporaryResources->evictAllResourcesResult.status);
}
TEST_F(WddmLockWithMakeResidentTests, whenEvictingAllTemporaryResourcesThenAcquireTemporaryResourcesLock) {
wddm->evictAllTemporaryResources();
EXPECT_EQ(1u, wddm->acquireLockResult.called);
EXPECT_EQ(reinterpret_cast<uint64_t>(&wddm->temporaryResourcesLock), wddm->acquireLockResult.uint64ParamPassed);
wddm->getTemporaryResourcesContainer()->evictAllResources();
EXPECT_EQ(1u, mockTemporaryResources->acquireLockResult.called);
EXPECT_EQ(reinterpret_cast<uint64_t>(&mockTemporaryResources->resourcesLock), mockTemporaryResources->acquireLockResult.uint64ParamPassed);
}
TEST_F(WddmLockWithMakeResidentTests, whenEvictingAllTemporaryResourcesAndAllEvictionsSucceedThenReturnSuccess) {
MockWddmAllocation allocation;
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(allocation.handle);
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
mockTemporaryResources->resourceHandles.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);
gmockWddm.getTemporaryResourcesContainer()->evictAllResources();
EXPECT_EQ(1u, mockTemporaryResources->evictAllResourcesResult.called);
EXPECT_EQ(EvictionStatus::SUCCESS, mockTemporaryResources->evictAllResourcesResult.status);
}
TEST_F(WddmLockWithMakeResidentTests, givenThreeAllocationsWhenEvictingAllTemporaryResourcesThenCallEvictForEachAllocationAndCleanList) {
GmockWddm gmockWddm;
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
constexpr uint32_t numAllocations = 3u;
for (auto i = 0u; i < numAllocations; i++) {
gmockWddm.temporaryResources.push_back(i);
mockTemporaryResources->resourceHandles.push_back(i);
}
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(3).WillRepeatedly(::testing::Return(true));
gmockWddm.evictAllTemporaryResources();
EXPECT_TRUE(gmockWddm.temporaryResources.empty());
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillRepeatedly(::testing::Return(true));
gmockWddm.getTemporaryResourcesContainer()->evictAllResources();
EXPECT_TRUE(mockTemporaryResources->resourceHandles.empty());
}
TEST_F(WddmLockWithMakeResidentTests, givenThreeAllocationsWhenEvictingAllTemporaryResourcesAndOneOfThemFailsThenReturnFail) {
GmockWddm gmockWddm;
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
constexpr uint32_t numAllocations = 3u;
for (auto i = 0u; i < numAllocations; i++) {
gmockWddm.temporaryResources.push_back(i);
mockTemporaryResources->resourceHandles.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);
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillOnce(::testing::Return(false));
gmockWddm.getTemporaryResourcesContainer()->evictAllResources();
EXPECT_EQ(EvictionStatus::FAILED, mockTemporaryResources->evictAllResourcesResult.status);
}
TEST_F(WddmLockWithMakeResidentTests, givenNoTemporaryResourcesWhenEvictingTemporaryResourceThenEvictionIsNotApplied) {
wddm->evictTemporaryResource(ALLOCATION_HANDLE);
EXPECT_EQ(EvictionStatus::NOT_APPLIED, wddm->evictTemporaryResourceResult.status);
wddm->getTemporaryResourcesContainer()->evictResource(ALLOCATION_HANDLE);
EXPECT_EQ(EvictionStatus::NOT_APPLIED, mockTemporaryResources->evictResourceResult.status);
}
TEST_F(WddmLockWithMakeResidentTests, whenEvictingTemporaryResourceThenAcquireTemporaryResourcesLock) {
wddm->evictTemporaryResource(ALLOCATION_HANDLE);
EXPECT_EQ(1u, wddm->acquireLockResult.called);
EXPECT_EQ(reinterpret_cast<uint64_t>(&wddm->temporaryResourcesLock), wddm->acquireLockResult.uint64ParamPassed);
wddm->getTemporaryResourcesContainer()->evictResource(ALLOCATION_HANDLE);
EXPECT_EQ(1u, mockTemporaryResources->acquireLockResult.called);
EXPECT_EQ(reinterpret_cast<uint64_t>(&mockTemporaryResources->resourcesLock), mockTemporaryResources->acquireLockResult.uint64ParamPassed);
}
TEST_F(WddmLockWithMakeResidentTests, whenEvictingNonExistingTemporaryResourceThenEvictIsNotAppliedAndTemporaryResourcesAreRestored) {
wddm->temporaryResources.push_back(ALLOCATION_HANDLE);
EXPECT_FALSE(wddm->temporaryResources.empty());
wddm->evictTemporaryResource(ALLOCATION_HANDLE + 1);
EXPECT_FALSE(wddm->temporaryResources.empty());
EXPECT_EQ(EvictionStatus::NOT_APPLIED, wddm->evictTemporaryResourceResult.status);
mockTemporaryResources->resourceHandles.push_back(ALLOCATION_HANDLE);
EXPECT_FALSE(mockTemporaryResources->resourceHandles.empty());
wddm->getTemporaryResourcesContainer()->evictResource(ALLOCATION_HANDLE + 1);
EXPECT_FALSE(mockTemporaryResources->resourceHandles.empty());
EXPECT_EQ(EvictionStatus::NOT_APPLIED, mockTemporaryResources->evictResourceResult.status);
}
TEST_F(WddmLockWithMakeResidentTests, whenEvictingTemporaryResourceAndEvictFailsThenReturnFail) {
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(ALLOCATION_HANDLE);
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
mockTemporaryResources->resourceHandles.push_back(ALLOCATION_HANDLE);
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillOnce(::testing::Return(false));
gmockWddm.evictTemporaryResource(ALLOCATION_HANDLE);
EXPECT_TRUE(gmockWddm.temporaryResources.empty());
EXPECT_EQ(EvictionStatus::FAILED, gmockWddm.evictTemporaryResourceResult.status);
gmockWddm.getTemporaryResourcesContainer()->evictResource(ALLOCATION_HANDLE);
EXPECT_TRUE(mockTemporaryResources->resourceHandles.empty());
EXPECT_EQ(EvictionStatus::FAILED, mockTemporaryResources->evictResourceResult.status);
}
TEST_F(WddmLockWithMakeResidentTests, whenEvictingTemporaryResourceAndEvictSucceedThenReturnSuccess) {
GmockWddm gmockWddm;
gmockWddm.temporaryResources.push_back(ALLOCATION_HANDLE);
auto mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(gmockWddm.temporaryResources.get());
mockTemporaryResources->resourceHandles.push_back(ALLOCATION_HANDLE);
EXPECT_CALL(gmockWddm, evict(::testing::_, ::testing::_, ::testing::_)).Times(1).WillOnce(::testing::Return(true));
gmockWddm.evictTemporaryResource(ALLOCATION_HANDLE);
EXPECT_TRUE(gmockWddm.temporaryResources.empty());
EXPECT_EQ(EvictionStatus::SUCCESS, gmockWddm.evictTemporaryResourceResult.status);
gmockWddm.getTemporaryResourcesContainer()->evictResource(ALLOCATION_HANDLE);
EXPECT_TRUE(mockTemporaryResources->resourceHandles.empty());
EXPECT_EQ(EvictionStatus::SUCCESS, mockTemporaryResources->evictResourceResult.status);
}
TEST_F(WddmLockWithMakeResidentTests, whenEvictingTemporaryResourceThenOtherResourcesRemainOnTheList) {
wddm->temporaryResources.push_back(0x1);
wddm->temporaryResources.push_back(0x2);
wddm->temporaryResources.push_back(0x3);
mockTemporaryResources->resourceHandles.push_back(0x1);
mockTemporaryResources->resourceHandles.push_back(0x2);
mockTemporaryResources->resourceHandles.push_back(0x3);
wddm->evictTemporaryResource(0x2);
wddm->getTemporaryResourcesContainer()->evictResource(0x2);
EXPECT_EQ(2u, wddm->temporaryResources.size());
EXPECT_EQ(0x1, wddm->temporaryResources.front());
EXPECT_EQ(0x3, wddm->temporaryResources.back());
EXPECT_EQ(2u, mockTemporaryResources->resourceHandles.size());
EXPECT_EQ(0x1, mockTemporaryResources->resourceHandles.front());
EXPECT_EQ(0x3, mockTemporaryResources->resourceHandles.back());
}
TEST_F(WddmLockWithMakeResidentTests, whenAlllocationNeedsBlockingMakeResidentBeforeLockThenLockWithBlockingMakeResident) {

View File

@ -16,6 +16,7 @@
#include "runtime/platform/platform.h"
#include "test.h"
#include "unit_tests/mocks/mock_wddm.h"
#include "unit_tests/mocks/mock_wddm_residency_allocations_container.h"
#include "unit_tests/os_interface/windows/gdi_dll_fixture.h"
#include "unit_tests/os_interface/windows/mock_gdi_interface.h"
@ -23,7 +24,7 @@
namespace NEO {
struct WddmFixture : ::testing::Test {
void SetUp() {
void SetUp() override {
executionEnvironment = platformImpl->peekExecutionEnvironment();
wddm = static_cast<WddmMock *>(Wddm::createWddm());
executionEnvironment->osInterface = std::make_unique<OSInterface>();
@ -35,6 +36,7 @@ struct WddmFixture : ::testing::Test {
auto hwInfo = *platformDevices[0];
wddm->init(hwInfo);
osContext = std::make_unique<OsContextWin>(*osInterface->get()->getWddm(), 0u, 1u, HwHelper::get(platformDevices[0]->platform.eRenderCoreFamily).getGpgpuEngineInstances()[0], preemptionMode, false);
mockTemporaryResources = static_cast<MockWddmResidentAllocationsContainer *>(wddm->temporaryResources.get());
}
WddmMock *wddm = nullptr;
@ -43,6 +45,7 @@ struct WddmFixture : ::testing::Test {
ExecutionEnvironment *executionEnvironment;
MockGdi *gdi = nullptr;
MockWddmResidentAllocationsContainer *mockTemporaryResources;
};
struct WddmFixtureWithMockGdiDll : public GdiDllFixture {

View File

@ -1637,28 +1637,28 @@ TEST_F(WddmMemoryManagerSimpleTest, whenDestroyingLockedAllocationThatDoesntNeed
memoryManager->lockResource(allocation);
EXPECT_FALSE(allocation->needsMakeResidentBeforeLock);
memoryManager->freeGraphicsMemory(allocation);
EXPECT_EQ(0u, wddm->evictTemporaryResourceResult.called);
EXPECT_EQ(0u, mockTemporaryResources->evictResourceResult.called);
}
TEST_F(WddmMemoryManagerSimpleTest, whenDestroyingNotLockedAllocationThatDoesntNeedMakeResidentBeforeLockThenDontEvictAllocationFromWddmTemporaryResources) {
auto allocation = static_cast<WddmAllocation *>(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize}));
EXPECT_FALSE(allocation->isLocked());
EXPECT_FALSE(allocation->needsMakeResidentBeforeLock);
memoryManager->freeGraphicsMemory(allocation);
EXPECT_EQ(0u, wddm->evictTemporaryResourceResult.called);
EXPECT_EQ(0u, mockTemporaryResources->evictResourceResult.called);
}
TEST_F(WddmMemoryManagerSimpleTest, whenDestroyingLockedAllocationThatNeedsMakeResidentBeforeLockThenRemoveTemporaryResource) {
auto allocation = static_cast<WddmAllocation *>(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize}));
allocation->needsMakeResidentBeforeLock = true;
memoryManager->lockResource(allocation);
memoryManager->freeGraphicsMemory(allocation);
EXPECT_EQ(1u, wddm->removeTemporaryResourceResult.called);
EXPECT_EQ(1u, mockTemporaryResources->removeResourceResult.called);
}
TEST_F(WddmMemoryManagerSimpleTest, whenDestroyingNotLockedAllocationThatNeedsMakeResidentBeforeLockThenDontEvictAllocationFromWddmTemporaryResources) {
auto allocation = static_cast<WddmAllocation *>(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize}));
allocation->needsMakeResidentBeforeLock = true;
EXPECT_FALSE(allocation->isLocked());
memoryManager->freeGraphicsMemory(allocation);
EXPECT_EQ(0u, wddm->evictTemporaryResourceResult.called);
EXPECT_EQ(0u, mockTemporaryResources->evictResourceResult.called);
}
TEST_F(WddmMemoryManagerSimpleTest, whenDestroyingAllocationWithReservedGpuVirtualAddressThenReleaseTheAddress) {
auto allocation = static_cast<WddmAllocation *>(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize}));

View File

@ -13,6 +13,7 @@
#include "unit_tests/mocks/mock_context.h"
#include "unit_tests/mocks/mock_gmm.h"
#include "unit_tests/mocks/mock_gmm_page_table_mngr.h"
#include "unit_tests/mocks/mock_wddm_residency_allocations_container.h"
#include "unit_tests/os_interface/windows/mock_gdi_interface.h"
#include "unit_tests/os_interface/windows/mock_wddm_memory_manager.h"
#include "unit_tests/os_interface/windows/wddm_fixture.h"
@ -61,6 +62,7 @@ class MockWddmMemoryManagerFixture {
1, PreemptionHelper::getDefaultPreemptionMode(*platformDevices[0]), false);
osContext->incRefInternal();
mockTemporaryResources = reinterpret_cast<MockWddmResidentAllocationsContainer *>(wddm->getTemporaryResourcesContainer());
}
void TearDown() {
@ -70,6 +72,7 @@ class MockWddmMemoryManagerFixture {
ExecutionEnvironment *executionEnvironment;
std::unique_ptr<MockWddmMemoryManager> memoryManager;
WddmMock *wddm = nullptr;
MockWddmResidentAllocationsContainer *mockTemporaryResources;
OsContext *osContext = nullptr;
MockGdi *gdi = nullptr;
};

View File

@ -5,6 +5,7 @@
*
*/
#include "core/memory_manager/residency_handler.h"
#include "runtime/command_stream/preemption.h"
#include "runtime/execution_environment/execution_environment.h"
#include "runtime/helpers/hw_helper.h"

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2018-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "runtime/os_interface/windows/wddm_residency_handler.h"
#include "test.h"
#include "unit_tests/mocks/mock_allocation_properties.h"
#include "unit_tests/mocks/mock_wddm.h"
#include "unit_tests/os_interface/windows/mock_wddm_allocation.h"
#include "unit_tests/os_interface/windows/wddm_fixture.h"
using namespace NEO;
struct WddmResidencyHandlerTest : public WddmTest {
void SetUp() override {
WddmTest::SetUp();
wddmResidencyHandler = std::make_unique<WddmResidencyHandler>(wddm);
wddmAllocation.handle = 0x2;
}
std::unique_ptr<WddmResidencyHandler> wddmResidencyHandler;
MockWddmAllocation wddmAllocation;
};
TEST_F(WddmResidencyHandlerTest, whenMakingResidentAllocaionExpectMakeResidentCalled) {
EXPECT_TRUE(wddmResidencyHandler->makeResident(wddmAllocation));
EXPECT_TRUE(wddmResidencyHandler->isResident(wddmAllocation));
}
TEST_F(WddmResidencyHandlerTest, whenEvictingResidentAllocationExpectEvictCalled) {
EXPECT_TRUE(wddmResidencyHandler->makeResident(wddmAllocation));
EXPECT_TRUE(wddmResidencyHandler->evict(wddmAllocation));
EXPECT_FALSE(wddmResidencyHandler->isResident(wddmAllocation));
}

View File

@ -1,5 +1,5 @@
#
# Copyright (C) 2017-2018 Intel Corporation
# Copyright (C) 2017-2019 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@ -19,9 +19,12 @@ set(IGDRCL_SRCS_tests_utilities
${CMAKE_CURRENT_SOURCE_DIR}/numeric_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/perf_profiler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/reference_tracked_object_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/spinlock_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/tag_allocator_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/timer_util_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/vec_tests.cpp
)
get_property(NEO_CORE_UTILITIES_TESTS GLOBAL PROPERTY NEO_CORE_UTILITIES_TESTS)
list(APPEND IGDRCL_SRCS_tests_utilities ${NEO_CORE_UTILITIES_TESTS})
target_sources(igdrcl_tests PRIVATE ${IGDRCL_SRCS_tests_utilities})

View File

@ -1,68 +0,0 @@
/*
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "runtime/utilities/spinlock.h"
#include "gtest/gtest.h"
#include <mutex>
#include <thread>
using namespace NEO;
TEST(SpinLockTest, givenTwoThreadsThenVerifyThatTheySynchronizeWithSpinLock) {
std::atomic<bool> threadStarted(false);
std::atomic<bool> threadFinished(false);
SpinLock spinLock;
int sharedCount = 0;
// Initially acquire spin lock so the worker thread will wait
std::unique_lock<SpinLock> lock1{spinLock};
// Start worker thread
std::thread workerThread([&]() {
threadStarted = true;
std::unique_lock<SpinLock> lock2{spinLock};
sharedCount++;
EXPECT_EQ(2, sharedCount);
lock2.unlock();
threadFinished = true;
});
// Wait till worker thread is started
while (!threadStarted)
;
sharedCount++;
EXPECT_EQ(1, sharedCount);
// Release spin lock thus allowing worker thread to proceed
lock1.unlock();
// Wait till worker thread finishes
while (!threadFinished)
;
EXPECT_EQ(2, sharedCount);
workerThread.join();
}
TEST(SpinLockTest, givenSpinLockThenAttemptedLockingWorks) {
SpinLock spinLock;
auto workerThreadFunction = [&spinLock](bool expectedLockAcquired) {
std::unique_lock<SpinLock> lock{spinLock, std::defer_lock};
auto lockAcquired = lock.try_lock();
EXPECT_EQ(expectedLockAcquired, lockAcquired);
};
// Expect locking to fail when lock is already taken
std::unique_lock<SpinLock> lock{spinLock};
std::thread workerThread1(workerThreadFunction, false);
workerThread1.join();
lock.unlock();
std::thread workerThread2(workerThreadFunction, true);
workerThread2.join();
}