From 1a89a0103a166b4edee29cd8b4877544a4a3d7f0 Mon Sep 17 00:00:00 2001 From: Mateusz Jablonski Date: Wed, 14 Nov 2018 14:35:45 +0100 Subject: [PATCH] Register trim callback after creating monitored fence Change-Id: Ib0510a0aed180c7bfe883a60632fd642664e1085 Signed-off-by: Mateusz Jablonski --- .../os_interface/windows/os_context_win.cpp | 1 + runtime/os_interface/windows/wddm/wddm.h | 2 +- .../windows/wddm_residency_controller.cpp | 3 +++ .../windows/wddm_residency_controller.h | 2 ++ unit_tests/mocks/mock_wddm.cpp | 4 +++ unit_tests/mocks/mock_wddm.h | 2 ++ .../windows/os_interface_win_tests.cpp | 4 ++- .../wddm_residency_controller_tests.cpp | 26 +++++++++++++++++-- 8 files changed, 40 insertions(+), 4 deletions(-) diff --git a/runtime/os_interface/windows/os_context_win.cpp b/runtime/os_interface/windows/os_context_win.cpp index 8455cfbb09..422c8de4d4 100644 --- a/runtime/os_interface/windows/os_context_win.cpp +++ b/runtime/os_interface/windows/os_context_win.cpp @@ -24,6 +24,7 @@ OsContextWin::OsContextImpl(Wddm &wddm, uint32_t osContextId) : wddm(wddm), resi } } initialized = wddmInterface->createMonitoredFence(this->residencyController); + this->residencyController.registerCallback(); }; OsContextWin::~OsContextImpl() { wddm.getWddmInterface()->destroyHwQueue(hwQueueHandle); diff --git a/runtime/os_interface/windows/wddm/wddm.h b/runtime/os_interface/windows/wddm/wddm.h index 8452c2b00e..36b2b71c47 100644 --- a/runtime/os_interface/windows/wddm/wddm.h +++ b/runtime/os_interface/windows/wddm/wddm.h @@ -78,7 +78,7 @@ class Wddm { MOCKABLE_VIRTUAL bool waitFromCpu(uint64_t lastFenceValue, const MonitoredFence &monitoredFence); NTSTATUS escape(D3DKMT_ESCAPE &escapeCommand); - VOID *registerTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, WddmResidencyController &residencyController); + MOCKABLE_VIRTUAL VOID *registerTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, WddmResidencyController &residencyController); void unregisterTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, VOID *trimCallbackHandle); MOCKABLE_VIRTUAL void releaseReservedAddress(void *reservedAddress); MOCKABLE_VIRTUAL bool reserveValidAddressRange(size_t size, void *&reservedMem); diff --git a/runtime/os_interface/windows/wddm_residency_controller.cpp b/runtime/os_interface/windows/wddm_residency_controller.cpp index 0697943481..867403873d 100644 --- a/runtime/os_interface/windows/wddm_residency_controller.cpp +++ b/runtime/os_interface/windows/wddm_residency_controller.cpp @@ -16,6 +16,9 @@ namespace OCLRT { WddmResidencyController::WddmResidencyController(Wddm &wddm, uint32_t osContextId) : wddm(wddm), osContextId(osContextId) { +} + +void WddmResidencyController::registerCallback() { this->trimCallbackHandle = wddm.registerTrimCallback(WddmMemoryManager::trimCallback, *this); } diff --git a/runtime/os_interface/windows/wddm_residency_controller.h b/runtime/os_interface/windows/wddm_residency_controller.h index 09a001ff2e..15654cb4d3 100644 --- a/runtime/os_interface/windows/wddm_residency_controller.h +++ b/runtime/os_interface/windows/wddm_residency_controller.h @@ -46,6 +46,8 @@ class WddmResidencyController { MonitoredFence &getMonitoredFence() { return monitoredFence; } void resetMonitoredFenceParams(D3DKMT_HANDLE &handle, uint64_t *cpuAddress, D3DGPU_VIRTUAL_ADDRESS &gpuAddress); + void registerCallback(); + void trimResidency(D3DDDI_TRIMRESIDENCYSET_FLAGS flags, uint64_t bytes); bool trimResidencyToBudget(uint64_t bytes); diff --git a/unit_tests/mocks/mock_wddm.cpp b/unit_tests/mocks/mock_wddm.cpp index ac759f9748..9aeaa16320 100644 --- a/unit_tests/mocks/mock_wddm.cpp +++ b/unit_tests/mocks/mock_wddm.cpp @@ -220,6 +220,10 @@ bool WddmMock::reserveValidAddressRange(size_t size, void *&reservedMem) { } return ret; } +VOID *WddmMock::registerTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, WddmResidencyController &residencyController) { + registerTrimCallbackResult.called++; + return Wddm::registerTrimCallback(callback, residencyController); +} GmmMemory *WddmMock::getGmmMemory() const { return gmmMemory.get(); diff --git a/unit_tests/mocks/mock_wddm.h b/unit_tests/mocks/mock_wddm.h index 0c8afae4bf..88de9f81ff 100644 --- a/unit_tests/mocks/mock_wddm.h +++ b/unit_tests/mocks/mock_wddm.h @@ -77,6 +77,7 @@ class WddmMock : public Wddm { void *virtualAlloc(void *inPtr, size_t size, unsigned long flags, unsigned long type) override; int virtualFree(void *ptr, size_t size, unsigned long flags) override; void releaseReservedAddress(void *reservedAddress) override; + VOID *registerTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, WddmResidencyController &residencyController) override; bool reserveValidAddressRange(size_t size, void *&reservedMem); GmmMemory *getGmmMemory() const; PLATFORM *getGfxPlatform() { return gfxPlatform.get(); } @@ -110,6 +111,7 @@ class WddmMock : public Wddm { WddmMockHelpers::CallResult waitFromCpuResult; WddmMockHelpers::CallResult releaseReservedAddressResult; WddmMockHelpers::CallResult reserveValidAddressRangeResult; + WddmMockHelpers::CallResult registerTrimCallbackResult; NTSTATUS createAllocationStatus; bool mapGpuVaStatus; diff --git a/unit_tests/os_interface/windows/os_interface_win_tests.cpp b/unit_tests/os_interface/windows/os_interface_win_tests.cpp index 1bac760b19..1f90c267df 100644 --- a/unit_tests/os_interface/windows/os_interface_win_tests.cpp +++ b/unit_tests/os_interface/windows/os_interface_win_tests.cpp @@ -32,15 +32,17 @@ TEST(OsContextTest, givenWddmWhenCreateOsContextBeforeInitWddmThenOsContextIsNot EXPECT_THROW(auto osContext = std::make_unique(&osInterface, 0u), std::exception); } -TEST(OsContextTest, givenWddmWhenCreateOsContextAfterInitWddmThenOsContextIsInitialized) { +TEST(OsContextTest, givenWddmWhenCreateOsContextAfterInitWddmThenOsContextIsInitializedAndTrimCallbackIsRegistered) { auto wddm = new WddmMock; OSInterface osInterface; osInterface.get()->setWddm(wddm); wddm->init(); + EXPECT_EQ(0u, wddm->registerTrimCallbackResult.called); auto osContext = std::make_unique(&osInterface, 0u); EXPECT_NE(nullptr, osContext->get()); EXPECT_TRUE(osContext->get()->isInitialized()); EXPECT_EQ(osContext->get()->getWddm(), wddm); + EXPECT_EQ(1u, wddm->registerTrimCallbackResult.called); } TEST(OsContextTest, whenCreateOsContextWithoutOsInterfaceThenOsContextImplIsNotAvailable) { diff --git a/unit_tests/os_interface/windows/wddm_residency_controller_tests.cpp b/unit_tests/os_interface/windows/wddm_residency_controller_tests.cpp index fee51435a7..24babafd41 100644 --- a/unit_tests/os_interface/windows/wddm_residency_controller_tests.cpp +++ b/unit_tests/os_interface/windows/wddm_residency_controller_tests.cpp @@ -63,6 +63,7 @@ struct WddmResidencyControllerWithGdiTest : ::testing::Test { residencyController = std::make_unique(*wddm, osContextId); wddm->getWddmInterface()->createMonitoredFence(*residencyController); + residencyController->registerCallback(); } std::unique_ptr wddm; @@ -142,7 +143,7 @@ struct WddmResidencyControllerWithGdiAndMemoryManagerTest : ::testing::Test { WddmResidencyController *residencyController = nullptr; }; -TEST(WddmResidencyController, givenWddmResidencyControllerWhenItIsConstructedThenRegisterTrimCallback) { +TEST(WddmResidencyController, givenWddmResidencyControllerWhenItIsConstructedThenDoNotRegisterTrimCallback) { ExecutionEnvironment executionEnvironment; auto gdi = new MockGdi(); auto wddm = std::unique_ptr{static_cast(Wddm::createWddm())}; @@ -150,8 +151,29 @@ TEST(WddmResidencyController, givenWddmResidencyControllerWhenItIsConstructedThe wddm->init(); std::memset(&gdi->getRegisterTrimNotificationArg(), 0, sizeof(D3DKMT_REGISTERTRIMNOTIFICATION)); - WddmResidencyController residencyController{*wddm, 0u}; + MockWddmResidencyController residencyController{*wddm, 0u}; + EXPECT_EQ(0u, wddm->registerTrimCallbackResult.called); + EXPECT_EQ(nullptr, residencyController.trimCallbackHandle); + + EXPECT_EQ(nullptr, gdi->getRegisterTrimNotificationArg().Callback); + EXPECT_EQ(nullptr, gdi->getRegisterTrimNotificationArg().Context); + EXPECT_EQ(0u, gdi->getRegisterTrimNotificationArg().hDevice); +} + +TEST(WddmResidencyController, givenWddmResidencyControllerWhenRegisterCallbackThenCallbackIsSetUpProperly) { + ExecutionEnvironment executionEnvironment; + auto gdi = new MockGdi(); + auto wddm = std::unique_ptr{static_cast(Wddm::createWddm())}; + wddm->gdi.reset(gdi); + wddm->init(); + + std::memset(&gdi->getRegisterTrimNotificationArg(), 0, sizeof(D3DKMT_REGISTERTRIMNOTIFICATION)); + + WddmResidencyController residencyController{*wddm, 0u}; + residencyController.registerCallback(); + + EXPECT_EQ(1u, wddm->registerTrimCallbackResult.called); EXPECT_EQ(reinterpret_cast(WddmMemoryManager::trimCallback), gdi->getRegisterTrimNotificationArg().Callback); EXPECT_EQ(reinterpret_cast(&residencyController), gdi->getRegisterTrimNotificationArg().Context); EXPECT_EQ(wddm->getDevice(), gdi->getRegisterTrimNotificationArg().hDevice);