From 71b844f52231cc242694ee940a835a66396fc15f Mon Sep 17 00:00:00 2001 From: "Dunajski, Bartosz" Date: Fri, 18 May 2018 10:18:16 +0200 Subject: [PATCH] Wddm interface [7/n]: Add 2.3 interface with HW queue support Change-Id: Ia0e829b8616b7060e39170aea0f1d2f123d73399 --- runtime/dll/CMakeLists.txt | 2 +- runtime/os_interface/DebugVariables.inl | 1 - .../os_interface/windows/gdi_interface.cpp | 13 +- runtime/os_interface/windows/gdi_interface.h | 11 +- runtime/os_interface/windows/thk_wrapper.h | 6 + runtime/os_interface/windows/wddm/wddm.cpp | 23 ++- runtime/os_interface/windows/wddm/wddm.h | 9 +- runtime/os_interface/windows/wddm/wddm.inl | 3 + runtime/os_interface/windows/wddm/wddm23.cpp | 98 ++++++++++ runtime/os_interface/windows/wddm/wddm23.h | 41 +++++ .../os_interface/windows/wddm/wddm_create.cpp | 16 +- runtime/os_interface/windows/windows_defs.h | 10 +- unit_tests/CMakeLists.txt | 2 +- unit_tests/aub_tests/CMakeLists.txt | 2 +- unit_tests/mock_gdi/gdi32_mock.def | 6 + unit_tests/mock_gdi/mock_gdi.cpp | 37 ++++ unit_tests/mock_gdi/mock_gdi.h | 3 + unit_tests/mocks/mock_wddm20.cpp | 5 + unit_tests/mocks/mock_wddm20.h | 4 + unit_tests/mocks/mock_wddm23.h | 59 ++++++ unit_tests/mt_tests/CMakeLists.txt | 2 +- .../os_interface/windows/gdi_dll_fixture.h | 10 + .../os_interface/windows/wddm20_tests.cpp | 24 ++- .../os_interface/windows/wddm23_tests.cpp | 174 ++++++++++++++++++ .../os_interface/windows/wddm_create.cpp | 10 +- unit_tests/test_files/igdrcl.config | 1 - unit_tests/windows/wddm_create_tests.cpp | 32 +++- 27 files changed, 560 insertions(+), 44 deletions(-) create mode 100644 runtime/os_interface/windows/wddm/wddm23.cpp create mode 100644 runtime/os_interface/windows/wddm/wddm23.h create mode 100644 unit_tests/mocks/mock_wddm23.h create mode 100644 unit_tests/os_interface/windows/wddm23_tests.cpp diff --git a/runtime/dll/CMakeLists.txt b/runtime/dll/CMakeLists.txt index cd80bad86c..c0222019ec 100644 --- a/runtime/dll/CMakeLists.txt +++ b/runtime/dll/CMakeLists.txt @@ -56,7 +56,7 @@ set(RUNTIME_SRCS_DLL_WINDOWS ${IGDRCL_SOURCE_DIR}/runtime/gmm_helper/page_table_mngr.cpp ${IGDRCL_SOURCE_DIR}/runtime/os_interface/windows/sys_calls.cpp ${IGDRCL_SOURCE_DIR}/runtime/os_interface/windows/wddm/wddm_calls.cpp - ${IGDRCL_SOURCE_DIR}/runtime/os_interface/windows/wddm${BRANCH_DIR_SUFFIX}/wddm_create.cpp + ${IGDRCL_SOURCE_DIR}/runtime/os_interface/windows/wddm/wddm_create.cpp ) target_sources(${NEO_DYNAMIC_LIB_NAME} PRIVATE ${RUNTIME_SRCS_DLL_BASE}) diff --git a/runtime/os_interface/DebugVariables.inl b/runtime/os_interface/DebugVariables.inl index 772e01cb1c..a4463e174a 100644 --- a/runtime/os_interface/DebugVariables.inl +++ b/runtime/os_interface/DebugVariables.inl @@ -87,7 +87,6 @@ DECLARE_DEBUG_VARIABLE(int32_t, CsrDispatchMode, 0, "Chooses DispatchMode for Cs /*DRIVER TOGGLES*/ DECLARE_DEBUG_VARIABLE(int32_t, ForceOCLVersion, 0, "Force specific OpenCL API version") DECLARE_DEBUG_VARIABLE(int32_t, ForcePreemptionMode, -1, "Keep this variable in sync with PreemptionMode enum. -1 - devices default mode, 1 - disable, 2 - midBatch, 3 - threadGroup, 4 - midThread") -DECLARE_DEBUG_VARIABLE(int32_t, ForceWddmInterfaceVersion, 0, "Windows only. Force internal interface version. 0 is default value. Example: set 20 to force 2.0") DECLARE_DEBUG_VARIABLE(int32_t, NodeOrdinal, -1, "-1: default do not override, 0: ENGINE_RCS") DECLARE_DEBUG_VARIABLE(int32_t, OverrideThreadArbitrationPolicy, -1, "-1 (dont override) or any valid config (0: Age Based, 1: Round Robin)") DECLARE_DEBUG_VARIABLE(bool, HwQueueSupported, false, "Windows only. Pass flag to KMD during Wddm Context creation") diff --git a/runtime/os_interface/windows/gdi_interface.cpp b/runtime/os_interface/windows/gdi_interface.cpp index 0eac5b3445..25df2fd118 100644 --- a/runtime/os_interface/windows/gdi_interface.cpp +++ b/runtime/os_interface/windows/gdi_interface.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * 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"), @@ -31,6 +31,17 @@ Gdi::Gdi() : gdiDll(Os::gdiDllName), } } +bool Gdi::setupHwQueueProcAddresses() { + createHwQueue = reinterpret_cast(gdiDll.getProcAddress("D3DKMTCreateHwQueue")); + destroyHwQueue = reinterpret_cast(gdiDll.getProcAddress("D3DKMTDestroyHwQueue")); + submitCommandToHwQueue = reinterpret_cast(gdiDll.getProcAddress("D3DKMTSubmitCommandToHwQueue")); + + if (!createHwQueue || !destroyHwQueue || !submitCommandToHwQueue) { + return false; + } + return true; +} + bool Gdi::getAllProcAddresses() { openAdapterFromHdc = reinterpret_cast(gdiDll.getProcAddress("D3DKMTOpenAdapterFromHdc")); openAdapterFromLuid = reinterpret_cast(gdiDll.getProcAddress("D3DKMTOpenAdapterFromLuid")); diff --git a/runtime/os_interface/windows/gdi_interface.h b/runtime/os_interface/windows/gdi_interface.h index e1afb9e69b..c4c8d31730 100644 --- a/runtime/os_interface/windows/gdi_interface.h +++ b/runtime/os_interface/windows/gdi_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Intel Corporation + * 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"), @@ -79,6 +79,11 @@ class Gdi { ThkWrapper registerTrimNotification; ThkWrapper unregisterTrimNotification; + // HW queue + ThkWrapper createHwQueue; + ThkWrapper destroyHwQueue; + ThkWrapper submitCommandToHwQueue; + // For debug purposes ThkWrapper getDeviceState; @@ -86,8 +91,10 @@ class Gdi { return initialized; } + MOCKABLE_VIRTUAL bool setupHwQueueProcAddresses(); + protected: - virtual bool getAllProcAddresses(); + MOCKABLE_VIRTUAL bool getAllProcAddresses(); bool initialized; private: diff --git a/runtime/os_interface/windows/thk_wrapper.h b/runtime/os_interface/windows/thk_wrapper.h index 2b79615aba..2f3606d8a1 100644 --- a/runtime/os_interface/windows/thk_wrapper.h +++ b/runtime/os_interface/windows/thk_wrapper.h @@ -72,6 +72,9 @@ enum SystemCallsIds { SYSTIMER_ID_UNREGISTERTRIMNOTIFICATION = 44, SYSTIMER_ID_QUERYRESOURCEINFOFROMNTHANDLE = 45, SYSTIMER_ID_OPENRESOURCEFROMNTHANDLE = 46, + SYSTIMER_ID_CREATEHWQUEUE = 47, + SYSTIMER_ID_DESTROYHWQUEUE = 48, + SYSTIMER_ID_SUBMITCOMMANDTOHWQUEUE = 49, SYSTIMER_ID_SLEEP_0 = 100, SYSTIMER_ID_WAIT_FOR_KMD = 200, @@ -172,5 +175,8 @@ class ThkWrapper { GET_ID(D3DKMT_UNREGISTERTRIMNOTIFICATION *, SYSTIMER_ID_UNREGISTERTRIMNOTIFICATION) GET_ID(D3DKMT_OPENRESOURCEFROMNTHANDLE *, SYSTIMER_ID_OPENRESOURCEFROMNTHANDLE) GET_ID(D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE *, SYSTIMER_ID_QUERYRESOURCEINFOFROMNTHANDLE) + GET_ID(D3DKMT_CREATEHWQUEUE *, SYSTIMER_ID_CREATEHWQUEUE) + GET_ID(CONST D3DKMT_DESTROYHWQUEUE *, SYSTIMER_ID_DESTROYHWQUEUE) + GET_ID(CONST D3DKMT_SUBMITCOMMANDTOHWQUEUE *, SYSTIMER_ID_SUBMITCOMMANDTOHWQUEUE) }; } // namespace OCLRT diff --git a/runtime/os_interface/windows/wddm/wddm.cpp b/runtime/os_interface/windows/wddm/wddm.cpp index 0fbeef81fd..1548e131ea 100644 --- a/runtime/os_interface/windows/wddm/wddm.cpp +++ b/runtime/os_interface/windows/wddm/wddm.cpp @@ -62,8 +62,7 @@ Wddm::Wddm() : initialized(false), pagingFenceAddress(nullptr), currentPagingFenceValue(0), hwContextId(0), - trimCallbackHandle(nullptr), - wddmInterfaceVersion(WddmInterfaceVersion::Wddm20) { + trimCallbackHandle(nullptr) { featureTable.reset(new FeatureTable()); waTable.reset(new WorkaroundTable()); gtSystemInfo.reset(new GT_SYSTEM_INFO); @@ -235,12 +234,9 @@ bool Wddm::createMonitoredFence() { DEBUG_BREAK_IF(STATUS_SUCCESS != Status); - monitoredFence.currentFenceValue = 1; - monitoredFence.fenceHandle = CreateSynchronizationObject.hSyncObject; - monitoredFence.cpuAddress = reinterpret_cast(CreateSynchronizationObject.Info.MonitoredFence.FenceValueCPUVirtualAddress); - monitoredFence.lastSubmittedFence = 0; - - monitoredFence.gpuAddress = CreateSynchronizationObject.Info.MonitoredFence.FenceValueGPUVirtualAddress; + resetMonitoredFenceParams(CreateSynchronizationObject.hSyncObject, + reinterpret_cast(CreateSynchronizationObject.Info.MonitoredFence.FenceValueCPUVirtualAddress), + CreateSynchronizationObject.Info.MonitoredFence.FenceValueGPUVirtualAddress); return Status == STATUS_SUCCESS; } @@ -728,7 +724,7 @@ bool Wddm::createContext() { CreateContext.EngineAffinity = 0; CreateContext.Flags.NullRendering = static_cast(DebugManager.flags.EnableNullHardware.get()); - CreateContext.Flags.HwQueueSupported = static_cast(DebugManager.flags.HwQueueSupported.get()); + CreateContext.Flags.HwQueueSupported = hwQueuesSupported(); if (preemptionMode >= PreemptionMode::MidBatch) { CreateContext.Flags.DisableGpuTimeout = readEnablePreemptionRegKey(); @@ -951,8 +947,17 @@ bool Wddm::reserveValidAddressRange(size_t size, void *&reservedMem) { void *Wddm::virtualAlloc(void *inPtr, size_t size, unsigned long flags, unsigned long type) { return virtualAllocFnc(inPtr, size, flags, type); } + int Wddm::virtualFree(void *ptr, size_t size, unsigned long flags) { return virtualFreeFnc(ptr, size, flags); } +void Wddm::resetMonitoredFenceParams(D3DKMT_HANDLE &handle, uint64_t *cpuAddress, D3DGPU_VIRTUAL_ADDRESS &gpuAddress) { + monitoredFence.lastSubmittedFence = 0; + monitoredFence.currentFenceValue = 1; + monitoredFence.fenceHandle = handle; + monitoredFence.cpuAddress = cpuAddress; + monitoredFence.gpuAddress = gpuAddress; +} + } // namespace OCLRT diff --git a/runtime/os_interface/windows/wddm/wddm.h b/runtime/os_interface/windows/wddm/wddm.h index 8352835c6b..1f79a095b7 100644 --- a/runtime/os_interface/windows/wddm/wddm.h +++ b/runtime/os_interface/windows/wddm/wddm.h @@ -51,6 +51,7 @@ struct KmDafListener; namespace WddmInterfaceVersion { constexpr uint32_t Wddm20 = 20; +constexpr uint32_t Wddm23 = 23; } // namespace WddmInterfaceVersion class Wddm { @@ -59,7 +60,6 @@ class Wddm { typedef void(WINAPI *GetSystemInfoFcn)(SYSTEM_INFO *pSystemInfo); typedef BOOL(WINAPI *VirtualFreeFcn)(LPVOID ptr, SIZE_T size, DWORD flags); typedef LPVOID(WINAPI *VirtualAllocFcn)(LPVOID inPtr, SIZE_T size, DWORD flags, DWORD type); - const uint32_t wddmInterfaceVersion; virtual ~Wddm(); @@ -72,6 +72,7 @@ class Wddm { bool mapGpuVirtualAddress(WddmAllocation *allocation, void *cpuPtr, uint64_t size, bool allocation32bit, bool use64kbPages, bool useHeap1); bool mapGpuVirtualAddress(AllocationStorageData *allocationStorageData, bool allocation32bit, bool use64kbPages); MOCKABLE_VIRTUAL bool createContext(); + virtual bool createHwQueue() { return false; } MOCKABLE_VIRTUAL bool freeGpuVirtualAddres(D3DGPU_VIRTUAL_ADDRESS &gpuPtr, uint64_t size); MOCKABLE_VIRTUAL NTSTATUS createAllocation(WddmAllocation *alloc); MOCKABLE_VIRTUAL bool createAllocation64k(WddmAllocation *alloc); @@ -87,7 +88,7 @@ class Wddm { MOCKABLE_VIRTUAL bool destroyContext(D3DKMT_HANDLE context); MOCKABLE_VIRTUAL bool queryAdapterInfo(); - MOCKABLE_VIRTUAL bool submit(uint64_t commandBuffer, size_t size, void *commandHeader); + virtual bool submit(uint64_t commandBuffer, size_t size, void *commandHeader); MOCKABLE_VIRTUAL bool waitOnGPU(); MOCKABLE_VIRTUAL bool waitFromCpu(uint64_t lastFenceValue); @@ -207,12 +208,14 @@ class Wddm { bool destroyPagingQueue(); bool destroyDevice(); bool closeAdapter(); - bool createMonitoredFence(); + virtual bool createMonitoredFence(); void getDeviceState(); void handleCompletion(); unsigned int readEnablePreemptionRegKey(); bool initGmmContext(); void destroyGmmContext(); + void resetMonitoredFenceParams(D3DKMT_HANDLE &handle, uint64_t *cpuAddress, D3DGPU_VIRTUAL_ADDRESS &gpuAddress); + virtual const bool hwQueuesSupported() const { return false; } static CreateDXGIFactoryFcn createDxgiFactory; static GetSystemInfoFcn getSystemInfo; diff --git a/runtime/os_interface/windows/wddm/wddm.inl b/runtime/os_interface/windows/wddm/wddm.inl index 04c82e65d6..d84716a934 100644 --- a/runtime/os_interface/windows/wddm/wddm.inl +++ b/runtime/os_interface/windows/wddm/wddm.inl @@ -61,6 +61,9 @@ bool Wddm::init() { if (!createContext()) { return false; } + if (hwQueuesSupported() && !createHwQueue()) { + return false; + } if (!createMonitoredFence()) { return false; } diff --git a/runtime/os_interface/windows/wddm/wddm23.cpp b/runtime/os_interface/windows/wddm/wddm23.cpp new file mode 100644 index 0000000000..8f4ce58afc --- /dev/null +++ b/runtime/os_interface/windows/wddm/wddm23.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 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: + * + * 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. + */ + +#include "runtime/os_interface/windows/gdi_interface.h" +#include "runtime/os_interface/windows/wddm/wddm23.h" + +namespace OCLRT { +Wddm23::Wddm23() : Wddm20() {} + +Wddm23::~Wddm23() { + destroyHwQueue(); +} + +bool Wddm23::createHwQueue() { + D3DKMT_CREATEHWQUEUE createHwQueue = {}; + + if (!gdi->setupHwQueueProcAddresses()) { + return false; + } + + createHwQueue.hHwContext = context; + if (preemptionMode >= PreemptionMode::MidBatch) { + createHwQueue.Flags.DisableGpuTimeout = readEnablePreemptionRegKey(); + } + + auto status = gdi->createHwQueue(&createHwQueue); + UNRECOVERABLE_IF(status != STATUS_SUCCESS); + hwQueueHandle = createHwQueue.hHwQueue; + + resetMonitoredFenceParams(createHwQueue.hHwQueueProgressFence, + reinterpret_cast(createHwQueue.HwQueueProgressFenceCPUVirtualAddress), + createHwQueue.HwQueueProgressFenceGPUVirtualAddress); + + return status == STATUS_SUCCESS; +} + +void Wddm23::destroyHwQueue() { + if (hwQueueHandle) { + D3DKMT_DESTROYHWQUEUE destroyHwQueue = {}; + destroyHwQueue.hHwQueue = hwQueueHandle; + + auto status = gdi->destroyHwQueue(&destroyHwQueue); + DEBUG_BREAK_IF(status != STATUS_SUCCESS); + } +} + +bool Wddm23::submit(uint64_t commandBuffer, size_t size, void *commandHeader) { + D3DKMT_SUBMITCOMMANDTOHWQUEUE submitCommand = {}; + submitCommand.hHwQueue = hwQueueHandle; + submitCommand.HwQueueProgressFenceId = monitoredFence.fenceHandle; + 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 = sizeof(COMMAND_BUFFER_HEADER); + + if (currentPagingFenceValue > *pagingFenceAddress && !waitOnGPU()) { + return false; + } + + DBG_LOG(ResidencyDebugEnable, "Residency:", __FUNCTION__, "currentFenceValue =", monitoredFence.currentFenceValue); + + auto status = gdi->submitCommandToHwQueue(&submitCommand); + UNRECOVERABLE_IF(status != STATUS_SUCCESS); + + if (STATUS_SUCCESS == status) { + monitoredFence.lastSubmittedFence = monitoredFence.currentFenceValue; + monitoredFence.currentFenceValue++; + } + + getDeviceState(); + + return status == STATUS_SUCCESS; +} +} // namespace OCLRT diff --git a/runtime/os_interface/windows/wddm/wddm23.h b/runtime/os_interface/windows/wddm/wddm23.h new file mode 100644 index 0000000000..1fb38abafc --- /dev/null +++ b/runtime/os_interface/windows/wddm/wddm23.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 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: + * + * 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. + */ + +#pragma once +#include "runtime/os_interface/windows/wddm/wddm.h" + +namespace OCLRT { +class Wddm23 : public Wddm20 { + protected: + friend Wddm20; + Wddm23(); + ~Wddm23(); + + bool createHwQueue() override; + void destroyHwQueue(); + bool createMonitoredFence() override { return true; } + const bool hwQueuesSupported() const override { return true; } + bool submit(uint64_t commandBuffer, size_t size, void *commandHeader) override; + + D3DKMT_HANDLE hwQueueHandle = 0; +}; +} // namespace OCLRT diff --git a/runtime/os_interface/windows/wddm/wddm_create.cpp b/runtime/os_interface/windows/wddm/wddm_create.cpp index 8f05c0c3db..eb93d62a50 100644 --- a/runtime/os_interface/windows/wddm/wddm_create.cpp +++ b/runtime/os_interface/windows/wddm/wddm_create.cpp @@ -20,10 +20,24 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include "runtime/os_interface/debug_settings_manager.h" #include "runtime/os_interface/windows/wddm/wddm.h" +#include "runtime/os_interface/windows/wddm/wddm23.h" namespace OCLRT { Wddm *Wddm::createWddm(uint32_t interfaceVersion) { - return new Wddm20(); + if (DebugManager.flags.HwQueueSupported.get()) { + interfaceVersion = WddmInterfaceVersion::Wddm23; + } + + switch (interfaceVersion) { + case WddmInterfaceVersion::Wddm20: + return new Wddm20(); + case WddmInterfaceVersion::Wddm23: + return new Wddm23(); + default: + UNRECOVERABLE_IF(true); + return nullptr; + } } } // namespace OCLRT diff --git a/runtime/os_interface/windows/windows_defs.h b/runtime/os_interface/windows/windows_defs.h index 27b6144b73..406a06f05d 100644 --- a/runtime/os_interface/windows/windows_defs.h +++ b/runtime/os_interface/windows/windows_defs.h @@ -30,11 +30,11 @@ namespace OCLRT { constexpr uintptr_t windowsMinAddress = 0x200000; struct MonitoredFence { - D3DKMT_HANDLE fenceHandle; - D3DGPU_VIRTUAL_ADDRESS gpuAddress; - volatile uint64_t *cpuAddress; - volatile uint64_t currentFenceValue; - uint64_t lastSubmittedFence; + D3DKMT_HANDLE fenceHandle = 0; + D3DGPU_VIRTUAL_ADDRESS gpuAddress = 0; + volatile uint64_t *cpuAddress = nullptr; + volatile uint64_t currentFenceValue = 0; + uint64_t lastSubmittedFence = 0; }; } // namespace OCLRT diff --git a/unit_tests/CMakeLists.txt b/unit_tests/CMakeLists.txt index c747e3ece9..f4471415f0 100644 --- a/unit_tests/CMakeLists.txt +++ b/unit_tests/CMakeLists.txt @@ -32,7 +32,7 @@ set(IGDRCL_SRCS_tests_local ) if(WIN32) - list(APPEND IGDRCL_SRCS_tests_local ${IGDRCL_SOURCE_DIR}/unit_tests/os_interface/windows${BRANCH_DIR_SUFFIX}/wddm_create.cpp) + list(APPEND IGDRCL_SRCS_tests_local ${IGDRCL_SOURCE_DIR}/unit_tests/os_interface/windows/wddm_create.cpp) endif() add_subdirectory(libult) diff --git a/unit_tests/aub_tests/CMakeLists.txt b/unit_tests/aub_tests/CMakeLists.txt index 0cd273eb07..b313abd8d0 100644 --- a/unit_tests/aub_tests/CMakeLists.txt +++ b/unit_tests/aub_tests/CMakeLists.txt @@ -49,7 +49,7 @@ target_sources(igdrcl_aub_tests PRIVATE if(WIN32) target_sources(igdrcl_aub_tests PRIVATE ${IGDRCL_SOURCE_DIR}/runtime/gmm_helper/gmm_memory.cpp - ${IGDRCL_SOURCE_DIR}/unit_tests/os_interface/windows${BRANCH_DIR_SUFFIX}/wddm_create.cpp + ${IGDRCL_SOURCE_DIR}/unit_tests/os_interface/windows/wddm_create.cpp ) endif() diff --git a/unit_tests/mock_gdi/gdi32_mock.def b/unit_tests/mock_gdi/gdi32_mock.def index b620f241e3..41e3629908 100644 --- a/unit_tests/mock_gdi/gdi32_mock.def +++ b/unit_tests/mock_gdi/gdi32_mock.def @@ -62,6 +62,9 @@ D3DKMTEvict D3DKMTGetDeviceState D3DKMTRegisterTrimNotification D3DKMTUnregisterTrimNotification +D3DKMTCreateHwQueue +D3DKMTDestroyHwQueue +D3DKMTSubmitCommandToHwQueue MockSetAdapterInfo MockSetSizes GetMockSizes @@ -74,3 +77,6 @@ getAdapterInfoAddress getLastCallMapGpuVaArg setMapGpuVaFailConfig getCreateContextData +getCreateHwQueueData +getDestroyHwQueueData +getSubmitCommandToHwQueueData diff --git a/unit_tests/mock_gdi/mock_gdi.cpp b/unit_tests/mock_gdi/mock_gdi.cpp index a431712719..46b1483e5d 100644 --- a/unit_tests/mock_gdi/mock_gdi.cpp +++ b/unit_tests/mock_gdi/mock_gdi.cpp @@ -387,6 +387,31 @@ NTSTATUS __stdcall D3DKMTCreateSynchronizationObject2(IN OUT D3DKMT_CREATESYNCHR return STATUS_SUCCESS; } +static D3DKMT_CREATEHWQUEUE createHwQueueData = {}; + +NTSTATUS __stdcall D3DKMTCreateHwQueue(IN OUT D3DKMT_CREATEHWQUEUE *createHwQueue) { + createHwQueue->hHwQueueProgressFence = 1; + createHwQueue->HwQueueProgressFenceCPUVirtualAddress = reinterpret_cast(2); + createHwQueue->HwQueueProgressFenceGPUVirtualAddress = 3; + createHwQueue->hHwQueue = 4; + createHwQueueData = *createHwQueue; + return STATUS_SUCCESS; +} + +static D3DKMT_DESTROYHWQUEUE destroyHwQueueData = {}; + +NTSTATUS __stdcall D3DKMTDestroyHwQueue(IN CONST D3DKMT_DESTROYHWQUEUE *destroyHwQueue) { + destroyHwQueueData = *destroyHwQueue; + return STATUS_SUCCESS; +} + +static D3DKMT_SUBMITCOMMANDTOHWQUEUE submitCommandToHwQueueData = {}; + +NTSTATUS __stdcall D3DKMTSubmitCommandToHwQueue(IN CONST D3DKMT_SUBMITCOMMANDTOHWQUEUE *submitCommandToHwQueue) { + submitCommandToHwQueueData = *submitCommandToHwQueue; + return STATUS_SUCCESS; +} + #ifdef __cplusplus } #endif @@ -441,3 +466,15 @@ void setMapGpuVaFailConfig(uint32_t count, uint32_t max) { D3DKMT_CREATECONTEXTVIRTUAL *getCreateContextData() { return &createContextData; } + +D3DKMT_CREATEHWQUEUE *getCreateHwQueueData() { + return &createHwQueueData; +} + +D3DKMT_DESTROYHWQUEUE *getDestroyHwQueueData() { + return &destroyHwQueueData; +} + +D3DKMT_SUBMITCOMMANDTOHWQUEUE *getSubmitCommandToHwQueueData() { + return &submitCommandToHwQueueData; +} diff --git a/unit_tests/mock_gdi/mock_gdi.h b/unit_tests/mock_gdi/mock_gdi.h index c0ceab7f04..ef09ba3ebc 100644 --- a/unit_tests/mock_gdi/mock_gdi.h +++ b/unit_tests/mock_gdi/mock_gdi.h @@ -83,3 +83,6 @@ ADAPTER_INFO *getAdapterInfoAddress(); D3DDDI_MAPGPUVIRTUALADDRESS *getLastCallMapGpuVaArg(); void setMapGpuVaFailConfig(uint32_t count, uint32_t max); D3DKMT_CREATECONTEXTVIRTUAL *getCreateContextData(); +D3DKMT_CREATEHWQUEUE *getCreateHwQueueData(); +D3DKMT_DESTROYHWQUEUE *getDestroyHwQueueData(); +D3DKMT_SUBMITCOMMANDTOHWQUEUE *getSubmitCommandToHwQueueData(); diff --git a/unit_tests/mocks/mock_wddm20.cpp b/unit_tests/mocks/mock_wddm20.cpp index f779fd568e..d5f9100d37 100644 --- a/unit_tests/mocks/mock_wddm20.cpp +++ b/unit_tests/mocks/mock_wddm20.cpp @@ -125,6 +125,11 @@ bool WddmMock::createContext() { return createContextResult.success = Wddm::createContext(); } +bool WddmMock::createHwQueue() { + createHwQueueResult.called++; + return createHwQueueResult.success = Wddm::createHwQueue(); +} + bool WddmMock::destroyContext(D3DKMT_HANDLE context) { destroyContextResult.called++; return destroyContextResult.success = Wddm::destroyContext(context); diff --git a/unit_tests/mocks/mock_wddm20.h b/unit_tests/mocks/mock_wddm20.h index 337c6ce4f9..bc7c36d24b 100644 --- a/unit_tests/mocks/mock_wddm20.h +++ b/unit_tests/mocks/mock_wddm20.h @@ -49,11 +49,13 @@ class WddmMock : public Wddm20 { public: using Wddm::adapter; using Wddm::context; + using Wddm::createHwQueue; using Wddm::createMonitoredFence; using Wddm::device; using Wddm::gdi; using Wddm::getSystemInfo; using Wddm::gmmMemory; + using Wddm::hwQueuesSupported; using Wddm::pagingQueue; WddmMock() : Wddm20(){}; @@ -69,6 +71,7 @@ class WddmMock : public Wddm20 { bool destroyAllocation(WddmAllocation *alloc); bool openSharedHandle(D3DKMT_HANDLE handle, WddmAllocation *alloc) override; bool createContext() override; + bool createHwQueue() override; bool destroyContext(D3DKMT_HANDLE context) override; bool queryAdapterInfo() override; bool submit(uint64_t commandBuffer, size_t size, void *commandHeader) override; @@ -118,6 +121,7 @@ class WddmMock : public Wddm20 { WddmMockHelpers::CallResult waitFromCpuResult; WddmMockHelpers::CallResult releaseReservedAddressResult; WddmMockHelpers::CallResult reserveValidAddressRangeResult; + WddmMockHelpers::CallResult createHwQueueResult; NTSTATUS createAllocationStatus; bool mapGpuVaStatus; diff --git a/unit_tests/mocks/mock_wddm23.h b/unit_tests/mocks/mock_wddm23.h new file mode 100644 index 0000000000..8287f48055 --- /dev/null +++ b/unit_tests/mocks/mock_wddm23.h @@ -0,0 +1,59 @@ +/* +* Copyright (c) 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: +* +* 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. +*/ + +#pragma once + +#include "runtime/os_interface/windows/wddm/wddm23.h" + +namespace OCLRT { +class WddmMock23 : public Wddm23 { + public: + using Wddm23::context; + using Wddm23::createHwQueue; + using Wddm23::createMonitoredFence; + using Wddm23::currentPagingFenceValue; + using Wddm23::destroyHwQueue; + using Wddm23::gdi; + using Wddm23::hwQueueHandle; + using Wddm23::hwQueuesSupported; + using Wddm23::pagingFenceAddress; + using Wddm23::submit; + + WddmMock23() : Wddm23(){}; + + bool waitOnGPU() override { + waitOnGPUCalled++; + return true; + } + + bool createHwQueue() override { + createHwQueueCalled++; + createHwQueueResult = forceCreateHwQueueFail ? false : Wddm23::createHwQueue(); + return createHwQueueResult; + } + + uint32_t waitOnGPUCalled = 0; + uint32_t createHwQueueCalled = 0; + bool forceCreateHwQueueFail = false; + bool createHwQueueResult = false; +}; +} // namespace OCLRT diff --git a/unit_tests/mt_tests/CMakeLists.txt b/unit_tests/mt_tests/CMakeLists.txt index 23ca4c231d..9f5511080b 100644 --- a/unit_tests/mt_tests/CMakeLists.txt +++ b/unit_tests/mt_tests/CMakeLists.txt @@ -44,7 +44,7 @@ target_link_libraries(igdrcl_mt_tests igdrcl_mocks ${IGDRCL_EXTRA_LIBS}) if(WIN32) target_sources(igdrcl_mt_tests PRIVATE - ${IGDRCL_SOURCE_DIR}/unit_tests/os_interface/windows${BRANCH_DIR_SUFFIX}/wddm_create.cpp + ${IGDRCL_SOURCE_DIR}/unit_tests/os_interface/windows/wddm_create.cpp ) endif() diff --git a/unit_tests/os_interface/windows/gdi_dll_fixture.h b/unit_tests/os_interface/windows/gdi_dll_fixture.h index ffef0950a5..4ac3f81679 100644 --- a/unit_tests/os_interface/windows/gdi_dll_fixture.h +++ b/unit_tests/os_interface/windows/gdi_dll_fixture.h @@ -51,10 +51,17 @@ struct GdiDllFixture { setMapGpuVaFailConfigFcn = reinterpret_cast(mockGdiDll->getProcAddress("setMapGpuVaFailConfig")); setMapGpuVaFailConfigFcn(0, 0); getCreateContextDataFcn = reinterpret_cast(mockGdiDll->getProcAddress("getCreateContextData")); + getCreateHwQueueDataFcn = reinterpret_cast(mockGdiDll->getProcAddress("getCreateHwQueueData")); + getDestroyHwQueueDataFcn = reinterpret_cast(mockGdiDll->getProcAddress("getDestroyHwQueueData")); + getSubmitCommandToHwQueueDataFcn = + reinterpret_cast(mockGdiDll->getProcAddress("getSubmitCommandToHwQueueData")); setMockLastDestroyedResHandleFcn((D3DKMT_HANDLE)0); } virtual void TearDown() { + *getCreateHwQueueDataFcn() = {}; + *getDestroyHwQueueDataFcn() = {}; + *getSubmitCommandToHwQueueDataFcn() = {}; setMapGpuVaFailConfigFcn(0, 0); } @@ -71,4 +78,7 @@ struct GdiDllFixture { decltype(&getLastCallMapGpuVaArg) getLastCallMapGpuVaArgFcn = nullptr; decltype(&setMapGpuVaFailConfig) setMapGpuVaFailConfigFcn = nullptr; decltype(&getCreateContextData) getCreateContextDataFcn = nullptr; + decltype(&getCreateHwQueueData) getCreateHwQueueDataFcn = nullptr; + decltype(&getDestroyHwQueueData) getDestroyHwQueueDataFcn = nullptr; + decltype(&getSubmitCommandToHwQueueData) getSubmitCommandToHwQueueDataFcn = nullptr; }; diff --git a/unit_tests/os_interface/windows/wddm20_tests.cpp b/unit_tests/os_interface/windows/wddm20_tests.cpp index 8ddff5693d..f531b7377b 100644 --- a/unit_tests/os_interface/windows/wddm20_tests.cpp +++ b/unit_tests/os_interface/windows/wddm20_tests.cpp @@ -667,20 +667,26 @@ HWTEST_F(Wddm20WithMockGdiDllTests, givenUseNoRingFlushesKmdModeDebugFlagToTrueW EXPECT_TRUE(!!privateData->NoRingFlushes); } -HWTEST_F(Wddm20WithMockGdiDllTests, givenHwQueueSupportEnabledWhenCreateContextIsCalledThenSetAppropriateFlag) { - DebugManagerStateRestore dbgRestore; - DebugManager.flags.HwQueueSupported.set(true); - +HWTEST_F(Wddm20WithMockGdiDllTests, whenCreateContextIsCalledThenDisableHwQueues) { wddm->init(); - EXPECT_EQ(1u, getCreateContextDataFcn()->Flags.HwQueueSupported); + EXPECT_FALSE(wddm->hwQueuesSupported()); + EXPECT_EQ(0u, getCreateContextDataFcn()->Flags.HwQueueSupported); } -HWTEST_F(Wddm20WithMockGdiDllTests, givenHwQueueSupportDisabledWhenCreateContextIsCalledThenSetAppropriateFlag) { - DebugManagerStateRestore dbgRestore; - DebugManager.flags.HwQueueSupported.set(false); +TEST_F(Wddm20Tests, whenCreateHwQueueIsCalledThenAlwaysReturnFalse) { + EXPECT_FALSE(wddm->createHwQueue()); +} +HWTEST_F(Wddm20Tests, whenInitCalledThenDontCallToCreateHwQueue) { wddm->init(); - EXPECT_EQ(0u, getCreateContextDataFcn()->Flags.HwQueueSupported); + EXPECT_EQ(0u, wddm->createHwQueueResult.called); +} + +HWTEST_F(Wddm20Tests, whenWddmIsInitializedThenGdiDoesntHaveHwQueueDDIs) { + wddm->init(); + EXPECT_EQ(nullptr, wddm->gdi->createHwQueue.mFunc); + EXPECT_EQ(nullptr, wddm->gdi->destroyHwQueue.mFunc); + EXPECT_EQ(nullptr, wddm->gdi->submitCommandToHwQueue.mFunc); } HWTEST_F(Wddm20Tests, givenDebugManagerWhenGetForUseNoRingFlushesKmdModeIsCalledThenTrueIsReturned) { diff --git a/unit_tests/os_interface/windows/wddm23_tests.cpp b/unit_tests/os_interface/windows/wddm23_tests.cpp new file mode 100644 index 0000000000..005ff60dd4 --- /dev/null +++ b/unit_tests/os_interface/windows/wddm23_tests.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 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: + * + * 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. + */ + +#include "runtime/os_interface/windows/gdi_interface.h" +#include "runtime/os_interface/windows/wddm/wddm23.h" +#include "unit_tests/mocks/mock_wddm23.h" +#include "unit_tests/os_interface/windows/gdi_dll_fixture.h" +#include "test.h" + +using namespace OCLRT; + +struct Wddm23Tests : public ::testing::Test, GdiDllFixture { + void SetUp() override { + GdiDllFixture::SetUp(); + wddm.reset(static_cast(Wddm::createWddm(WddmInterfaceVersion::Wddm23))); + } + + void TearDown() override { + GdiDllFixture::TearDown(); + } + + std::unique_ptr wddm; +}; + +TEST_F(Wddm23Tests, whenCreateMonitoredFenceCalledThenDoNothing) { + EXPECT_TRUE(wddm->createMonitoredFence()); + EXPECT_TRUE(nullptr == wddm->getMonitoredFence().cpuAddress); + EXPECT_EQ(0u, wddm->getMonitoredFence().currentFenceValue); + EXPECT_EQ(static_cast(0), wddm->getMonitoredFence().fenceHandle); + EXPECT_EQ(static_cast(0), wddm->getMonitoredFence().gpuAddress); + EXPECT_EQ(0u, wddm->getMonitoredFence().lastSubmittedFence); +} + +HWTEST_F(Wddm23Tests, whenCreateContextIsCalledThenEnableHwQueues) { + wddm->init(); + EXPECT_TRUE(wddm->hwQueuesSupported()); + EXPECT_EQ(1u, getCreateContextDataFcn()->Flags.HwQueueSupported); +} + +TEST_F(Wddm23Tests, whenCreateHwQueueIsCalledThenSetAllRequiredFieldsAndMonitoredFence) { + EXPECT_EQ(0u, wddm->hwQueueHandle); + wddm->context = 1; + + wddm->createHwQueue(); + + EXPECT_EQ(wddm->context, getCreateHwQueueDataFcn()->hHwContext); + EXPECT_EQ(0u, getCreateHwQueueDataFcn()->PrivateDriverDataSize); + EXPECT_EQ(nullptr, getCreateHwQueueDataFcn()->pPrivateDriverData); + + EXPECT_TRUE(nullptr != wddm->getMonitoredFence().cpuAddress); + EXPECT_EQ(1u, wddm->getMonitoredFence().currentFenceValue); + EXPECT_NE(static_cast(0), wddm->getMonitoredFence().fenceHandle); + EXPECT_NE(static_cast(0), wddm->getMonitoredFence().gpuAddress); + EXPECT_EQ(0u, wddm->getMonitoredFence().lastSubmittedFence); +} + +TEST_F(Wddm23Tests, givenPreemptionModeWhenCreateHwQueueCalledThenSetGpuTimeoutIfEnabled) { + wddm->setPreemptionMode(PreemptionMode::Disabled); + wddm->createHwQueue(); + EXPECT_EQ(0u, getCreateHwQueueDataFcn()->Flags.DisableGpuTimeout); + + wddm->setPreemptionMode(PreemptionMode::MidBatch); + wddm->createHwQueue(); + EXPECT_EQ(1u, getCreateHwQueueDataFcn()->Flags.DisableGpuTimeout); +} + +HWTEST_F(Wddm23Tests, whenDestroyHwQueueCalledThenPassExistingHandle) { + wddm->init(); + wddm->hwQueueHandle = 123; + wddm->destroyHwQueue(); + EXPECT_EQ(wddm->hwQueueHandle, getDestroyHwQueueDataFcn()->hHwQueue); + + wddm->hwQueueHandle = 0; + wddm->destroyHwQueue(); + EXPECT_NE(wddm->hwQueueHandle, getDestroyHwQueueDataFcn()->hHwQueue); // gdi not called when 0 +} + +HWTEST_F(Wddm23Tests, whenObjectIsDestructedThenDestroyHwQueue) { + wddm->init(); + D3DKMT_HANDLE hwQueue = 123; + wddm->hwQueueHandle = hwQueue; + wddm.reset(nullptr); + EXPECT_EQ(hwQueue, getDestroyHwQueueDataFcn()->hHwQueue); +} + +HWTEST_F(Wddm23Tests, givenCmdBufferWhenSubmitCalledThenSetAllRequiredFiledsAndUpdateMonitoredFence) { + wddm->init(); + uint64_t cmdBufferAddress = 123; + size_t cmdSize = 456; + COMMAND_BUFFER_HEADER cmdBufferHeader = {}; + + EXPECT_EQ(1u, wddm->getMonitoredFence().currentFenceValue); + EXPECT_EQ(0u, wddm->getMonitoredFence().lastSubmittedFence); + + wddm->submit(cmdBufferAddress, cmdSize, &cmdBufferHeader); + + EXPECT_EQ(cmdBufferAddress, getSubmitCommandToHwQueueDataFcn()->CommandBuffer); + EXPECT_EQ(static_cast(cmdSize), getSubmitCommandToHwQueueDataFcn()->CommandLength); + EXPECT_EQ(wddm->hwQueueHandle, getSubmitCommandToHwQueueDataFcn()->hHwQueue); + EXPECT_EQ(wddm->getMonitoredFence().fenceHandle, getSubmitCommandToHwQueueDataFcn()->HwQueueProgressFenceId); + EXPECT_EQ(&cmdBufferHeader, getSubmitCommandToHwQueueDataFcn()->pPrivateDriverData); + EXPECT_EQ(static_cast(sizeof(COMMAND_BUFFER_HEADER)), getSubmitCommandToHwQueueDataFcn()->PrivateDriverDataSize); + + EXPECT_EQ(wddm->getMonitoredFence().gpuAddress, cmdBufferHeader.MonitorFenceVA); + EXPECT_EQ(wddm->getMonitoredFence().lastSubmittedFence, cmdBufferHeader.MonitorFenceValue); + EXPECT_EQ(2u, wddm->getMonitoredFence().currentFenceValue); + EXPECT_EQ(1u, wddm->getMonitoredFence().lastSubmittedFence); +} + +HWTEST_F(Wddm23Tests, givenCurrentPendingFenceValueGreaterThanPendingFenceValueWhenSubmitCalledThenCallWaitOnGpu) { + wddm->init(); + uint64_t cmdBufferAddress = 123; + size_t cmdSize = 456; + COMMAND_BUFFER_HEADER cmdBufferHeader = {}; + + *wddm->pagingFenceAddress = 1; + wddm->currentPagingFenceValue = 1; + wddm->submit(cmdBufferAddress, cmdSize, &cmdBufferHeader); + EXPECT_EQ(0u, wddm->waitOnGPUCalled); + + wddm->currentPagingFenceValue = 2; + wddm->submit(cmdBufferAddress, cmdSize, &cmdBufferHeader); + EXPECT_EQ(1u, wddm->waitOnGPUCalled); +} + +HWTEST_F(Wddm23Tests, whenInitCalledThenInitializeNewGdiDDIsAndCallToCreateHwQueue) { + EXPECT_EQ(nullptr, wddm->gdi->createHwQueue.mFunc); + EXPECT_EQ(nullptr, wddm->gdi->destroyHwQueue.mFunc); + EXPECT_EQ(nullptr, wddm->gdi->submitCommandToHwQueue.mFunc); + + EXPECT_TRUE(wddm->init()); + EXPECT_EQ(1u, wddm->createHwQueueCalled); + + EXPECT_NE(nullptr, wddm->gdi->createHwQueue.mFunc); + EXPECT_NE(nullptr, wddm->gdi->destroyHwQueue.mFunc); + EXPECT_NE(nullptr, wddm->gdi->submitCommandToHwQueue.mFunc); +} + +HWTEST_F(Wddm23Tests, whenCreateHwQueueFailedThenReturnFalseFromInit) { + wddm->forceCreateHwQueueFail = true; + EXPECT_FALSE(wddm->init()); +} + +HWTEST_F(Wddm23Tests, givenFailureOnGdiInitializationWhenCreatingHwQueueThenReturnFailure) { + struct MyMockGdi : public Gdi { + bool setupHwQueueProcAddresses() override { + return false; + } + }; + wddm->gdi.reset(new MyMockGdi()); + + EXPECT_FALSE(wddm->init()); + EXPECT_EQ(1u, wddm->createHwQueueCalled); + EXPECT_FALSE(wddm->createHwQueueResult); +} diff --git a/unit_tests/os_interface/windows/wddm_create.cpp b/unit_tests/os_interface/windows/wddm_create.cpp index 7b86209398..548fcf5e7a 100644 --- a/unit_tests/os_interface/windows/wddm_create.cpp +++ b/unit_tests/os_interface/windows/wddm_create.cpp @@ -21,9 +21,17 @@ */ #include "unit_tests/mocks/mock_wddm20.h" +#include "unit_tests/mocks/mock_wddm23.h" namespace OCLRT { Wddm *Wddm::createWddm(uint32_t interfaceVersion) { - return new WddmMock20(); + switch (interfaceVersion) { + case WddmInterfaceVersion::Wddm20: + return new WddmMock20(); + case WddmInterfaceVersion::Wddm23: + return new WddmMock23(); + default: + return nullptr; + } } } // namespace OCLRT diff --git a/unit_tests/test_files/igdrcl.config b/unit_tests/test_files/igdrcl.config index 48acafb84e..6ae18fc793 100644 --- a/unit_tests/test_files/igdrcl.config +++ b/unit_tests/test_files/igdrcl.config @@ -62,5 +62,4 @@ FlattenBatchBufferForAUBDump = false PrintDispatchParameters = false AddPatchInfoCommentsForAUBDump = false HwQueueSupported = false -ForceWddmInterfaceVersion = 0 DisableZeroCopyForUseHostPtr = false \ No newline at end of file diff --git a/unit_tests/windows/wddm_create_tests.cpp b/unit_tests/windows/wddm_create_tests.cpp index 2aa5759c14..3e92295330 100644 --- a/unit_tests/windows/wddm_create_tests.cpp +++ b/unit_tests/windows/wddm_create_tests.cpp @@ -21,16 +21,34 @@ */ #include "runtime/os_interface/windows/wddm/wddm.h" +#include "runtime/os_interface/windows/wddm/wddm23.h" +#include "unit_tests/helpers/debug_manager_state_restore.h" #include "test.h" +#include + using namespace OCLRT; -TEST(wddmCreateTests, givenInputVersionWhenCreatingThenAlwaysUse20) { - std::unique_ptr wddm1(Wddm::createWddm(WddmInterfaceVersion::Wddm20)); - std::unique_ptr wddm2(Wddm::createWddm(21)); - std::unique_ptr wddm3(Wddm::createWddm(0)); +TEST(wddmCreateTests, givenInputVersionWhenCreatingThenCreateRequestedObject) { + std::unique_ptr wddm20(Wddm::createWddm(WddmInterfaceVersion::Wddm20)); + std::unique_ptr wddm23(Wddm::createWddm(WddmInterfaceVersion::Wddm23)); - EXPECT_EQ(WddmInterfaceVersion::Wddm20, wddm1->wddmInterfaceVersion); - EXPECT_EQ(WddmInterfaceVersion::Wddm20, wddm2->wddmInterfaceVersion); - EXPECT_EQ(WddmInterfaceVersion::Wddm20, wddm3->wddmInterfaceVersion); + EXPECT_EQ(typeid(*wddm20.get()), typeid(Wddm20)); + EXPECT_EQ(typeid(*wddm23.get()), typeid(Wddm23)); +} + +TEST(wddmCreateTests, givenInvalidInputVersionWhenCreatingThenThrowException) { + EXPECT_THROW(Wddm::createWddm(0), std::exception); + EXPECT_THROW(Wddm::createWddm(21), std::exception); + EXPECT_THROW(Wddm::createWddm(22), std::exception); + EXPECT_THROW(Wddm::createWddm(24), std::exception); +} + +TEST(wddmCreateTests, givenHwQueuesSupportedDebugVariableWhenCreatingThenForceWddm23) { + DebugManagerStateRestore restore; + DebugManager.flags.HwQueueSupported.set(true); + + std::unique_ptr wddm(Wddm::createWddm(WddmInterfaceVersion::Wddm20)); + + EXPECT_EQ(typeid(*wddm.get()), typeid(Wddm23)); }