From c4fcd7ed9b9ae47a6f64f15c67458fc032ad9ebc Mon Sep 17 00:00:00 2001 From: Bartosz Dunajski Date: Tue, 10 May 2022 13:53:48 +0000 Subject: [PATCH] Capability to set low scheduling priority for Wddm context Signed-off-by: Bartosz Dunajski --- .../os_interface/windows/wddm20_tests.cpp | 56 +++++++++++++++++++ .../test/unit_test/test_files/igdrcl.config | 1 + .../debug_settings/debug_variables_base.inl | 1 + .../os_interface/windows/gdi_interface.cpp | 5 +- .../os_interface/windows/gdi_interface.h | 3 +- .../source/os_interface/windows/thk_wrapper.h | 3 +- .../source/os_interface/windows/wddm/wddm.cpp | 29 +++++++++- .../source/os_interface/windows/wddm/wddm.h | 1 + shared/test/common/mock_gdi/gdi32_mock.def | 3 + shared/test/common/mock_gdi/mock_gdi.cpp | 23 +++++++- shared/test/common/mock_gdi/mock_gdi.h | 4 +- .../os_interface/windows/gdi_dll_fixture.h | 12 +++- 12 files changed, 133 insertions(+), 8 deletions(-) diff --git a/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp b/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp index 5ca29bc669..e3d0e7a63a 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp +++ b/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp @@ -665,6 +665,62 @@ TEST_F(Wddm20WithMockGdiDllTestsWithoutWddmInit, givenUseNoRingFlushesKmdModeDeb EXPECT_FALSE(!!privateData->NoRingFlushes); } +struct WddmContextSchedulingPriorityTests : public Wddm20WithMockGdiDllTestsWithoutWddmInit { + void initContext(bool lowPriority) { + auto preemptionMode = PreemptionHelper::getDefaultPreemptionMode(*defaultHwInfo); + wddmMockInterface = static_cast(wddm->wddmInterface.release()); + wddm->init(); + wddm->wddmInterface.reset(wddmMockInterface); + + auto hwInfo = rootDeviceEnvironment->getHardwareInfo(); + auto engine = HwHelper::get(defaultHwInfo->platform.eRenderCoreFamily).getGpgpuEngineInstances(*hwInfo)[0]; + + auto engineDescriptor = EngineDescriptorHelper::getDefaultDescriptor(engine, preemptionMode); + engineDescriptor.engineTypeUsage.second = lowPriority ? EngineUsage::LowPriority : EngineUsage::Regular; + osContext = std::make_unique(*osInterface->getDriverModel()->as(), 0u, engineDescriptor); + osContext->ensureContextInitialized(); + } +}; + +TEST_F(WddmContextSchedulingPriorityTests, givenLowPriorityContextWhenInitializingThenCallSetPriority) { + initContext(true); + + auto createContextParams = this->getSetContextSchedulingPriorityDataCallFcn(); + + EXPECT_EQ(osContext->getWddmContextHandle(), createContextParams->hContext); + EXPECT_EQ(1, createContextParams->Priority); +} + +TEST_F(WddmContextSchedulingPriorityTests, givenLowPriorityContextWhenFailingDuringSetSchedulingPriorityThenThrow) { + *this->getFailOnSetContextSchedulingPriorityCallFcn() = true; + + EXPECT_ANY_THROW(initContext(true)); +} + +TEST_F(WddmContextSchedulingPriorityTests, givenDebugFlagSetWhenInitializingLowPriorityContextThenSetPriorityValue) { + DebugManagerStateRestore dbgRestore; + + constexpr int32_t newPriority = 3; + + DebugManager.flags.ForceWddmLowPriorityContextValue.set(newPriority); + + initContext(true); + + auto createContextParams = this->getSetContextSchedulingPriorityDataCallFcn(); + + EXPECT_EQ(osContext->getWddmContextHandle(), createContextParams->hContext); + EXPECT_EQ(newPriority, createContextParams->Priority); +} + +TEST_F(WddmContextSchedulingPriorityTests, givenRegularContextWhenInitializingThenDontCallSetPriority) { + initContext(false); + + auto createContextParams = this->getSetContextSchedulingPriorityDataCallFcn(); + + EXPECT_EQ(0, createContextParams->hContext); + EXPECT_EQ(0, createContextParams->Priority); +} + TEST_F(Wddm20WithMockGdiDllTestsWithoutWddmInit, givenCreateContextCallWhenDriverHintsThenItPointsToOpenCL) { init(); auto createContextParams = this->getCreateContextDataFcn(); diff --git a/opencl/test/unit_test/test_files/igdrcl.config b/opencl/test/unit_test/test_files/igdrcl.config index a8487f3433..1efe9272b9 100644 --- a/opencl/test/unit_test/test_files/igdrcl.config +++ b/opencl/test/unit_test/test_files/igdrcl.config @@ -419,3 +419,4 @@ UseContextEndOffsetForEventCompletion = -1 DirectSubmissionInsertExtraMiMemFenceCommands = -1 DirectSubmissionInsertSfenceInstructionPriorToSubmission = -1 EnableTimestampWaitForEvents = -1 +ForceWddmLowPriorityContextValue = -1 \ No newline at end of file diff --git a/shared/source/debug_settings/debug_variables_base.inl b/shared/source/debug_settings/debug_variables_base.inl index 8f9dce9f20..ccc175f66d 100644 --- a/shared/source/debug_settings/debug_variables_base.inl +++ b/shared/source/debug_settings/debug_variables_base.inl @@ -202,6 +202,7 @@ DECLARE_DEBUG_VARIABLE(int32_t, BatchBufferStartPrepatchingWaEnabled, -1, "-1: d DECLARE_DEBUG_VARIABLE(int32_t, SetVmAdviseAtomicAttribute, -1, "-1: default - atomic system, 0: atomic none, 1: atomic device, 2: atomic system)") DECLARE_DEBUG_VARIABLE(int32_t, ReadBackCommandBufferAllocation, -1, "Read command buffer allocation back on the host side. -1: default, 0 - disabled, 1 - local memory only, 2 - local and system memory") DECLARE_DEBUG_VARIABLE(int32_t, UseContextEndOffsetForEventCompletion, -1, "Use Context End or Context Start for event completion signalling. -1: default: platform dependent, 0 - Use Context Start, 1 - Use Context End") +DECLARE_DEBUG_VARIABLE(int32_t, ForceWddmLowPriorityContextValue, -1, "Force scheduling priority value during Wddm low priority context creation. -1 - default.") DECLARE_DEBUG_VARIABLE(bool, DisableScratchPages, false, "Disable scratch pages during VM creations") /*LOGGING FLAGS*/ DECLARE_DEBUG_VARIABLE(int32_t, PrintDriverDiagnostics, -1, "prints driver diagnostics messages to standard output, value corresponds to hint level") diff --git a/shared/source/os_interface/windows/gdi_interface.cpp b/shared/source/os_interface/windows/gdi_interface.cpp index bda4980619..75f7314c67 100644 --- a/shared/source/os_interface/windows/gdi_interface.cpp +++ b/shared/source/os_interface/windows/gdi_interface.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -77,6 +77,7 @@ bool Gdi::getAllProcAddresses() { registerTrimNotification = gdiDll->getProcAddress("D3DKMTRegisterTrimNotification"); unregisterTrimNotification = gdiDll->getProcAddress("D3DKMTUnregisterTrimNotification"); setAllocationPriority = gdiDll->getProcAddress("D3DKMTSetAllocationPriority"); + setSchedulingPriority = gdiDll->getProcAddress("D3DKMTSetContextSchedulingPriority"); // For debug purposes getDeviceState = gdiDll->getProcAddress("D3DKMTGetDeviceState"); @@ -93,7 +94,7 @@ bool Gdi::getAllProcAddresses() { && signalSynchronizationObjectFromGpu && createPagingQueue && destroyPagingQueue && lock2 && unlock2 && mapGpuVirtualAddress && reserveGpuVirtualAddress && freeGpuVirtualAddress && updateGpuVirtualAddress &&submitCommand - && makeResident && evict){ + && makeResident && evict && setSchedulingPriority){ if (NEO::OSInterface::requiresSupportForWddmTrimNotification) { if(registerTrimNotification && unregisterTrimNotification){ return true; diff --git a/shared/source/os_interface/windows/gdi_interface.h b/shared/source/os_interface/windows/gdi_interface.h index 01527032f3..103a773b02 100644 --- a/shared/source/os_interface/windows/gdi_interface.h +++ b/shared/source/os_interface/windows/gdi_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -62,6 +62,7 @@ class Gdi { ThkWrapper registerTrimNotification{}; ThkWrapper unregisterTrimNotification{}; ThkWrapper setAllocationPriority{}; + ThkWrapper setSchedulingPriority{}; // HW queue ThkWrapper createHwQueue{}; diff --git a/shared/source/os_interface/windows/thk_wrapper.h b/shared/source/os_interface/windows/thk_wrapper.h index 23d9c3b787..539341b468 100644 --- a/shared/source/os_interface/windows/thk_wrapper.h +++ b/shared/source/os_interface/windows/thk_wrapper.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -71,6 +71,7 @@ GET_ID(D3DKMT_CREATEHWQUEUE *, SYSTIMER_ID_CREATEHWQUEUE) GET_ID(CONST D3DKMT_DESTROYHWQUEUE *, SYSTIMER_ID_DESTROYHWQUEUE) GET_ID(CONST D3DKMT_SUBMITCOMMANDTOHWQUEUE *, SYSTIMER_ID_SUBMITCOMMANDTOHWQUEUE) GET_ID(CONST D3DKMT_SETALLOCATIONPRIORITY *, SYSTIMER_ID_SETALLOCATIONPRIORITY) +GET_ID(CONST D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *, SYSTIMER_ID_SETCONTEXTSCHEDULINGPRIORITY) template class ThkWrapper { diff --git a/shared/source/os_interface/windows/wddm/wddm.cpp b/shared/source/os_interface/windows/wddm/wddm.cpp index f0bd5d2dcd..5fe5a0b0de 100644 --- a/shared/source/os_interface/windows/wddm/wddm.cpp +++ b/shared/source/os_interface/windows/wddm/wddm.cpp @@ -792,6 +792,25 @@ void Wddm::kmDafLock(D3DKMT_HANDLE handle) { kmDafListener->notifyLock(featureTable->flags.ftrKmdDaf, getAdapter(), device, handle, 0, getGdi()->escape); } +bool Wddm::setLowPriorityContextParam(D3DKMT_HANDLE contextHandle) { + D3DKMT_SETCONTEXTSCHEDULINGPRIORITY contextPriority = {}; + + contextPriority.hContext = contextHandle; + contextPriority.Priority = 1; + + if (DebugManager.flags.ForceWddmLowPriorityContextValue.get() != -1) { + contextPriority.Priority = static_cast(DebugManager.flags.ForceWddmLowPriorityContextValue.get()); + } + + auto status = getGdi()->setSchedulingPriority(&contextPriority); + + PRINT_DEBUG_STRING(DebugManager.flags.PrintDebugMessages.get(), stdout, + "\nSet scheduling priority for Wddm context. Status: :%lu, context handle: %u, priority: %d \n", + status, contextHandle, contextPriority.Priority); + + return (status == STATUS_SUCCESS); +} + bool Wddm::createContext(OsContextWin &osContext) { NTSTATUS status = STATUS_UNSUCCESSFUL; D3DKMT_CREATECONTEXTVIRTUAL CreateContext = {}; @@ -838,7 +857,15 @@ bool Wddm::createContext(OsContextWin &osContext) { "\nCreated Wddm context. Status: :%lu, engine: %u, contextId: %u, deviceBitfield: %lu \n", status, osContext.getEngineType(), osContext.getContextId(), osContext.getDeviceBitfield().to_ulong()); - return status == STATUS_SUCCESS; + if (status != STATUS_SUCCESS) { + return false; + } + + if (osContext.isLowPriority()) { + return setLowPriorityContextParam(osContext.getWddmContextHandle()); + } + + return true; } bool Wddm::destroyContext(D3DKMT_HANDLE context) { diff --git a/shared/source/os_interface/windows/wddm/wddm.h b/shared/source/os_interface/windows/wddm/wddm.h index bbb45cc1da..9ba4986773 100644 --- a/shared/source/os_interface/windows/wddm/wddm.h +++ b/shared/source/os_interface/windows/wddm/wddm.h @@ -243,6 +243,7 @@ class Wddm : public DriverModel { bool destroyDevice(); void getDeviceState(); MOCKABLE_VIRTUAL void createPagingFenceLogger(); + bool setLowPriorityContextParam(D3DKMT_HANDLE contextHandle); static GetSystemInfoFcn getSystemInfo; diff --git a/shared/test/common/mock_gdi/gdi32_mock.def b/shared/test/common/mock_gdi/gdi32_mock.def index 6536cb23bb..a34d4f4f06 100644 --- a/shared/test/common/mock_gdi/gdi32_mock.def +++ b/shared/test/common/mock_gdi/gdi32_mock.def @@ -54,6 +54,7 @@ D3DKMTCreateHwQueue D3DKMTDestroyHwQueue D3DKMTSubmitCommandToHwQueue D3DKMTSetAllocationPriority +D3DKMTSetContextSchedulingPriority MockSetAdapterInfo MockSetSizes GetMockSizes @@ -73,6 +74,8 @@ getSubmitCommandToHwQueueData getDestroySynchronizationObjectData getMonitorFenceCpuFenceAddress getCreateSynchronizationObject2FailCall +getFailOnSetContextSchedulingPriorityCall +getSetContextSchedulingPriorityDataCall getRegisterTrimNotificationFailCall getLastPriority setAdapterBDF diff --git a/shared/test/common/mock_gdi/mock_gdi.cpp b/shared/test/common/mock_gdi/mock_gdi.cpp index c45d7c9197..f0594c9600 100644 --- a/shared/test/common/mock_gdi/mock_gdi.cpp +++ b/shared/test/common/mock_gdi/mock_gdi.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -122,6 +122,19 @@ NTSTATUS __stdcall D3DKMTCreateContextVirtual(IN D3DKMT_CREATECONTEXTVIRTUAL *cr return STATUS_SUCCESS; } +static bool failOnSetContextSchedulingPriority = false; +static D3DKMT_SETCONTEXTSCHEDULINGPRIORITY setContextSchedulingPriorityData = {}; + +NTSTATUS __stdcall D3DKMTSetContextSchedulingPriority(_In_ CONST D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *setContextSchedulingPriority) { + setContextSchedulingPriorityData = *setContextSchedulingPriority; + + if (failOnSetContextSchedulingPriority) { + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + NTSTATUS __stdcall D3DKMTDestroyContext(IN CONST D3DKMT_DESTROYCONTEXT *destroyContext) { if (destroyContext == nullptr || destroyContext->hContext != CONTEXT_HANDLE) { return STATUS_INVALID_PARAMETER; @@ -567,3 +580,11 @@ uint32_t getLastPriority() { void setAdapterBDF(ADAPTER_BDF &adapterBDF) { gAdapterBDF = adapterBDF; } + +bool *getFailOnSetContextSchedulingPriorityCall() { + return &failOnSetContextSchedulingPriority; +} + +D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *getSetContextSchedulingPriorityDataCall() { + return &setContextSchedulingPriorityData; +} diff --git a/shared/test/common/mock_gdi/mock_gdi.h b/shared/test/common/mock_gdi/mock_gdi.h index f626338c3a..9c30b3692e 100644 --- a/shared/test/common/mock_gdi/mock_gdi.h +++ b/shared/test/common/mock_gdi/mock_gdi.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -78,6 +78,8 @@ D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *getDestroySynchronizationObjectData(); void InitGfxPartition(); VOID *getMonitorFenceCpuFenceAddress(); bool *getCreateSynchronizationObject2FailCall(); +bool *getFailOnSetContextSchedulingPriorityCall(); +D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *getSetContextSchedulingPriorityDataCall(); bool *getRegisterTrimNotificationFailCall(); uint32_t getLastPriority(); void setAdapterBDF(ADAPTER_BDF &adapterBDF); diff --git a/shared/test/common/os_interface/windows/gdi_dll_fixture.h b/shared/test/common/os_interface/windows/gdi_dll_fixture.h index b68c12ddab..fcfe5ed730 100644 --- a/shared/test/common/os_interface/windows/gdi_dll_fixture.h +++ b/shared/test/common/os_interface/windows/gdi_dll_fixture.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -47,6 +47,10 @@ struct GdiDllFixture { reinterpret_cast(mockGdiDll->getProcAddress("getMonitorFenceCpuFenceAddress")); getCreateSynchronizationObject2FailCallFcn = reinterpret_cast(mockGdiDll->getProcAddress("getCreateSynchronizationObject2FailCall")); + getFailOnSetContextSchedulingPriorityCallFcn = + reinterpret_cast(mockGdiDll->getProcAddress("getFailOnSetContextSchedulingPriorityCall")); + getSetContextSchedulingPriorityDataCallFcn = + reinterpret_cast(mockGdiDll->getProcAddress("getSetContextSchedulingPriorityDataCall")); getRegisterTrimNotificationFailCallFcn = reinterpret_cast(mockGdiDll->getProcAddress("getRegisterTrimNotificationFailCall")); getLastPriorityFcn = @@ -56,6 +60,8 @@ struct GdiDllFixture { setMockLastDestroyedResHandleFcn((D3DKMT_HANDLE)0); *getDestroySynchronizationObjectDataFcn() = {}; *getCreateSynchronizationObject2FailCallFcn() = false; + *getFailOnSetContextSchedulingPriorityCallFcn() = false; + *getSetContextSchedulingPriorityDataCallFcn() = {}; *getRegisterTrimNotificationFailCallFcn() = false; } @@ -66,6 +72,8 @@ struct GdiDllFixture { *getDestroySynchronizationObjectDataFcn() = {}; setMapGpuVaFailConfigFcn(0, 0); *getCreateSynchronizationObject2FailCallFcn() = false; + *getFailOnSetContextSchedulingPriorityCallFcn() = false; + *getSetContextSchedulingPriorityDataCallFcn() = {}; *getRegisterTrimNotificationFailCallFcn() = false; } @@ -89,6 +97,8 @@ struct GdiDllFixture { decltype(&getDestroySynchronizationObjectData) getDestroySynchronizationObjectDataFcn = nullptr; decltype(&getMonitorFenceCpuFenceAddress) getMonitorFenceCpuFenceAddressFcn = nullptr; decltype(&getCreateSynchronizationObject2FailCall) getCreateSynchronizationObject2FailCallFcn = nullptr; + decltype(&getFailOnSetContextSchedulingPriorityCall) getFailOnSetContextSchedulingPriorityCallFcn = nullptr; + decltype(&getSetContextSchedulingPriorityDataCall) getSetContextSchedulingPriorityDataCallFcn = nullptr; decltype(&getRegisterTrimNotificationFailCall) getRegisterTrimNotificationFailCallFcn = nullptr; decltype(&getLastPriority) getLastPriorityFcn = nullptr; decltype(&setAdapterBDF) setAdapterBDFFcn = nullptr;