From c0c6a46ece2aa582c9dba3d8ddae41e6e0420a89 Mon Sep 17 00:00:00 2001 From: "Dunajski, Bartosz" Date: Fri, 13 Sep 2019 08:13:02 +0200 Subject: [PATCH] Wddm 2.3 improvements - Dont create synchronization object manually - take it from HW queue - Construct MonitoredFence from HwQueue object - D3DKMT_SUBMITCOMMANDTOHWQUEUE should get currentFenceValue instead of its handle - Dont pass MonitoredFenceVa/Value in cmd buffer header Change-Id: I4717119379cef2f0e641ce9f4ef614089491a85d Signed-off-by: Dunajski, Bartosz Related-To: NEO-3728 --- .../os_interface/windows/os_context_win.cpp | 4 +-- runtime/os_interface/windows/os_context_win.h | 16 +++++++--- .../windows/wddm/wddm_interface.cpp | 23 +++++++++----- .../windows/wddm/wddm_interface.h | 4 ++- .../os_interface/windows/wddm20_tests.cpp | 2 +- .../os_interface/windows/wddm23_tests.cpp | 27 +++++++++-------- .../wddm_residency_controller_tests.cpp | 30 ++++++++++++++----- 7 files changed, 70 insertions(+), 36 deletions(-) diff --git a/runtime/os_interface/windows/os_context_win.cpp b/runtime/os_interface/windows/os_context_win.cpp index ed82c4a371..d7696c16da 100644 --- a/runtime/os_interface/windows/os_context_win.cpp +++ b/runtime/os_interface/windows/os_context_win.cpp @@ -34,12 +34,12 @@ OsContextWin::OsContextWin(Wddm &wddm, uint32_t contextId, DeviceBitfield device return; } } - initialized = wddmInterface->createMonitoredFence(residencyController); + initialized = wddmInterface->createMonitoredFence(*this); residencyController.registerCallback(); }; OsContextWin::~OsContextWin() { - wddm.getWddmInterface()->destroyHwQueue(hwQueueHandle); + wddm.getWddmInterface()->destroyHwQueue(hardwareQueue.handle); wddm.destroyContext(wddmContextHandle); } diff --git a/runtime/os_interface/windows/os_context_win.h b/runtime/os_interface/windows/os_context_win.h index fa8f731194..a5b2e9ddac 100644 --- a/runtime/os_interface/windows/os_context_win.h +++ b/runtime/os_interface/windows/os_context_win.h @@ -12,6 +12,14 @@ namespace NEO { class Wddm; + +struct HardwareQueue { + D3DKMT_HANDLE handle = 0; + D3DKMT_HANDLE progressFenceHandle = 0; + VOID *progressFenceCpuVA = nullptr; + D3DGPU_VIRTUAL_ADDRESS progressFenceGpuVA = 0; +}; + class OsContextWin : public OsContext { public: OsContextWin() = delete; @@ -22,16 +30,16 @@ class OsContextWin : public OsContext { D3DKMT_HANDLE getWddmContextHandle() const { return wddmContextHandle; } void setWddmContextHandle(D3DKMT_HANDLE wddmContextHandle) { this->wddmContextHandle = wddmContextHandle; } - D3DKMT_HANDLE getHwQueue() const { return hwQueueHandle; } - void setHwQueue(D3DKMT_HANDLE hwQueue) { hwQueueHandle = hwQueue; } + HardwareQueue getHwQueue() const { return hardwareQueue; } + void setHwQueue(HardwareQueue hardwareQueue) { this->hardwareQueue = hardwareQueue; } bool isInitialized() const { return initialized; } Wddm *getWddm() const { return &wddm; } - WddmResidencyController &getResidencyController() { return residencyController; } + MOCKABLE_VIRTUAL WddmResidencyController &getResidencyController() { return residencyController; } protected: bool initialized = false; D3DKMT_HANDLE wddmContextHandle = 0; - D3DKMT_HANDLE hwQueueHandle = 0; + HardwareQueue hardwareQueue; Wddm &wddm; WddmResidencyController residencyController; }; diff --git a/runtime/os_interface/windows/wddm/wddm_interface.cpp b/runtime/os_interface/windows/wddm/wddm_interface.cpp index 75d15fba43..362407b6ca 100644 --- a/runtime/os_interface/windows/wddm/wddm_interface.cpp +++ b/runtime/os_interface/windows/wddm/wddm_interface.cpp @@ -19,7 +19,8 @@ bool WddmInterface20::createHwQueue(OsContextWin &osContext) { } void WddmInterface20::destroyHwQueue(D3DKMT_HANDLE hwQueue) {} -bool WddmInterface::createMonitoredFence(WddmResidencyController &residencyController) { +bool WddmInterface20::createMonitoredFence(OsContextWin &osContext) { + auto &residencyController = osContext.getResidencyController(); NTSTATUS Status; D3DKMT_CREATESYNCHRONIZATIONOBJECT2 CreateSynchronizationObject = {0}; CreateSynchronizationObject.hDevice = wddm.getDevice(); @@ -80,11 +81,21 @@ bool WddmInterface23::createHwQueue(OsContextWin &osContext) { auto status = wddm.getGdi()->createHwQueue(&createHwQueue); UNRECOVERABLE_IF(status != STATUS_SUCCESS); - osContext.setHwQueue(createHwQueue.hHwQueue); + osContext.setHwQueue({createHwQueue.hHwQueue, createHwQueue.hHwQueueProgressFence, createHwQueue.HwQueueProgressFenceCPUVirtualAddress, + createHwQueue.HwQueueProgressFenceGPUVirtualAddress}); return status == STATUS_SUCCESS; } +bool WddmInterface23::createMonitoredFence(OsContextWin &osContext) { + auto &residencyController = osContext.getResidencyController(); + auto hwQueue = osContext.getHwQueue(); + residencyController.resetMonitoredFenceParams(hwQueue.progressFenceHandle, + reinterpret_cast(hwQueue.progressFenceCpuVA), + hwQueue.progressFenceGpuVA); + return true; +} + void WddmInterface23::destroyHwQueue(D3DKMT_HANDLE hwQueue) { if (hwQueue) { D3DKMT_DESTROYHWQUEUE destroyHwQueue = {}; @@ -103,15 +114,11 @@ bool WddmInterface23::submit(uint64_t commandBuffer, size_t size, void *commandH auto monitoredFence = osContext.getResidencyController().getMonitoredFence(); D3DKMT_SUBMITCOMMANDTOHWQUEUE submitCommand = {}; - submitCommand.hHwQueue = osContext.getHwQueue(); - submitCommand.HwQueueProgressFenceId = monitoredFence.fenceHandle; + submitCommand.hHwQueue = osContext.getHwQueue().handle; + submitCommand.HwQueueProgressFenceId = monitoredFence.currentFenceValue; submitCommand.CommandBuffer = commandBuffer; submitCommand.CommandLength = static_cast(size); - COMMAND_BUFFER_HEADER *pHeader = reinterpret_cast(commandHeader); - pHeader->MonitorFenceVA = monitoredFence.gpuAddress; - pHeader->MonitorFenceValue = monitoredFence.currentFenceValue; - submitCommand.pPrivateDriverData = commandHeader; submitCommand.PrivateDriverDataSize = MemoryConstants::pageSize; diff --git a/runtime/os_interface/windows/wddm/wddm_interface.h b/runtime/os_interface/windows/wddm/wddm_interface.h index b53f329178..8a8348b943 100644 --- a/runtime/os_interface/windows/wddm/wddm_interface.h +++ b/runtime/os_interface/windows/wddm/wddm_interface.h @@ -27,7 +27,7 @@ class WddmInterface { WddmInterface() = delete; virtual bool createHwQueue(OsContextWin &osContext) = 0; virtual void destroyHwQueue(D3DKMT_HANDLE hwQueue) = 0; - bool createMonitoredFence(WddmResidencyController &residencyController); + virtual bool createMonitoredFence(OsContextWin &osContext) = 0; virtual const bool hwQueuesSupported() = 0; virtual bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, OsContextWin &osContext) = 0; Wddm &wddm; @@ -38,6 +38,7 @@ class WddmInterface20 : public WddmInterface { using WddmInterface::WddmInterface; bool createHwQueue(OsContextWin &osContext) override; void destroyHwQueue(D3DKMT_HANDLE hwQueue) override; + bool createMonitoredFence(OsContextWin &osContext) override; const bool hwQueuesSupported() override; bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, OsContextWin &osContext) override; }; @@ -47,6 +48,7 @@ class WddmInterface23 : public WddmInterface { using WddmInterface::WddmInterface; bool createHwQueue(OsContextWin &osContext) override; void destroyHwQueue(D3DKMT_HANDLE hwQueue) override; + bool createMonitoredFence(OsContextWin &osContext) override; const bool hwQueuesSupported() override; bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, OsContextWin &osContext) override; }; diff --git a/unit_tests/os_interface/windows/wddm20_tests.cpp b/unit_tests/os_interface/windows/wddm20_tests.cpp index d5e43b8355..a9081ea8bf 100644 --- a/unit_tests/os_interface/windows/wddm20_tests.cpp +++ b/unit_tests/os_interface/windows/wddm20_tests.cpp @@ -649,7 +649,7 @@ TEST_F(Wddm20Tests, createMonitoredFenceIsInitializedWithFenceValueZeroAndCurren gdi->getCreateSynchronizationObject2Arg().Info.MonitoredFence.InitialFenceValue = 300; - wddm->wddmInterface->createMonitoredFence(osContext->getResidencyController()); + wddm->wddmInterface->createMonitoredFence(*osContext); EXPECT_EQ(0u, gdi->getCreateSynchronizationObject2Arg().Info.MonitoredFence.InitialFenceValue); EXPECT_EQ(1u, osContext->getResidencyController().getMonitoredFence().currentFenceValue); diff --git a/unit_tests/os_interface/windows/wddm23_tests.cpp b/unit_tests/os_interface/windows/wddm23_tests.cpp index e63502f56d..1230165a1a 100644 --- a/unit_tests/os_interface/windows/wddm23_tests.cpp +++ b/unit_tests/os_interface/windows/wddm23_tests.cpp @@ -86,19 +86,19 @@ TEST_F(Wddm23Tests, givenPreemptionModeWhenCreateHwQueueCalledThenSetGpuTimeoutI TEST_F(Wddm23Tests, whenDestroyHwQueueCalledThenPassExistingHandle) { D3DKMT_HANDLE hwQueue = 123; - osContext->setHwQueue(hwQueue); - wddmMockInterface->destroyHwQueue(osContext->getHwQueue()); + osContext->setHwQueue({hwQueue, 0, nullptr, 0}); + wddmMockInterface->destroyHwQueue(osContext->getHwQueue().handle); EXPECT_EQ(hwQueue, getDestroyHwQueueDataFcn()->hHwQueue); hwQueue = 0; - osContext->setHwQueue(hwQueue); - wddmMockInterface->destroyHwQueue(osContext->getHwQueue()); + osContext->setHwQueue({hwQueue, 0, nullptr, 0}); + wddmMockInterface->destroyHwQueue(osContext->getHwQueue().handle); EXPECT_NE(hwQueue, getDestroyHwQueueDataFcn()->hHwQueue); // gdi not called when 0 } TEST_F(Wddm23Tests, whenObjectIsDestructedThenDestroyHwQueue) { D3DKMT_HANDLE hwQueue = 123; - osContext->setHwQueue(hwQueue); + osContext->setHwQueue({hwQueue, 0, nullptr, 0}); osContext.reset(); EXPECT_EQ(hwQueue, getDestroyHwQueueDataFcn()->hHwQueue); } @@ -116,24 +116,25 @@ TEST_F(Wddm23Tests, givenCmdBufferWhenSubmitCalledThenSetAllRequiredFiledsAndUpd EXPECT_EQ(cmdBufferAddress, getSubmitCommandToHwQueueDataFcn()->CommandBuffer); EXPECT_EQ(static_cast(cmdSize), getSubmitCommandToHwQueueDataFcn()->CommandLength); - EXPECT_EQ(hwQueue, getSubmitCommandToHwQueueDataFcn()->hHwQueue); - EXPECT_EQ(osContext->getResidencyController().getMonitoredFence().fenceHandle, getSubmitCommandToHwQueueDataFcn()->HwQueueProgressFenceId); + EXPECT_EQ(hwQueue.handle, getSubmitCommandToHwQueueDataFcn()->hHwQueue); + EXPECT_EQ(osContext->getResidencyController().getMonitoredFence().lastSubmittedFence, getSubmitCommandToHwQueueDataFcn()->HwQueueProgressFenceId); EXPECT_EQ(&cmdBufferHeader, getSubmitCommandToHwQueueDataFcn()->pPrivateDriverData); EXPECT_EQ(static_cast(MemoryConstants::pageSize), getSubmitCommandToHwQueueDataFcn()->PrivateDriverDataSize); - EXPECT_EQ(osContext->getResidencyController().getMonitoredFence().gpuAddress, cmdBufferHeader.MonitorFenceVA); - EXPECT_EQ(osContext->getResidencyController().getMonitoredFence().lastSubmittedFence, cmdBufferHeader.MonitorFenceValue); + EXPECT_EQ(0u, cmdBufferHeader.MonitorFenceVA); + EXPECT_EQ(0u, cmdBufferHeader.MonitorFenceValue); EXPECT_EQ(2u, osContext->getResidencyController().getMonitoredFence().currentFenceValue); EXPECT_EQ(1u, osContext->getResidencyController().getMonitoredFence().lastSubmittedFence); } TEST_F(Wddm23Tests, whenMonitoredFenceIsCreatedThenSetupAllRequiredFields) { - wddm->wddmInterface->createMonitoredFence(osContext->getResidencyController()); + wddm->wddmInterface->createMonitoredFence(*osContext); + auto hwQueue = osContext->getHwQueue(); - EXPECT_NE(nullptr, osContext->getResidencyController().getMonitoredFence().cpuAddress); + EXPECT_EQ(hwQueue.progressFenceCpuVA, osContext->getResidencyController().getMonitoredFence().cpuAddress); EXPECT_EQ(1u, osContext->getResidencyController().getMonitoredFence().currentFenceValue); - EXPECT_NE(static_cast(0), osContext->getResidencyController().getMonitoredFence().fenceHandle); - EXPECT_NE(static_cast(0), osContext->getResidencyController().getMonitoredFence().gpuAddress); + EXPECT_EQ(hwQueue.progressFenceHandle, osContext->getResidencyController().getMonitoredFence().fenceHandle); + EXPECT_EQ(hwQueue.progressFenceGpuVA, osContext->getResidencyController().getMonitoredFence().gpuAddress); EXPECT_EQ(0u, osContext->getResidencyController().getMonitoredFence().lastSubmittedFence); } 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 0933df7aa6..b9eb28e79a 100644 --- a/unit_tests/os_interface/windows/wddm_residency_controller_tests.cpp +++ b/unit_tests/os_interface/windows/wddm_residency_controller_tests.cpp @@ -48,6 +48,18 @@ class MockWddmResidencyController : public WddmResidencyController { } }; +class MockOsContextWin : public OsContextWin { + public: + MockOsContextWin(Wddm &wddm, uint32_t contextId, DeviceBitfield deviceBitfield, + aub_stream::EngineType engineType, PreemptionMode preemptionMode, bool lowPriority) + : OsContextWin(wddm, contextId, deviceBitfield, engineType, preemptionMode, lowPriority), + mockResidencyController(wddm, contextId) {} + + WddmResidencyController &getResidencyController() override { return mockResidencyController; }; + + MockWddmResidencyController mockResidencyController; +}; + struct WddmResidencyControllerTest : ::testing::Test { const uint32_t osContextId = 0u; @@ -55,12 +67,14 @@ struct WddmResidencyControllerTest : ::testing::Test { wddm = std::unique_ptr(static_cast(Wddm::createWddm())); auto hwInfo = *platformDevices[0]; wddm->init(hwInfo); - residencyController = std::make_unique(*wddm, osContextId); - wddm->getWddmInterface()->createMonitoredFence(*residencyController); + mockOsContextWin = std::make_unique(*wddm, osContextId, 0, aub_stream::ENGINE_RCS, PreemptionMode::Disabled, false); + wddm->getWddmInterface()->createMonitoredFence(*mockOsContextWin); + residencyController = &mockOsContextWin->mockResidencyController; } std::unique_ptr wddm; - std::unique_ptr residencyController; + std::unique_ptr mockOsContextWin; + MockWddmResidencyController *residencyController = nullptr; }; struct WddmResidencyControllerWithGdiTest : ::testing::Test { @@ -73,13 +87,15 @@ struct WddmResidencyControllerWithGdiTest : ::testing::Test { auto hwInfo = *platformDevices[0]; wddm->init(hwInfo); - residencyController = std::make_unique(*wddm, osContextId); - wddm->getWddmInterface()->createMonitoredFence(*residencyController); + mockOsContextWin = std::make_unique(*wddm, osContextId, 0, aub_stream::ENGINE_RCS, PreemptionMode::Disabled, false); + wddm->getWddmInterface()->createMonitoredFence(*mockOsContextWin); + residencyController = &mockOsContextWin->mockResidencyController; residencyController->registerCallback(); } std::unique_ptr wddm; - std::unique_ptr residencyController; + std::unique_ptr mockOsContextWin; + MockWddmResidencyController *residencyController = nullptr; MockGdi *gdi; }; @@ -212,7 +228,7 @@ TEST_F(WddmResidencyControllerWithGdiTest, givenWddmResidencyControllerWhenItIsD auto trimCallbackAddress = reinterpret_cast(WddmResidencyController::trimCallback); std::memset(&gdi->getUnregisterTrimNotificationArg(), 0, sizeof(D3DKMT_UNREGISTERTRIMNOTIFICATION)); - residencyController.reset(); + mockOsContextWin.reset(); EXPECT_EQ(trimCallbackAddress, gdi->getUnregisterTrimNotificationArg().Callback); EXPECT_EQ(trimCallbackHandle, gdi->getUnregisterTrimNotificationArg().Handle);