diff --git a/runtime/os_interface/windows/os_context_win.cpp b/runtime/os_interface/windows/os_context_win.cpp index d7696c16da..0bdb7364d1 100644 --- a/runtime/os_interface/windows/os_context_win.cpp +++ b/runtime/os_interface/windows/os_context_win.cpp @@ -40,6 +40,7 @@ OsContextWin::OsContextWin(Wddm &wddm, uint32_t contextId, DeviceBitfield device OsContextWin::~OsContextWin() { wddm.getWddmInterface()->destroyHwQueue(hardwareQueue.handle); + wddm.getWddmInterface()->destroyMonitorFence(residencyController.getMonitoredFence().fenceHandle); wddm.destroyContext(wddmContextHandle); } diff --git a/runtime/os_interface/windows/wddm/wddm_interface.cpp b/runtime/os_interface/windows/wddm/wddm_interface.cpp index 362407b6ca..d9c0042b2d 100644 --- a/runtime/os_interface/windows/wddm/wddm_interface.cpp +++ b/runtime/os_interface/windows/wddm/wddm_interface.cpp @@ -28,7 +28,6 @@ bool WddmInterface20::createMonitoredFence(OsContextWin &osContext) { CreateSynchronizationObject.Info.MonitoredFence.InitialFenceValue = 0; Status = wddm.getGdi()->createSynchronizationObject2(&CreateSynchronizationObject); - DEBUG_BREAK_IF(STATUS_SUCCESS != Status); residencyController.resetMonitoredFenceParams(CreateSynchronizationObject.hSyncObject, @@ -38,6 +37,14 @@ bool WddmInterface20::createMonitoredFence(OsContextWin &osContext) { return Status == STATUS_SUCCESS; } +void WddmInterface20::destroyMonitorFence(D3DKMT_HANDLE fenceHandle) { + NTSTATUS status = STATUS_SUCCESS; + D3DKMT_DESTROYSYNCHRONIZATIONOBJECT destroySyncObject = {0}; + destroySyncObject.hSyncObject = fenceHandle; + status = wddm.getGdi()->destroySynchronizationObject(&destroySyncObject); + DEBUG_BREAK_IF(STATUS_SUCCESS != status); +} + const bool WddmInterface20::hwQueuesSupported() { return false; } @@ -96,6 +103,9 @@ bool WddmInterface23::createMonitoredFence(OsContextWin &osContext) { return true; } +void WddmInterface23::destroyMonitorFence(D3DKMT_HANDLE fenceHandle) { +} + void WddmInterface23::destroyHwQueue(D3DKMT_HANDLE hwQueue) { if (hwQueue) { D3DKMT_DESTROYHWQUEUE destroyHwQueue = {}; diff --git a/runtime/os_interface/windows/wddm/wddm_interface.h b/runtime/os_interface/windows/wddm/wddm_interface.h index ab74c1277d..36a4414654 100644 --- a/runtime/os_interface/windows/wddm/wddm_interface.h +++ b/runtime/os_interface/windows/wddm/wddm_interface.h @@ -28,6 +28,7 @@ class WddmInterface { virtual bool createHwQueue(OsContextWin &osContext) = 0; virtual void destroyHwQueue(D3DKMT_HANDLE hwQueue) = 0; virtual bool createMonitoredFence(OsContextWin &osContext) = 0; + virtual void destroyMonitorFence(D3DKMT_HANDLE fenceHandle) = 0; virtual const bool hwQueuesSupported() = 0; virtual bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, OsContextWin &osContext) = 0; Wddm &wddm; @@ -39,6 +40,7 @@ class WddmInterface20 : public WddmInterface { bool createHwQueue(OsContextWin &osContext) override; void destroyHwQueue(D3DKMT_HANDLE hwQueue) override; bool createMonitoredFence(OsContextWin &osContext) override; + void destroyMonitorFence(D3DKMT_HANDLE fenceHandle) override; const bool hwQueuesSupported() override; bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, OsContextWin &osContext) override; }; @@ -49,6 +51,7 @@ class WddmInterface23 : public WddmInterface { bool createHwQueue(OsContextWin &osContext) override; void destroyHwQueue(D3DKMT_HANDLE hwQueue) override; bool createMonitoredFence(OsContextWin &osContext) override; + void destroyMonitorFence(D3DKMT_HANDLE fenceHandle) override; const bool hwQueuesSupported() override; bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, OsContextWin &osContext) override; }; diff --git a/unit_tests/mock_gdi/gdi32_mock.def b/unit_tests/mock_gdi/gdi32_mock.def index 76b740a7f1..58e9a75589 100644 --- a/unit_tests/mock_gdi/gdi32_mock.def +++ b/unit_tests/mock_gdi/gdi32_mock.def @@ -1,22 +1,9 @@ -; Copyright (c) 2017 - 2018, Intel Corporation ; -; Permission is hereby granted, free of charge, to any person obtaining a -; copy of this software and associated documentation files (the "Software"), -; to deal in the Software without restriction, including without limitation -; the rights to use, copy, modify, merge, publish, distribute, sublicense, -; and/or sell copies of the Software, and to permit persons to whom the -; Software is furnished to do so, subject to the following conditions: +; Copyright (C) 2017-2019 Intel Corporation +; +; SPDX-License-Identifier: MIT ; -; The above copyright notice and this permission notice shall be included -; in all copies or substantial portions of the Software. ; -; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -; OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -; OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -; ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -; OTHER DEALINGS IN THE SOFTWARE. LIBRARY "gdi32_mock" EXPORTS @@ -81,3 +68,4 @@ getCreateContextData getCreateHwQueueData getDestroyHwQueueData getSubmitCommandToHwQueueData +getDestroySynchronizationObjectData diff --git a/unit_tests/mock_gdi/mock_gdi.cpp b/unit_tests/mock_gdi/mock_gdi.cpp index 01a28b9284..04d16ba687 100644 --- a/unit_tests/mock_gdi/mock_gdi.cpp +++ b/unit_tests/mock_gdi/mock_gdi.cpp @@ -394,6 +394,13 @@ NTSTATUS __stdcall D3DKMTSubmitCommandToHwQueue(IN CONST D3DKMT_SUBMITCOMMANDTOH return STATUS_SUCCESS; } +static D3DKMT_DESTROYSYNCHRONIZATIONOBJECT destroySynchronizationObjectData = {}; + +NTSTATUS __stdcall D3DKMTDestroySynchronizationObject(IN CONST D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *destroySynchronizationObject) { + destroySynchronizationObjectData = *destroySynchronizationObject; + return STATUS_SUCCESS; +} + #ifdef __cplusplus } #endif @@ -464,3 +471,7 @@ D3DKMT_DESTROYHWQUEUE *getDestroyHwQueueData() { D3DKMT_SUBMITCOMMANDTOHWQUEUE *getSubmitCommandToHwQueueData() { return &submitCommandToHwQueueData; } + +D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *getDestroySynchronizationObjectData() { + return &destroySynchronizationObjectData; +} diff --git a/unit_tests/mock_gdi/mock_gdi.h b/unit_tests/mock_gdi/mock_gdi.h index 3daf67636d..e65d3272c4 100644 --- a/unit_tests/mock_gdi/mock_gdi.h +++ b/unit_tests/mock_gdi/mock_gdi.h @@ -26,7 +26,6 @@ FUNCTION(Unlock, IN CONST D3DKMT_UNLOCK *) \ FUNCTION(Render, IN OUT D3DKMT_RENDER *) \ FUNCTION(CreateSynchronizationObject, IN OUT D3DKMT_CREATESYNCHRONIZATIONOBJECT *) \ - FUNCTION(DestroySynchronizationObject, IN CONST D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *) \ FUNCTION(SignalSynchronizationObject, IN CONST D3DKMT_SIGNALSYNCHRONIZATIONOBJECT *) \ FUNCTION(WaitForSynchronizationObject, IN OUT CONST D3DKMT_WAITFORSYNCHRONIZATIONOBJECT *) \ FUNCTION(WaitForSynchronizationObjectFromCpu, IN CONST D3DKMT_WAITFORSYNCHRONIZATIONOBJECTFROMCPU *) \ @@ -78,4 +77,5 @@ D3DKMT_CREATECONTEXTVIRTUAL *getCreateContextData(); D3DKMT_CREATEHWQUEUE *getCreateHwQueueData(); D3DKMT_DESTROYHWQUEUE *getDestroyHwQueueData(); D3DKMT_SUBMITCOMMANDTOHWQUEUE *getSubmitCommandToHwQueueData(); +D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *getDestroySynchronizationObjectData(); void InitGfxPartition(); diff --git a/unit_tests/mocks/CMakeLists.txt b/unit_tests/mocks/CMakeLists.txt index b180704ad1..0a5e8d7a12 100644 --- a/unit_tests/mocks/CMakeLists.txt +++ b/unit_tests/mocks/CMakeLists.txt @@ -84,6 +84,7 @@ if(WIN32) ${CMAKE_CURRENT_SOURCE_DIR}/gmm_memory${BRANCH_DIR_SUFFIX}/mock_gmm_memory.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_gmm_page_table_mngr.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_gmm_page_table_mngr.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_interface20.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_interface23.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm.cpp diff --git a/unit_tests/mocks/mock_wddm_interface20.h b/unit_tests/mocks/mock_wddm_interface20.h new file mode 100644 index 0000000000..04ede2ab61 --- /dev/null +++ b/unit_tests/mocks/mock_wddm_interface20.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2019 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "runtime/os_interface/windows/wddm/wddm_interface.h" + +namespace NEO { +class WddmMockInterface20 : public WddmInterface20 { + public: + using WddmInterface20::WddmInterface20; + + void destroyMonitorFence(D3DKMT_HANDLE fenceHandle) override { + destroyMonitorFenceCalled++; + WddmInterface20::destroyMonitorFence(fenceHandle); + } + + uint32_t destroyMonitorFenceCalled = 0; +}; +} // namespace NEO diff --git a/unit_tests/mocks/mock_wddm_interface23.h b/unit_tests/mocks/mock_wddm_interface23.h index 447ece636b..4415ab4dff 100644 --- a/unit_tests/mocks/mock_wddm_interface23.h +++ b/unit_tests/mocks/mock_wddm_interface23.h @@ -20,8 +20,15 @@ class WddmMockInterface23 : public WddmInterface23 { return createHwQueueResult; } + void destroyMonitorFence(D3DKMT_HANDLE fenceHandle) override { + destroyMonitorFenceCalled++; + WddmInterface23::destroyMonitorFence(fenceHandle); + } + uint32_t createHwQueueCalled = 0; bool forceCreateHwQueueFail = false; bool createHwQueueResult = false; + + uint32_t destroyMonitorFenceCalled = 0; }; } // namespace NEO diff --git a/unit_tests/os_interface/windows/gdi_dll_fixture.h b/unit_tests/os_interface/windows/gdi_dll_fixture.h index f577ec0136..22ed732f09 100644 --- a/unit_tests/os_interface/windows/gdi_dll_fixture.h +++ b/unit_tests/os_interface/windows/gdi_dll_fixture.h @@ -41,13 +41,17 @@ struct GdiDllFixture { getDestroyHwQueueDataFcn = reinterpret_cast(mockGdiDll->getProcAddress("getDestroyHwQueueData")); getSubmitCommandToHwQueueDataFcn = reinterpret_cast(mockGdiDll->getProcAddress("getSubmitCommandToHwQueueData")); + getDestroySynchronizationObjectDataFcn = + reinterpret_cast(mockGdiDll->getProcAddress("getDestroySynchronizationObjectData")); setMockLastDestroyedResHandleFcn((D3DKMT_HANDLE)0); + *getDestroySynchronizationObjectDataFcn() = {}; } virtual void TearDown() { *getCreateHwQueueDataFcn() = {}; *getDestroyHwQueueDataFcn() = {}; *getSubmitCommandToHwQueueDataFcn() = {}; + *getDestroySynchronizationObjectDataFcn() = {}; setMapGpuVaFailConfigFcn(0, 0); } @@ -68,4 +72,5 @@ struct GdiDllFixture { decltype(&getCreateHwQueueData) getCreateHwQueueDataFcn = nullptr; decltype(&getDestroyHwQueueData) getDestroyHwQueueDataFcn = nullptr; decltype(&getSubmitCommandToHwQueueData) getSubmitCommandToHwQueueDataFcn = nullptr; + decltype(&getDestroySynchronizationObjectData) getDestroySynchronizationObjectDataFcn = nullptr; }; diff --git a/unit_tests/os_interface/windows/wddm20_tests.cpp b/unit_tests/os_interface/windows/wddm20_tests.cpp index 99edf4a4d1..58ca13429b 100644 --- a/unit_tests/os_interface/windows/wddm20_tests.cpp +++ b/unit_tests/os_interface/windows/wddm20_tests.cpp @@ -592,6 +592,14 @@ TEST_F(Wddm20WithMockGdiDllTests, whenCreateContextIsCalledThenDisableHwQueues) EXPECT_EQ(0u, getCreateContextDataFcn()->Flags.HwQueueSupported); } +TEST_F(Wddm20WithMockGdiDllTests, givenDestructionOsContextWinWhenCallingDestroyMonitorFenceThenDoCallGdiDestroy) { + auto fenceHandle = osContext->getResidencyController().getMonitoredFence().fenceHandle; + + osContext.reset(nullptr); + EXPECT_EQ(1u, wddmMockInterface->destroyMonitorFenceCalled); + EXPECT_EQ(fenceHandle, getDestroySynchronizationObjectDataFcn()->hSyncObject); +} + TEST_F(Wddm20Tests, whenCreateHwQueueIsCalledThenAlwaysReturnFalse) { EXPECT_FALSE(wddm->wddmInterface->createHwQueue(*osContext.get())); } diff --git a/unit_tests/os_interface/windows/wddm23_tests.cpp b/unit_tests/os_interface/windows/wddm23_tests.cpp index 0e7aee2806..0db2450b93 100644 --- a/unit_tests/os_interface/windows/wddm23_tests.cpp +++ b/unit_tests/os_interface/windows/wddm23_tests.cpp @@ -153,6 +153,12 @@ TEST_F(Wddm23Tests, givenCurrentPendingFenceValueGreaterThanPendingFenceValueWhe EXPECT_EQ(1u, wddm->waitOnGPUResult.called); } +TEST_F(Wddm23Tests, givenDestructionOsContextWinWhenCallingDestroyMonitorFenceThenDoNotCallGdiDestroy) { + osContext.reset(nullptr); + EXPECT_EQ(1u, wddmMockInterface->destroyMonitorFenceCalled); + EXPECT_EQ(0u, getDestroySynchronizationObjectDataFcn()->hSyncObject); +} + TEST_F(Wddm23TestsWithoutWddmInit, whenInitCalledThenInitializeNewGdiDDIsAndCallToCreateHwQueue) { EXPECT_EQ(nullptr, wddm->gdi->createHwQueue.mFunc); EXPECT_EQ(nullptr, wddm->gdi->destroyHwQueue.mFunc); diff --git a/unit_tests/os_interface/windows/wddm_fixture.h b/unit_tests/os_interface/windows/wddm_fixture.h index 798e727fac..404871000b 100644 --- a/unit_tests/os_interface/windows/wddm_fixture.h +++ b/unit_tests/os_interface/windows/wddm_fixture.h @@ -17,6 +17,7 @@ #include "runtime/platform/platform.h" #include "test.h" #include "unit_tests/mocks/mock_wddm.h" +#include "unit_tests/mocks/mock_wddm_interface20.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" @@ -55,6 +56,8 @@ struct WddmFixtureWithMockGdiDll : public GdiDllFixture { executionEnvironment = platformImpl->peekExecutionEnvironment(); GdiDllFixture::SetUp(); wddm = static_cast(Wddm::createWddm()); + wddmMockInterface = new WddmMockInterface20(*wddm); + wddm->wddmInterface.reset(wddmMockInterface); executionEnvironment->osInterface = std::make_unique(); executionEnvironment->osInterface->get()->setWddm(wddm); executionEnvironment->memoryOperationsInterface = std::make_unique(wddm); @@ -64,7 +67,9 @@ struct WddmFixtureWithMockGdiDll : public GdiDllFixture { void init() { auto preemptionMode = PreemptionHelper::getDefaultPreemptionMode(*platformDevices[0]); auto hwInfo = *platformDevices[0]; + wddmMockInterface = reinterpret_cast(wddm->wddmInterface.release()); wddm->init(hwInfo); + wddm->wddmInterface.reset(wddmMockInterface); osContext = std::make_unique(*osInterface->get()->getWddm(), 0u, 1, HwHelper::get(platformDevices[0]->platform.eRenderCoreFamily).getGpgpuEngineInstances()[0], preemptionMode, false); } @@ -76,6 +81,7 @@ struct WddmFixtureWithMockGdiDll : public GdiDllFixture { OSInterface *osInterface; std::unique_ptr osContext; ExecutionEnvironment *executionEnvironment; + WddmMockInterface20 *wddmMockInterface = nullptr; }; struct WddmInstrumentationGmmFixture {