From de72e91269cb16b487f1ea955307e17cffadc138 Mon Sep 17 00:00:00 2001 From: Krzysztof Sprzaczkowski Date: Tue, 6 May 2025 11:24:01 +0000 Subject: [PATCH] feature: Native GPU fence synchronization object implementation Related-To: NEO-10811 Signed-off-by: Krzysztof Sprzaczkowski --- CMakeLists.txt | 4 + .../windows/wddm_direct_submission.inl | 2 +- .../source/os_interface/linux/CMakeLists.txt | 4 +- .../definitions/gdi_interface_logging.inl | 6 + .../linux/wddm_linux/wddm_interface_extra.cpp | 16 ++ .../os_interface/windows/CMakeLists.txt | 3 + .../os_interface/windows/gdi_interface.cpp | 1 + .../os_interface/windows/gdi_interface.h | 3 + .../windows/gdi_interface_logging.cpp | 2 + .../definitions/gdi_interface_logging.inl | 14 ++ .../source/os_interface/windows/wddm/wddm.cpp | 8 +- .../source/os_interface/windows/wddm/wddm.h | 1 + .../os_interface/windows/wddm/wddm_defs.h | 5 +- .../windows/wddm/wddm_features_extra.cpp | 17 ++ .../windows/wddm/wddm_interface.cpp | 13 +- .../windows/wddm/wddm_interface.h | 15 +- .../windows/wddm/wddm_interface_extra.cpp | 30 +++ shared/test/common/mock_gdi/mock_gdi.cpp | 4 + shared/test/common/mock_gdi/mock_gdi.h | 3 + .../test/common/mock_gdi/mock_os_library.cpp | 3 + shared/test/common/mocks/CMakeLists.txt | 1 + .../test/common/mocks/mock_wddm_interface.h | 4 +- .../test/common/mocks/mock_wddm_interface20.h | 4 +- .../test/common/mocks/mock_wddm_interface32.h | 41 ++++ .../os_interface/wddm_linux/CMakeLists.txt | 1 + .../wddm_linux/wddm32_tests_extra.cpp | 15 ++ .../os_interface/windows/CMakeLists.txt | 4 +- .../os_interface/windows/wddm20_tests.cpp | 2 +- .../os_interface/windows/wddm23_tests.cpp | 4 +- .../os_interface/windows/wddm32_tests.cpp | 179 ++++++++++++++++++ .../os_interface/windows/wddm32_tests.h | 64 +++++++ .../windows/wddm32_tests_extra.cpp | 16 ++ 32 files changed, 468 insertions(+), 21 deletions(-) create mode 100644 shared/source/os_interface/linux/wddm_linux/definitions/gdi_interface_logging.inl create mode 100644 shared/source/os_interface/linux/wddm_linux/wddm_interface_extra.cpp create mode 100644 shared/source/os_interface/windows/wddm/definitions/gdi_interface_logging.inl create mode 100644 shared/source/os_interface/windows/wddm/wddm_features_extra.cpp create mode 100644 shared/source/os_interface/windows/wddm/wddm_interface_extra.cpp create mode 100644 shared/test/common/mocks/mock_wddm_interface32.h create mode 100644 shared/test/unit_test/os_interface/wddm_linux/wddm32_tests_extra.cpp create mode 100644 shared/test/unit_test/os_interface/windows/wddm32_tests.cpp create mode 100644 shared/test/unit_test/os_interface/windows/wddm32_tests.h create mode 100644 shared/test/unit_test/os_interface/windows/wddm32_tests_extra.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a11f884feb..98acc4353c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -927,6 +927,7 @@ include_directories(${NEO_SHARED_DIRECTORY}/kernel/definitions${BRANCH_DIR_SUFFI include_directories(${NEO_SHARED_DIRECTORY}/gen_common${BRANCH_DIR_SUFFIX}) if(WIN32) include_directories(${NEO_SHARED_DIRECTORY}/gmm_helper/windows/gmm_memory${BRANCH_DIR_SUFFIX}) + include_directories(${NEO_SHARED_DIRECTORY}/os_interface/windows/wddm/definitions) else() include_directories(${NEO_LINUX_KMD_HEADERS_DIR} ${NEO_SHARED_DIRECTORY}/gmm_helper/windows/gmm_memory @@ -934,6 +935,9 @@ else() if("${BRANCH_TYPE}" STREQUAL "") include_directories(${NEO_SOURCE_DIR}/third_party/uapi/prelim) endif() + if(NOT DISABLE_WDDM_LINUX) + include_directories(${NEO_SHARED_DIRECTORY}/os_interface/linux/wddm_linux/definitions) + endif() endif() include_directories(${NEO_SHARED_DIRECTORY}/helpers/definitions${BRANCH_DIR_SUFFIX}) include_directories(${NEO_SHARED_DIRECTORY}/memory_properties${BRANCH_DIR_SUFFIX}) diff --git a/shared/source/direct_submission/windows/wddm_direct_submission.inl b/shared/source/direct_submission/windows/wddm_direct_submission.inl index 46541b9dcd..3416a599a2 100644 --- a/shared/source/direct_submission/windows/wddm_direct_submission.inl +++ b/shared/source/direct_submission/windows/wddm_direct_submission.inl @@ -86,7 +86,7 @@ void WddmDirectSubmission::ensureRingCompletion() { template bool WddmDirectSubmission::allocateOsResources() { - bool ret = wddm->getWddmInterface()->createMonitoredFenceForDirectSubmission(ringFence, *this->osContextWin); + bool ret = wddm->getWddmInterface()->createFenceForDirectSubmission(ringFence, *this->osContextWin); perfLogResidencyVariadicLog(wddm->getResidencyLogger(), "ULLS resource allocation finished with: %d\n", ret); this->ringBufferEndCompletionTagData.tagAddress = this->semaphoreGpuVa + offsetof(RingSemaphoreData, tagAllocation); diff --git a/shared/source/os_interface/linux/CMakeLists.txt b/shared/source/os_interface/linux/CMakeLists.txt index 4f46f7ac24..8060ec1186 100644 --- a/shared/source/os_interface/linux/CMakeLists.txt +++ b/shared/source/os_interface/linux/CMakeLists.txt @@ -116,8 +116,10 @@ if(DISABLE_WDDM_LINUX) ) else() list(APPEND NEO_CORE_OS_INTERFACE_LINUX - ${CMAKE_CURRENT_SOURCE_DIR}/wddm_linux/sys_calls_win.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm_linux/compatible_driver_store.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/wddm_linux/definitions/gdi_interface_logging.inl + ${CMAKE_CURRENT_SOURCE_DIR}/wddm_linux/sys_calls_win.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/wddm_linux/wddm_interface_extra.cpp ) endif() diff --git a/shared/source/os_interface/linux/wddm_linux/definitions/gdi_interface_logging.inl b/shared/source/os_interface/linux/wddm_linux/definitions/gdi_interface_logging.inl new file mode 100644 index 0000000000..196735787e --- /dev/null +++ b/shared/source/os_interface/linux/wddm_linux/definitions/gdi_interface_logging.inl @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ diff --git a/shared/source/os_interface/linux/wddm_linux/wddm_interface_extra.cpp b/shared/source/os_interface/linux/wddm_linux/wddm_interface_extra.cpp new file mode 100644 index 0000000000..e7a3721f97 --- /dev/null +++ b/shared/source/os_interface/linux/wddm_linux/wddm_interface_extra.cpp @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/windows/wddm/wddm.h" +#include "shared/source/os_interface/windows/wddm/wddm_interface.h" + +using namespace NEO; + +bool WddmInterface32::createSyncObject(MonitoredFence &monitorFence) { + UNRECOVERABLE_IF(true); + return false; +} diff --git a/shared/source/os_interface/windows/CMakeLists.txt b/shared/source/os_interface/windows/CMakeLists.txt index cf0404f70c..bb7019d787 100644 --- a/shared/source/os_interface/windows/CMakeLists.txt +++ b/shared/source/os_interface/windows/CMakeLists.txt @@ -45,7 +45,9 @@ set(NEO_CORE_OS_INTERFACE_WINDOWS ${CMAKE_CURRENT_SOURCE_DIR}/wddm/adapter_factory_create_with_fallback.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm/adapter_factory_dxgi.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm/adapter_factory_dxgi.h + ${CMAKE_CURRENT_SOURCE_DIR}/wddm/definitions/gdi_interface_logging.inl ${CMAKE_CURRENT_SOURCE_DIR}/wddm/read_preemption_regkey.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/wddm/wddm_interface_extra.cpp ${CMAKE_CURRENT_SOURCE_DIR}/windows_inc.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm/${BRANCH_DIR_SUFFIX}/perf_wddm.cpp ) @@ -127,6 +129,7 @@ set(NEO_CORE_OS_INTERFACE_WDDM ${CMAKE_CURRENT_SOURCE_DIR}/sys_calls_wrapper.h ${CMAKE_CURRENT_SOURCE_DIR}/wddm${BRANCH_DIR_SUFFIX}/init_context_private_data.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm${BRANCH_DIR_SUFFIX}/wddm_debug_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/wddm${BRANCH_DIR_SUFFIX}/wddm_features_extra.cpp ) if(NOT WIN32 AND NOT DISABLE_WDDM_LINUX) diff --git a/shared/source/os_interface/windows/gdi_interface.cpp b/shared/source/os_interface/windows/gdi_interface.cpp index 05490d0c8e..c60738fc05 100644 --- a/shared/source/os_interface/windows/gdi_interface.cpp +++ b/shared/source/os_interface/windows/gdi_interface.cpp @@ -59,6 +59,7 @@ bool Gdi::getAllProcAddresses() { createSynchronizationObject = gdiDll->getProcAddress("D3DKMTCreateSynchronizationObject"); createSynchronizationObject2 = gdiDll->getProcAddress("D3DKMTCreateSynchronizationObject2"); destroySynchronizationObject = gdiDll->getProcAddress("D3DKMTDestroySynchronizationObject"); + createNativeFence = gdiDll->getProcAddress("D3DKMTCreateNativeFence"); signalSynchronizationObject = gdiDll->getProcAddress("D3DKMTSignalSynchronizationObject"); waitForSynchronizationObject = gdiDll->getProcAddress("D3DKMTWaitForSynchronizationObject"); waitForSynchronizationObjectFromCpu = gdiDll->getProcAddress("D3DKMTWaitForSynchronizationObjectFromCpu"); diff --git a/shared/source/os_interface/windows/gdi_interface.h b/shared/source/os_interface/windows/gdi_interface.h index c356904121..aba22fa2f4 100644 --- a/shared/source/os_interface/windows/gdi_interface.h +++ b/shared/source/os_interface/windows/gdi_interface.h @@ -13,6 +13,8 @@ #include +typedef struct _D3DKMT_CREATENATIVEFENCE D3DKMT_CREATENATIVEFENCE; + namespace NEO { #define DEFINE_THK_WRAPPER(TYPE, VAR) ThkWrapper VAR = ThkWrapper(this->profiler, #TYPE, this->gdiId++); @@ -46,6 +48,7 @@ class Gdi { DEFINE_THK_WRAPPER(IN OUT D3DKMT_CREATESYNCHRONIZATIONOBJECT *, createSynchronizationObject); DEFINE_THK_WRAPPER(IN OUT D3DKMT_CREATESYNCHRONIZATIONOBJECT2 *, createSynchronizationObject2); DEFINE_THK_WRAPPER(IN CONST D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *, destroySynchronizationObject); + DEFINE_THK_WRAPPER(IN OUT D3DKMT_CREATENATIVEFENCE *, createNativeFence); DEFINE_THK_WRAPPER(IN CONST D3DKMT_SIGNALSYNCHRONIZATIONOBJECT *, signalSynchronizationObject); DEFINE_THK_WRAPPER(IN CONST_FROM_WDK_10_0_18328_0 D3DKMT_WAITFORSYNCHRONIZATIONOBJECT *, waitForSynchronizationObject); DEFINE_THK_WRAPPER(IN CONST D3DKMT_WAITFORSYNCHRONIZATIONOBJECTFROMCPU *, waitForSynchronizationObjectFromCpu); diff --git a/shared/source/os_interface/windows/gdi_interface_logging.cpp b/shared/source/os_interface/windows/gdi_interface_logging.cpp index a414fd8b47..5fdbc86310 100644 --- a/shared/source/os_interface/windows/gdi_interface_logging.cpp +++ b/shared/source/os_interface/windows/gdi_interface_logging.cpp @@ -466,6 +466,8 @@ template void logExit(NTSTATUS status, CON template void logEnter(CONST D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *param); template void logExit(NTSTATUS status, CONST D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *param); +#include "gdi_interface_logging.inl" + } // namespace GdiLogging } // namespace NEO diff --git a/shared/source/os_interface/windows/wddm/definitions/gdi_interface_logging.inl b/shared/source/os_interface/windows/wddm/definitions/gdi_interface_logging.inl new file mode 100644 index 0000000000..fdd715dd1d --- /dev/null +++ b/shared/source/os_interface/windows/wddm/definitions/gdi_interface_logging.inl @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +template <> +void getEnterString(D3DKMT_CREATENATIVEFENCE *param, char *input, size_t size) { + snprintf_s(input, size, size, "D3DKMT_CREATENATIVEFENCE Info Type %u Info Flags 0x%x", param->Info.Type, param->Info.Flags.Value); +} + +template void logEnter(D3DKMT_CREATENATIVEFENCE *param); +template void logExit(NTSTATUS status, D3DKMT_CREATENATIVEFENCE *param); diff --git a/shared/source/os_interface/windows/wddm/wddm.cpp b/shared/source/os_interface/windows/wddm/wddm.cpp index dca8fd5010..d5980f9b0c 100644 --- a/shared/source/os_interface/windows/wddm/wddm.cpp +++ b/shared/source/os_interface/windows/wddm/wddm.cpp @@ -138,7 +138,10 @@ bool Wddm::init() { rootDeviceEnvironment.initGmm(); this->rootDeviceEnvironment.getGmmClientContext()->setHandleAllocator(this->hwDeviceId->getUmKmDataTranslator()->createGmmHandleAllocator()); - if (WddmVersion::wddm23 == getWddmVersion()) { + auto wddmVersion = getWddmVersion(); + if (WddmVersion::wddm32 == wddmVersion) { + wddmInterface = std::make_unique(*this); + } else if (WddmVersion::wddm23 == wddmVersion) { wddmInterface = std::make_unique(*this); } else { wddmInterface = std::make_unique(*this); @@ -1392,6 +1395,9 @@ void Wddm::updatePagingFenceValue(uint64_t newPagingFenceValue) { WddmVersion Wddm::getWddmVersion() { if (featureTable->flags.ftrWddmHwQueues) { + if (isNativeFenceAvailable()) { + return WddmVersion::wddm32; + } return WddmVersion::wddm23; } else { return WddmVersion::wddm20; diff --git a/shared/source/os_interface/windows/wddm/wddm.h b/shared/source/os_interface/windows/wddm/wddm.h index c832c5c309..42381e74ca 100644 --- a/shared/source/os_interface/windows/wddm/wddm.h +++ b/shared/source/os_interface/windows/wddm/wddm.h @@ -106,6 +106,7 @@ class Wddm : public DriverModel { MOCKABLE_VIRTUAL bool isShutdownInProgress(); MOCKABLE_VIRTUAL bool isDebugAttachAvailable(); + MOCKABLE_VIRTUAL bool isNativeFenceAvailable(); bool isGpuHangDetected(OsContext &osContext) override; diff --git a/shared/source/os_interface/windows/wddm/wddm_defs.h b/shared/source/os_interface/windows/wddm/wddm_defs.h index 222a9efefd..ec88230a11 100644 --- a/shared/source/os_interface/windows/wddm/wddm_defs.h +++ b/shared/source/os_interface/windows/wddm/wddm_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -20,6 +20,7 @@ struct WddmSubmitArguments { enum class WddmVersion : uint32_t { wddm20 = 0, - wddm23 + wddm23, + wddm32 }; } // namespace NEO diff --git a/shared/source/os_interface/windows/wddm/wddm_features_extra.cpp b/shared/source/os_interface/windows/wddm/wddm_features_extra.cpp new file mode 100644 index 0000000000..1d3b339b59 --- /dev/null +++ b/shared/source/os_interface/windows/wddm/wddm_features_extra.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/os_interface.h" +#include "shared/source/os_interface/windows/wddm/wddm.h" + +namespace NEO { + +bool Wddm::isNativeFenceAvailable() { + return false; +} + +} // namespace NEO diff --git a/shared/source/os_interface/windows/wddm/wddm_interface.cpp b/shared/source/os_interface/windows/wddm/wddm_interface.cpp index e721f28d44..b3bf5ebadd 100644 --- a/shared/source/os_interface/windows/wddm/wddm_interface.cpp +++ b/shared/source/os_interface/windows/wddm/wddm_interface.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2024 Intel Corporation + * Copyright (C) 2018-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -97,7 +97,7 @@ bool WddmInterface20::submit(uint64_t commandBuffer, size_t size, void *commandH return STATUS_SUCCESS == status; } -bool NEO::WddmInterface20::createMonitoredFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) { +bool NEO::WddmInterface20::createFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) { auto ret = WddmInterface::createMonitoredFence(monitorFence); monitorFence.currentFenceValue = 1; return ret; @@ -177,9 +177,9 @@ bool WddmInterface23::submit(uint64_t commandBuffer, size_t size, void *commandH return status == STATUS_SUCCESS; } -bool NEO::WddmInterface23::createMonitoredFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) { +bool NEO::WddmInterface23::createFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) { MonitoredFence monitorFenceForResidency{}; - auto ret = WddmInterface::createMonitoredFence(monitorFenceForResidency); + auto ret = createSyncObject(monitorFenceForResidency); auto &residencyController = osContext.getResidencyController(); auto lastSubmittedFence = residencyController.getMonitoredFence().lastSubmittedFence; auto currentFenceValue = residencyController.getMonitoredFence().currentFenceValue; @@ -198,3 +198,8 @@ bool NEO::WddmInterface23::createMonitoredFenceForDirectSubmission(MonitoredFenc return ret; } + +bool WddmInterface23::createSyncObject(MonitoredFence &monitorFence) { + auto ret = WddmInterface::createMonitoredFence(monitorFence); + return ret; +} diff --git a/shared/source/os_interface/windows/wddm/wddm_interface.h b/shared/source/os_interface/windows/wddm/wddm_interface.h index 3895ef17ec..d196d1154d 100644 --- a/shared/source/os_interface/windows/wddm/wddm_interface.h +++ b/shared/source/os_interface/windows/wddm/wddm_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2024 Intel Corporation + * Copyright (C) 2018-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -31,7 +31,7 @@ class WddmInterface { virtual void destroyMonitorFence(MonitoredFence &monitorFence) = 0; virtual bool hwQueuesSupported() = 0; virtual bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, WddmSubmitArguments &submitArguments) = 0; - virtual bool createMonitoredFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) = 0; + virtual bool createFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) = 0; Wddm &wddm; }; @@ -44,7 +44,7 @@ class WddmInterface20 : public WddmInterface { void destroyMonitorFence(MonitoredFence &monitorFence) override; bool hwQueuesSupported() override; bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, WddmSubmitArguments &submitArguments) override; - bool createMonitoredFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) override; + bool createFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) override; }; class WddmInterface23 : public WddmInterface { @@ -56,6 +56,13 @@ class WddmInterface23 : public WddmInterface { void destroyMonitorFence(MonitoredFence &monitorFence) override; bool hwQueuesSupported() override; bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, WddmSubmitArguments &submitArguments) override; - bool createMonitoredFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) override; + bool createFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) override; + virtual bool createSyncObject(MonitoredFence &monitorFence); +}; + +class WddmInterface32 : public WddmInterface23 { + public: + using WddmInterface23::WddmInterface23; + bool createSyncObject(MonitoredFence &monitorFence) override; }; } // namespace NEO diff --git a/shared/source/os_interface/windows/wddm/wddm_interface_extra.cpp b/shared/source/os_interface/windows/wddm/wddm_interface_extra.cpp new file mode 100644 index 0000000000..3aa6a75e1a --- /dev/null +++ b/shared/source/os_interface/windows/wddm/wddm_interface_extra.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/windows/gdi_interface.h" +#include "shared/source/os_interface/windows/wddm/wddm.h" +#include "shared/source/os_interface/windows/wddm/wddm_interface.h" + +using namespace NEO; + +bool WddmInterface32::createSyncObject(MonitoredFence &monitorFence) { + UNRECOVERABLE_IF(wddm.getGdi()->createNativeFence == nullptr); + NTSTATUS status = STATUS_SUCCESS; + D3DKMT_CREATENATIVEFENCE createNativeFenceObject = {0}; + createNativeFenceObject.hDevice = wddm.getDeviceHandle(); + createNativeFenceObject.Info.Type = D3DDDI_NATIVEFENCE_TYPE_DEFAULT; + createNativeFenceObject.Info.InitialFenceValue = 0; + + status = wddm.getGdi()->createNativeFence(&createNativeFenceObject); + DEBUG_BREAK_IF(STATUS_SUCCESS != status); + + monitorFence.fenceHandle = createNativeFenceObject.hSyncObject; + monitorFence.cpuAddress = reinterpret_cast(createNativeFenceObject.Info.NativeFenceMapping.CurrentValueCpuVa); + monitorFence.gpuAddress = createNativeFenceObject.Info.NativeFenceMapping.CurrentValueGpuVa; + + return status == STATUS_SUCCESS; +} diff --git a/shared/test/common/mock_gdi/mock_gdi.cpp b/shared/test/common/mock_gdi/mock_gdi.cpp index 29040a5391..15662d2683 100644 --- a/shared/test/common/mock_gdi/mock_gdi.cpp +++ b/shared/test/common/mock_gdi/mock_gdi.cpp @@ -560,6 +560,10 @@ NTSTATUS __stdcall mockD3DKMTCreateSynchronizationObject2(IN OUT D3DKMT_CREATESY return STATUS_SUCCESS; } +NTSTATUS __stdcall mockD3DKMTCreateNativeFence(IN OUT D3DKMT_CREATENATIVEFENCE *synchObject) { + return STATUS_SUCCESS; +} + NTSTATUS __stdcall mockD3DKMTSetAllocationPriority(IN CONST D3DKMT_SETALLOCATIONPRIORITY *setAllocationPriority) { if (setAllocationPriority == nullptr || setAllocationPriority->hDevice != DEVICE_HANDLE) { return STATUS_INVALID_PARAMETER; diff --git a/shared/test/common/mock_gdi/mock_gdi.h b/shared/test/common/mock_gdi/mock_gdi.h index 6c60fa7c21..e0c5c631a8 100644 --- a/shared/test/common/mock_gdi/mock_gdi.h +++ b/shared/test/common/mock_gdi/mock_gdi.h @@ -29,6 +29,8 @@ #define GPUVA (static_cast(0x80123000000)) +typedef struct _D3DKMT_CREATENATIVEFENCE D3DKMT_CREATENATIVEFENCE; + void mockSetAdapterInfo(const void *pGfxPlatform, const void *pGTSystemInfo, uint64_t gpuAddressSpace); NTSTATUS __stdcall mockD3DKMTCreateAllocation(IN OUT D3DKMT_CREATEALLOCATION *allocation); NTSTATUS __stdcall mockD3DKMTCreateAllocation2(IN OUT D3DKMT_CREATEALLOCATION *allocation); @@ -47,6 +49,7 @@ NTSTATUS __stdcall mockD3DKMTQueryResourceInfo(IN OUT D3DKMT_QUERYRESOURCEINFO * NTSTATUS __stdcall mockD3DKMTQueryResourceInfoFromNtHandle(IN OUT D3DKMT_QUERYRESOURCEINFOFROMNTHANDLE *queryResourceInfo); NTSTATUS __stdcall mockD3DKMTCreateSynchronizationObject2(IN OUT D3DKMT_CREATESYNCHRONIZATIONOBJECT2 *synchObject); NTSTATUS __stdcall mockD3DKMTDestroySynchronizationObject(IN CONST D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *destroySynchronizationObject); +NTSTATUS __stdcall mockD3DKMTCreateNativeFence(IN OUT D3DKMT_CREATENATIVEFENCE *synchObject); NTSTATUS __stdcall mockD3DKMTCreatePagingQueue(IN OUT D3DKMT_CREATEPAGINGQUEUE *createQueue); NTSTATUS __stdcall mockD3DKMTDestroyPagingQueue(IN OUT D3DDDI_DESTROYPAGINGQUEUE *destoryQueue); NTSTATUS __stdcall mockD3DKMTLock2(IN OUT D3DKMT_LOCK2 *lock2); diff --git a/shared/test/common/mock_gdi/mock_os_library.cpp b/shared/test/common/mock_gdi/mock_os_library.cpp index 97043e4bea..04262a2567 100644 --- a/shared/test/common/mock_gdi/mock_os_library.cpp +++ b/shared/test/common/mock_gdi/mock_os_library.cpp @@ -67,6 +67,9 @@ void *MockOsLibrary::getProcAddress(const std::string &procName) { if (procName == "D3DKMTCreateSynchronizationObject2") { return reinterpret_cast(mockD3DKMTCreateSynchronizationObject2); } + if (procName == "D3DKMTCreateNativeFence") { + return reinterpret_cast(mockD3DKMTCreateNativeFence); + } if (procName == "D3DKMTDestroySynchronizationObject") { return reinterpret_cast(mockD3DKMTDestroySynchronizationObject); } diff --git a/shared/test/common/mocks/CMakeLists.txt b/shared/test/common/mocks/CMakeLists.txt index 2a7898d316..29761016cb 100644 --- a/shared/test/common/mocks/CMakeLists.txt +++ b/shared/test/common/mocks/CMakeLists.txt @@ -128,6 +128,7 @@ if(WIN32 OR NOT DISABLE_WDDM_LINUX) ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_interface.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_interface20.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_interface23.h + ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_interface32.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_residency_allocations_container.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_wddm_residency_logger.h ${CMAKE_CURRENT_SOURCE_DIR}/wddm_mock_helpers.h diff --git a/shared/test/common/mocks/mock_wddm_interface.h b/shared/test/common/mocks/mock_wddm_interface.h index 534d659a8a..06c93fb199 100644 --- a/shared/test/common/mocks/mock_wddm_interface.h +++ b/shared/test/common/mocks/mock_wddm_interface.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Intel Corporation + * Copyright (C) 2024-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -20,6 +20,6 @@ class WddmMockInterface : public WddmInterface { ADDMETHOD_NOBASE_VOIDRETURN(destroyMonitorFence, (MonitoredFence & monitorFence)); ADDMETHOD_NOBASE(hwQueuesSupported, bool, false, ()); ADDMETHOD_NOBASE(submit, bool, true, (uint64_t commandBuffer, size_t size, void *commandHeader, WddmSubmitArguments &submitArguments)); - ADDMETHOD_NOBASE(createMonitoredFenceForDirectSubmission, bool, true, (MonitoredFence & monitorFence, OsContextWin &osContext)); + ADDMETHOD_NOBASE(createFenceForDirectSubmission, bool, true, (MonitoredFence & monitorFence, OsContextWin &osContext)); }; } // namespace NEO diff --git a/shared/test/common/mocks/mock_wddm_interface20.h b/shared/test/common/mocks/mock_wddm_interface20.h index a1198a99d4..f7bf05cbeb 100644 --- a/shared/test/common/mocks/mock_wddm_interface20.h +++ b/shared/test/common/mocks/mock_wddm_interface20.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2024 Intel Corporation + * Copyright (C) 2019-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -33,7 +33,7 @@ class WddmMockInterface20 : public WddmInterface20 { return WddmInterface::createMonitoredFence(monitorFence); } - bool createMonitoredFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) override { + bool createFenceForDirectSubmission(MonitoredFence &monitorFence, OsContextWin &osContext) override { return createMonitoredFence(monitorFence); }; diff --git a/shared/test/common/mocks/mock_wddm_interface32.h b/shared/test/common/mocks/mock_wddm_interface32.h new file mode 100644 index 0000000000..1909ca4989 --- /dev/null +++ b/shared/test/common/mocks/mock_wddm_interface32.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/source/os_interface/windows/wddm/wddm_interface.h" + +namespace NEO { +class WddmMockInterface32 : public WddmInterface32 { + public: + using WddmInterface32::WddmInterface32; + + bool createHwQueue(OsContextWin &osContext) override { + createHwQueueCalled++; + createHwQueueResult = forceCreateHwQueueFail ? false : WddmInterface23::createHwQueue(osContext); + return createHwQueueResult; + } + + void destroyMonitorFence(MonitoredFence &monitorFence) override { + destroyMonitorFenceCalled++; + WddmInterface32::destroyMonitorFence(monitorFence); + } + + bool createSyncObject(MonitoredFence &monitorFence) override { + createSyncObjectCalled++; + WddmInterface32::createSyncObject(monitorFence); + return true; + } + + uint32_t createHwQueueCalled = 0; + uint32_t createSyncObjectCalled = 0; + bool forceCreateHwQueueFail = false; + bool createHwQueueResult = false; + + uint32_t destroyMonitorFenceCalled = 0; +}; +} // namespace NEO diff --git a/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt b/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt index 571246900a..3bd362e884 100644 --- a/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt +++ b/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt @@ -9,5 +9,6 @@ if(UNIX AND NOT DISABLE_WDDM_LINUX) ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/configure_device_address_space_drm_or_wddm_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ccs_mode_drm_or_wddm_test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/wddm32_tests_extra.cpp ) endif() diff --git a/shared/test/unit_test/os_interface/wddm_linux/wddm32_tests_extra.cpp b/shared/test/unit_test/os_interface/wddm_linux/wddm32_tests_extra.cpp new file mode 100644 index 0000000000..c8c4d071a6 --- /dev/null +++ b/shared/test/unit_test/os_interface/wddm_linux/wddm32_tests_extra.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/unit_test/os_interface/windows/wddm32_tests.h" + +using namespace NEO; + +TEST_F(Wddm32Tests, whencreateMonitoredFenceForDirectSubmissionThenObtainHwQueueFenceAndReplaceResidencyControllerWithNewFence) { + MonitoredFence fence{}; + EXPECT_THROW(wddm->getWddmInterface()->createFenceForDirectSubmission(fence, *osContext), std::exception); +} diff --git a/shared/test/unit_test/os_interface/windows/CMakeLists.txt b/shared/test/unit_test/os_interface/windows/CMakeLists.txt index 821211d715..7bcfd682c9 100644 --- a/shared/test/unit_test/os_interface/windows/CMakeLists.txt +++ b/shared/test/unit_test/os_interface/windows/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2019-2024 Intel Corporation +# Copyright (C) 2019-2025 Intel Corporation # # SPDX-License-Identifier: MIT # @@ -34,6 +34,7 @@ if(WIN32) ${CMAKE_CURRENT_SOURCE_DIR}/wddm_special_heap_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm_memory_reservation_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm_windows_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/wddm32_tests_extra.cpp ${CMAKE_CURRENT_SOURCE_DIR}/${BRANCH_DIR_SUFFIX}/wddm_perf_tests.cpp ) endif() @@ -43,6 +44,7 @@ if(WIN32 OR(UNIX AND NOT DISABLE_WDDM_LINUX)) ${IGDRCL_SRC_tests_wddm_interface} ${CMAKE_CURRENT_SOURCE_DIR}/wddm20_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm23_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/wddm32_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/gdi_interface_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm_address_space_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wddm_mapper_tests.cpp diff --git a/shared/test/unit_test/os_interface/windows/wddm20_tests.cpp b/shared/test/unit_test/os_interface/windows/wddm20_tests.cpp index da3bf0bda4..26cd2e144c 100644 --- a/shared/test/unit_test/os_interface/windows/wddm20_tests.cpp +++ b/shared/test/unit_test/os_interface/windows/wddm20_tests.cpp @@ -348,7 +348,7 @@ TEST_F(Wddm20WithMockGdiDllTests, GivenCpuValueDifferentThanGpuHangIndicationWhe TEST_F(Wddm20WithMockGdiDllTests, whencreateMonitoredFenceForDirectSubmissionThenCreateFence) { MonitoredFence fence{}; - wddm->getWddmInterface()->createMonitoredFenceForDirectSubmission(fence, *osContext); + wddm->getWddmInterface()->createFenceForDirectSubmission(fence, *osContext); EXPECT_EQ(wddmMockInterface->createMonitoredFenceCalled, 1u); EXPECT_NE(osContext->getHwQueue().progressFenceHandle, fence.fenceHandle); wddm->getWddmInterface()->destroyMonitorFence(fence); diff --git a/shared/test/unit_test/os_interface/windows/wddm23_tests.cpp b/shared/test/unit_test/os_interface/windows/wddm23_tests.cpp index 25ea4a0f03..d330dc430a 100644 --- a/shared/test/unit_test/os_interface/windows/wddm23_tests.cpp +++ b/shared/test/unit_test/os_interface/windows/wddm23_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2024 Intel Corporation + * Copyright (C) 2018-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -114,7 +114,7 @@ TEST_F(Wddm23Tests, whencreateMonitoredFenceForDirectSubmissionThenObtainHwQueue osContext->getResidencyController().getMonitoredFence().currentFenceValue = 2u; osContext->getResidencyController().getMonitoredFence().lastSubmittedFence = 1u; MonitoredFence fence{}; - wddm->getWddmInterface()->createMonitoredFenceForDirectSubmission(fence, *osContext); + wddm->getWddmInterface()->createFenceForDirectSubmission(fence, *osContext); EXPECT_EQ(osContext->getHwQueue().progressFenceHandle, fence.fenceHandle); EXPECT_NE(osContext->getResidencyController().getMonitoredFence().fenceHandle, osContext->getHwQueue().progressFenceHandle); EXPECT_EQ(osContext->getResidencyController().getMonitoredFence().currentFenceValue, 2u); diff --git a/shared/test/unit_test/os_interface/windows/wddm32_tests.cpp b/shared/test/unit_test/os_interface/windows/wddm32_tests.cpp new file mode 100644 index 0000000000..04671bf84d --- /dev/null +++ b/shared/test/unit_test/os_interface/windows/wddm32_tests.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/unit_test/os_interface/windows/wddm32_tests.h" + +#include "shared/test/common/helpers/debug_manager_state_restore.h" +#include "shared/test/common/helpers/variable_backup.h" + +using namespace NEO; + +TEST_F(Wddm32Tests, whenGetDedicatedVideoMemoryIsCalledThenCorrectValueIsReturned) { + EXPECT_EQ(wddm->dedicatedVideoMemory, wddm->getDedicatedVideoMemory()); +} + +TEST_F(Wddm32Tests, whenCreateContextIsCalledThenEnableHwQueues) { + EXPECT_TRUE(wddm->wddmInterface->hwQueuesSupported()); + EXPECT_EQ(1u, getCreateContextDataFcn()->Flags.HwQueueSupported); +} + +TEST_F(Wddm32Tests, givenPreemptionModeWhenCreateHwQueueCalledThenSetGpuTimeoutIfEnabled) { + auto &gfxCoreHelper = this->executionEnvironment.rootDeviceEnvironments[0]->getHelper(); + auto defaultEngine = gfxCoreHelper.getGpgpuEngineInstances(*this->executionEnvironment.rootDeviceEnvironments[0])[0]; + OsContextWin osContextWithoutPreemption(*wddm, 0, 0u, + EngineDescriptorHelper::getDefaultDescriptor(defaultEngine, PreemptionMode::Disabled)); + OsContextWin osContextWithPreemption(*wddm, 0, 0, EngineDescriptorHelper::getDefaultDescriptor(defaultEngine, PreemptionMode::MidBatch)); + + wddm->wddmInterface->createHwQueue(osContextWithoutPreemption); + EXPECT_EQ(0u, getCreateHwQueueDataFcn()->Flags.DisableGpuTimeout); + + wddm->wddmInterface->createHwQueue(osContextWithPreemption); + EXPECT_EQ(1u, getCreateHwQueueDataFcn()->Flags.DisableGpuTimeout); +} + +TEST_F(Wddm32Tests, whenDestroyHwQueueCalledThenPassExistingHandle) { + D3DKMT_HANDLE hwQueue = 123; + osContext->setHwQueue({hwQueue, 0, nullptr, 0}); + wddmMockInterface->destroyHwQueue(osContext->getHwQueue().handle); + EXPECT_EQ(hwQueue, getDestroyHwQueueDataFcn()->hHwQueue); + + hwQueue = 0; + osContext->setHwQueue({hwQueue, 0, nullptr, 0}); + wddmMockInterface->destroyHwQueue(osContext->getHwQueue().handle); + EXPECT_NE(hwQueue, getDestroyHwQueueDataFcn()->hHwQueue); // gdi not called when 0 +} + +TEST_F(Wddm32Tests, whenObjectIsDestructedThenDestroyHwQueue) { + D3DKMT_HANDLE hwQueue = 123; + osContext->setHwQueue({hwQueue, 0, nullptr, 0}); + osContext.reset(); + EXPECT_EQ(hwQueue, getDestroyHwQueueDataFcn()->hHwQueue); +} + +TEST_F(Wddm32Tests, givenCmdBufferWhenSubmitCalledThenSetAllRequiredFiledsAndUpdateMonitoredFence) { + uint64_t cmdBufferAddress = 123; + size_t cmdSize = 456; + auto hwQueue = osContext->getHwQueue(); + COMMAND_BUFFER_HEADER cmdBufferHeader = {}; + + EXPECT_EQ(1u, osContext->getResidencyController().getMonitoredFence().currentFenceValue); + EXPECT_EQ(0u, osContext->getResidencyController().getMonitoredFence().lastSubmittedFence); + + WddmSubmitArguments submitArgs = {}; + submitArgs.contextHandle = osContext->getWddmContextHandle(); + submitArgs.hwQueueHandle = hwQueue.handle; + submitArgs.monitorFence = &osContext->getResidencyController().getMonitoredFence(); + wddm->submit(cmdBufferAddress, cmdSize, &cmdBufferHeader, submitArgs); + + EXPECT_EQ(cmdBufferAddress, getSubmitCommandToHwQueueDataFcn()->CommandBuffer); + EXPECT_EQ(static_cast(cmdSize), getSubmitCommandToHwQueueDataFcn()->CommandLength); + EXPECT_EQ(hwQueue.handle, getSubmitCommandToHwQueueDataFcn()->hHwQueue); + EXPECT_EQ(osContext->getResidencyController().getMonitoredFence().lastSubmittedFence, getSubmitCommandToHwQueueDataFcn()->HwQueueProgressFenceId); + EXPECT_EQ(&cmdBufferHeader, getSubmitCommandToHwQueueDataFcn()->pPrivateDriverData); + EXPECT_EQ(static_cast(sizeof(COMMAND_BUFFER_HEADER)), getSubmitCommandToHwQueueDataFcn()->PrivateDriverDataSize); + + 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(Wddm32Tests, givenDebugVariableSetWhenSubmitCalledThenUseCmdBufferHeaderSizeForPrivateDriverDataSize) { + DebugManagerStateRestore restore; + debugManager.flags.UseCommandBufferHeaderSizeForWddmQueueSubmission.set(true); + + COMMAND_BUFFER_HEADER cmdBufferHeader = {}; + + WddmSubmitArguments submitArgs = {}; + submitArgs.contextHandle = osContext->getWddmContextHandle(); + submitArgs.hwQueueHandle = osContext->getHwQueue().handle; + submitArgs.monitorFence = &osContext->getResidencyController().getMonitoredFence(); + wddm->submit(123, 456, &cmdBufferHeader, submitArgs); + + EXPECT_EQ(static_cast(sizeof(COMMAND_BUFFER_HEADER)), getSubmitCommandToHwQueueDataFcn()->PrivateDriverDataSize); + + debugManager.flags.UseCommandBufferHeaderSizeForWddmQueueSubmission.set(false); + + cmdBufferHeader = {}; + submitArgs = {}; + submitArgs.contextHandle = osContext->getWddmContextHandle(); + submitArgs.hwQueueHandle = osContext->getHwQueue().handle; + submitArgs.monitorFence = &osContext->getResidencyController().getMonitoredFence(); + wddm->submit(123, 456, &cmdBufferHeader, submitArgs); + + EXPECT_EQ(static_cast(MemoryConstants::pageSize), getSubmitCommandToHwQueueDataFcn()->PrivateDriverDataSize); +} + +TEST_F(Wddm32Tests, whenMonitoredFenceIsCreatedThenSetupAllRequiredFields) { + wddm->wddmInterface->createMonitoredFence(*osContext); + auto hwQueue = osContext->getHwQueue(); + + EXPECT_EQ(hwQueue.progressFenceCpuVA, osContext->getResidencyController().getMonitoredFence().cpuAddress); + EXPECT_EQ(1u, osContext->getResidencyController().getMonitoredFence().currentFenceValue); + EXPECT_EQ(hwQueue.progressFenceHandle, osContext->getResidencyController().getMonitoredFence().fenceHandle); + EXPECT_EQ(hwQueue.progressFenceGpuVA, osContext->getResidencyController().getMonitoredFence().gpuAddress); + EXPECT_EQ(0u, osContext->getResidencyController().getMonitoredFence().lastSubmittedFence); +} + +TEST_F(Wddm32Tests, givenCurrentPendingFenceValueGreaterThanPendingFenceValueWhenSubmitCalledThenCallWaitOnGpu) { + uint64_t cmdBufferAddress = 123; + size_t cmdSize = 456; + COMMAND_BUFFER_HEADER cmdBufferHeader = {}; + + WddmSubmitArguments submitArgs = {}; + submitArgs.contextHandle = osContext->getWddmContextHandle(); + submitArgs.hwQueueHandle = osContext->getHwQueue().handle; + submitArgs.monitorFence = &osContext->getResidencyController().getMonitoredFence(); + + VariableBackup pagingFenceBackup(wddm->pagingFenceAddress); + *wddm->pagingFenceAddress = 1; + wddm->currentPagingFenceValue = 1; + + wddm->submit(cmdBufferAddress, cmdSize, &cmdBufferHeader, submitArgs); + EXPECT_EQ(0u, wddm->waitOnGPUResult.called); + + wddm->currentPagingFenceValue = 2; + wddm->submit(cmdBufferAddress, cmdSize, &cmdBufferHeader, submitArgs); + EXPECT_EQ(1u, wddm->waitOnGPUResult.called); +} + +TEST_F(Wddm32Tests, givenDestructionOsContextWinWhenCallingDestroyMonitorFenceThenDoNotCallDestroy) { + osContext.reset(nullptr); + EXPECT_EQ(0u, wddmMockInterface->destroyMonitorFenceCalled); + EXPECT_EQ(0u, getDestroySynchronizationObjectDataFcn()->hSyncObject); +} + +TEST_F(Wddm32TestsWithoutWddmInit, whenInitCalledThenInitializeNewGdiDDIsAndCallToCreateHwQueue) { + EXPECT_EQ(nullptr, wddm->getGdi()->createHwQueue.mFunc); + EXPECT_EQ(nullptr, wddm->getGdi()->destroyHwQueue.mFunc); + EXPECT_EQ(nullptr, wddm->getGdi()->submitCommandToHwQueue.mFunc); + + init(); + EXPECT_EQ(1u, wddmMockInterface->createHwQueueCalled); + + EXPECT_NE(nullptr, wddm->getGdi()->createHwQueue.mFunc); + EXPECT_NE(nullptr, wddm->getGdi()->destroyHwQueue.mFunc); + EXPECT_NE(nullptr, wddm->getGdi()->submitCommandToHwQueue.mFunc); +} + +TEST_F(Wddm32TestsWithoutWddmInit, whenCreateHwQueueFailedThenReturnFalseFromInit) { + wddmMockInterface->forceCreateHwQueueFail = true; + EXPECT_ANY_THROW(init()); +} + +TEST_F(Wddm32TestsWithoutWddmInit, givenFailureOnGdiInitializationWhenCreatingHwQueueThenReturnFailure) { + struct MyMockGdi : public Gdi { + bool setupHwQueueProcAddresses() override { + return false; + } + }; + auto myMockGdi = new MyMockGdi(); + wddm->resetGdi(myMockGdi); + EXPECT_ANY_THROW(init()); + EXPECT_EQ(1u, wddmMockInterface->createHwQueueCalled); + EXPECT_FALSE(wddmMockInterface->createHwQueueResult); +} diff --git a/shared/test/unit_test/os_interface/windows/wddm32_tests.h b/shared/test/unit_test/os_interface/windows/wddm32_tests.h new file mode 100644 index 0000000000..3c6270888d --- /dev/null +++ b/shared/test/unit_test/os_interface/windows/wddm32_tests.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/source/command_stream/preemption.h" +#include "shared/source/helpers/gfx_core_helper.h" +#include "shared/source/os_interface/windows/gdi_interface.h" +#include "shared/source/os_interface/windows/os_context_win.h" +#include "shared/test/common/helpers/engine_descriptor_helper.h" +#include "shared/test/common/mocks/mock_execution_environment.h" +#include "shared/test/common/mocks/mock_wddm.h" +#include "shared/test/common/mocks/mock_wddm_interface32.h" +#include "shared/test/common/os_interface/windows/gdi_dll_fixture.h" +#include "shared/test/common/test_macros/hw_test.h" + +using namespace NEO; + +struct Wddm32TestsWithoutWddmInit : public ::testing::Test, GdiDllFixture { + void SetUp() override { + GdiDllFixture::setUp(); + + wddm = static_cast(Wddm::createWddm(nullptr, *executionEnvironment.rootDeviceEnvironments[0].get())); + auto &osInterface = executionEnvironment.rootDeviceEnvironments[0]->osInterface; + osInterface = std::make_unique(); + osInterface->setDriverModel(std::unique_ptr(wddm)); + + wddm->featureTable->flags.ftrWddmHwQueues = true; + wddmMockInterface = new WddmMockInterface32(*wddm); + wddm->wddmInterface.reset(wddmMockInterface); + } + + void init() { + auto preemptionMode = PreemptionHelper::getDefaultPreemptionMode(*defaultHwInfo); + wddmMockInterface = static_cast(wddm->wddmInterface.release()); + wddm->init(); + wddm->wddmInterface.reset(wddmMockInterface); + auto &gfxCoreHelper = this->executionEnvironment.rootDeviceEnvironments[0]->getHelper(); + osContext = std::make_unique(*wddm, 0, 0u, + EngineDescriptorHelper::getDefaultDescriptor(gfxCoreHelper.getGpgpuEngineInstances(*this->executionEnvironment.rootDeviceEnvironments[0])[0], preemptionMode)); + osContext->ensureContextInitialized(false); + } + + void TearDown() override { + GdiDllFixture::tearDown(); + } + + MockExecutionEnvironment executionEnvironment; + std::unique_ptr osContext; + WddmMock *wddm = nullptr; + WddmMockInterface32 *wddmMockInterface = nullptr; +}; + +struct Wddm32Tests : public Wddm32TestsWithoutWddmInit { + using Wddm32TestsWithoutWddmInit::TearDown; + void SetUp() override { + Wddm32TestsWithoutWddmInit::SetUp(); + init(); + } +}; \ No newline at end of file diff --git a/shared/test/unit_test/os_interface/windows/wddm32_tests_extra.cpp b/shared/test/unit_test/os_interface/windows/wddm32_tests_extra.cpp new file mode 100644 index 0000000000..31fa951f62 --- /dev/null +++ b/shared/test/unit_test/os_interface/windows/wddm32_tests_extra.cpp @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/unit_test/os_interface/windows/wddm32_tests.h" + +using namespace NEO; + +TEST_F(Wddm32Tests, whencreateMonitoredFenceForDirectSubmissionThenObtainHwQueueFenceAndReplaceResidencyControllerWithNewFence) { + MonitoredFence fence{}; + wddm->getWddmInterface()->createFenceForDirectSubmission(fence, *osContext); + EXPECT_EQ(wddmMockInterface->createSyncObjectCalled, 1u); +}