From 3ae75b39fbf77587ab005d7706b4c6e0546c1890 Mon Sep 17 00:00:00 2001 From: Jaroslaw Chodor Date: Tue, 11 May 2021 17:07:20 +0200 Subject: [PATCH] Changing win dev discovery to DXCoreAdapterFactory Second try - keeping legacy path as fallback Signed-off-by: Jaroslaw Chodor --- CMakeLists.txt | 2 +- .../core/test/unit_tests/CMakeLists.txt | 1 + .../test/unit_tests/CMakeLists.txt | 1 + .../tools/test/unit_tests/CMakeLists.txt | 1 + opencl/test/unit_test/libult/CMakeLists.txt | 2 + .../windows/ult_dxcore_factory.cpp | 25 ++ .../os_interface/windows/ult_dxcore_factory.h | 252 ++++++++++++++++++ .../os_interface/windows/ult_dxgi_factory.cpp | 6 - .../os_interface/windows/ult_dxgi_factory.h | 1 - .../os_interface/windows/wddm20_tests.cpp | 8 +- .../os_interface/windows/wddm_calls.cpp | 6 +- .../windows/wddm/adapter_info.cpp | 176 ++++++++++++ .../os_interface/windows/wddm/adapter_info.h | 126 +++++++++ .../source/os_interface/windows/wddm/wddm.cpp | 82 +++--- .../source/os_interface/windows/wddm/wddm.h | 2 + .../os_interface/windows/wddm/wddm_calls.cpp | 7 +- shared/test/unit_test/CMakeLists.txt | 1 + .../windows/adapter_info_tests.cpp | 165 ++++++++++++ 18 files changed, 810 insertions(+), 54 deletions(-) create mode 100644 opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.cpp create mode 100644 opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 93e3b1de78..fbea0e8c52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -698,7 +698,7 @@ if(MSVC) set(LINKER_FLAGS "${LINKER_FLAGS} legacy_stdio_float_rounding.obj") # Support for WUD - set(CMAKE_CXX_STANDARD_LIBRARIES "onecore.lib") + set(CMAKE_CXX_STANDARD_LIBRARIES "onecore.lib dxcore.lib") foreach(IT kernel32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;) set(LINKER_FLAGS "${LINKER_FLAGS} /NODEFAULTLIB:${IT}") endforeach() diff --git a/level_zero/core/test/unit_tests/CMakeLists.txt b/level_zero/core/test/unit_tests/CMakeLists.txt index 524a9d4683..3e88a90be5 100644 --- a/level_zero/core/test/unit_tests/CMakeLists.txt +++ b/level_zero/core/test/unit_tests/CMakeLists.txt @@ -65,6 +65,7 @@ else() ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/create_wddm_memory_manager.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/options.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/sys_calls.cpp + ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/wddm_calls.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/wddm_create.cpp diff --git a/level_zero/experimental/test/unit_tests/CMakeLists.txt b/level_zero/experimental/test/unit_tests/CMakeLists.txt index a717689f8e..1eb7125320 100644 --- a/level_zero/experimental/test/unit_tests/CMakeLists.txt +++ b/level_zero/experimental/test/unit_tests/CMakeLists.txt @@ -76,6 +76,7 @@ else() ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/create_wddm_memory_manager.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/options.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/sys_calls.cpp + ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/wddm_calls.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/wddm_create.cpp diff --git a/level_zero/tools/test/unit_tests/CMakeLists.txt b/level_zero/tools/test/unit_tests/CMakeLists.txt index 3c3ddcb695..9ba0c85acb 100644 --- a/level_zero/tools/test/unit_tests/CMakeLists.txt +++ b/level_zero/tools/test/unit_tests/CMakeLists.txt @@ -62,6 +62,7 @@ else() ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/create_wddm_memory_manager.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/options.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/sys_calls.cpp + ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/wddm_calls.cpp ${COMPUTE_RUNTIME_DIR}/opencl/test/unit_test/os_interface/windows/wddm_create.cpp diff --git a/opencl/test/unit_test/libult/CMakeLists.txt b/opencl/test/unit_test/libult/CMakeLists.txt index dbcb8fa1ba..2053061f2c 100644 --- a/opencl/test/unit_test/libult/CMakeLists.txt +++ b/opencl/test/unit_test/libult/CMakeLists.txt @@ -139,6 +139,8 @@ set(IGDRCL_SRCS_LIB_ULT_ENV_WINDOWS ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/create_wddm_memory_manager.cpp ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/options.cpp ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/sys_calls.cpp + ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.cpp + ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.h ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.cpp ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.h ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/wddm_calls.cpp diff --git a/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.cpp b/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.cpp new file mode 100644 index 0000000000..7df5998399 --- /dev/null +++ b/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2017-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.h" + +namespace NEO { + +HRESULT WINAPI ULTDXCoreCreateAdapterFactory(REFIID riid, void **ppFactory) { + *reinterpret_cast(ppFactory) = new UltDXCoreAdapterFactory; + return S_OK; +} + +void WINAPI ULTGetSystemInfo(SYSTEM_INFO *pSystemInfo) { + pSystemInfo->lpMaximumApplicationAddress = is32bit ? (LPVOID)MemoryConstants::max32BitAppAddress : (LPVOID)MemoryConstants::max64BitAppAddress; +} + +const char *UltDxCoreAdapter::description = "Intel"; + +extern uint32_t numRootDevicesToEnum = 1; + +} // namespace NEO diff --git a/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.h b/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.h new file mode 100644 index 0000000000..70fffe7ef6 --- /dev/null +++ b/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.h @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2017-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/source/helpers/constants.h" +#include "shared/source/helpers/debug_helpers.h" + +#include +#include +#include + +namespace NEO { +static constexpr auto error = 1; + +class UltDxCoreAdapter : public IDXCoreAdapter { + public: + const static char *description; + bool STDMETHODCALLTYPE IsValid() override { + return true; + } + + bool STDMETHODCALLTYPE IsAttributeSupported(REFGUID attributeGUID) override { + UNRECOVERABLE_IF(true); + return false; + } + + bool STDMETHODCALLTYPE IsPropertySupported(DXCoreAdapterProperty property) override { + UNRECOVERABLE_IF(true); + return false; + } + + HRESULT STDMETHODCALLTYPE GetProperty(DXCoreAdapterProperty property, size_t bufferSize, + _Out_writes_bytes_(bufferSize) void *propertyData) override { + size_t requiredSize; + GetPropertySize(property, &requiredSize); + if (bufferSize < requiredSize) { + return error; + } + switch (property) { + default: + UNRECOVERABLE_IF(true); + return error; + case DXCoreAdapterProperty::IsHardware: + *reinterpret_cast(propertyData) = true; + break; + case DXCoreAdapterProperty::DriverDescription: + memcpy_s(propertyData, bufferSize, description, requiredSize); + break; + case DXCoreAdapterProperty::InstanceLuid: + reinterpret_cast(propertyData)->HighPart = 0x1234; + reinterpret_cast(propertyData)->LowPart = 0; + break; + case DXCoreAdapterProperty::HardwareID: { + DXCoreHardwareID ret = {}; + ret.deviceID = 0x1234; + *reinterpret_cast(propertyData) = ret; + } break; + } + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE GetPropertySize(DXCoreAdapterProperty property, _Out_ size_t *bufferSize) override { + switch (property) { + default: + UNRECOVERABLE_IF(true); + return error; + case DXCoreAdapterProperty::IsHardware: + *bufferSize = sizeof(bool); + break; + case DXCoreAdapterProperty::DriverDescription: + *bufferSize = strlen(description) + 1; + break; + case DXCoreAdapterProperty::InstanceLuid: + *bufferSize = sizeof(LUID); + break; + case DXCoreAdapterProperty::HardwareID: + *bufferSize = sizeof(DXCoreHardwareID); + break; + } + + return S_OK; + } + + bool STDMETHODCALLTYPE IsQueryStateSupported(DXCoreAdapterState property) override { + UNRECOVERABLE_IF(true); + return error; + } + + HRESULT STDMETHODCALLTYPE QueryState(DXCoreAdapterState state, size_t inputStateDetailsSize, + _In_reads_bytes_opt_(inputStateDetailsSize) const void *inputStateDetails, + size_t outputBufferSize, _Out_writes_bytes_(outputBufferSize) void *outputBuffer) override { + UNRECOVERABLE_IF(true); + return error; + } + + bool STDMETHODCALLTYPE IsSetStateSupported(DXCoreAdapterState property) override { + UNRECOVERABLE_IF(true); + return false; + } + + HRESULT STDMETHODCALLTYPE SetState(DXCoreAdapterState state, size_t inputStateDetailsSize, + _In_reads_bytes_opt_(inputStateDetailsSize) const void *inputStateDetails, + size_t inputDataSize, _In_reads_bytes_(inputDataSize) const void *inputData) override { + UNRECOVERABLE_IF(true); + return error; + } + + HRESULT STDMETHODCALLTYPE GetFactory(REFIID riid, _COM_Outptr_ void **ppvFactory) override { + UNRECOVERABLE_IF(true); + return error; + } + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) override { + UNRECOVERABLE_IF(true); + return error; + } + + ULONG STDMETHODCALLTYPE AddRef(void) override { + UNRECOVERABLE_IF(true); + return 0; + } + + ULONG STDMETHODCALLTYPE Release(void) override { + // this must be the last instruction + delete this; + return 0; + } +}; + +extern uint32_t numRootDevicesToEnum; +class UltDXCoreAdapterList : public IDXCoreAdapterList { + public: + HRESULT STDMETHODCALLTYPE GetAdapter(uint32_t index, REFIID riid, _COM_Outptr_ void **ppvAdapter) override { + *reinterpret_cast(ppvAdapter) = new UltDxCoreAdapter; + return S_OK; + } + uint32_t STDMETHODCALLTYPE GetAdapterCount() override { + return numRootDevicesToEnum; + } + + bool STDMETHODCALLTYPE IsStale() override { + return false; + } + + HRESULT STDMETHODCALLTYPE GetFactory(REFIID riid, _COM_Outptr_ void **ppvFactory) override { + UNRECOVERABLE_IF(true); + return error; + } + + HRESULT STDMETHODCALLTYPE Sort(uint32_t numPreferences, _In_reads_(numPreferences) const DXCoreAdapterPreference *preferences) override { + UNRECOVERABLE_IF(true); + return error; + } + + bool STDMETHODCALLTYPE IsAdapterPreferenceSupported(DXCoreAdapterPreference preference) override { + UNRECOVERABLE_IF(true); + return false; + } + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) override { + UNRECOVERABLE_IF(true); + return error; + } + + ULONG STDMETHODCALLTYPE AddRef(void) override { + UNRECOVERABLE_IF(true); + return 0; + } + + ULONG STDMETHODCALLTYPE Release(void) override { + // this must be the last instruction + delete this; + return 0; + } +}; + +extern uint32_t numRootDevicesToEnum; +class UltDXCoreAdapterFactory : public IDXCoreAdapterFactory { + public: + struct CreateAdapterListArgs { + uint32_t numAttributes; + const GUID *filterAttributesPtr; + std::vector filterAttributesCopy; + REFIID riid; + void **ppvAdapterList; + }; + + std::vector argsOfCreateAdapterListRequests; + + HRESULT STDMETHODCALLTYPE CreateAdapterList(uint32_t numAttributes, _In_reads_(numAttributes) const GUID *filterAttributes, + REFIID riid, _COM_Outptr_ void **ppvAdapterList) override { + argsOfCreateAdapterListRequests.push_back({numAttributes, + filterAttributes, + std::vector{filterAttributes, filterAttributes + numAttributes}, + riid, ppvAdapterList}); + + *reinterpret_cast(ppvAdapterList) = new UltDXCoreAdapterList; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE GetAdapterByLuid(const LUID &adapterLUID, REFIID riid, _COM_Outptr_ void **ppvAdapter) override { + UNRECOVERABLE_IF(true); + return error; + } + + bool STDMETHODCALLTYPE IsNotificationTypeSupported(DXCoreNotificationType notificationType) override { + UNRECOVERABLE_IF(true); + return false; + } + + HRESULT STDMETHODCALLTYPE RegisterEventNotification(_In_ IUnknown *dxCoreObject, DXCoreNotificationType notificationType, + _In_ PFN_DXCORE_NOTIFICATION_CALLBACK callbackFunction, + _In_opt_ void *callbackContext, _Out_ uint32_t *eventCookie) override { + UNRECOVERABLE_IF(true); + return error; + } + + HRESULT STDMETHODCALLTYPE UnregisterEventNotification(uint32_t eventCookie) override { + UNRECOVERABLE_IF(true); + return error; + } + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) override { + UNRECOVERABLE_IF(true); + return error; + } + + ULONG STDMETHODCALLTYPE AddRef(void) override { + UNRECOVERABLE_IF(true); + return 0; + } + + ULONG STDMETHODCALLTYPE Release(void) override { + // this must be the last instruction + delete this; + return 0; + } +}; + +HRESULT WINAPI ULTDXCoreCreateAdapterFactory(REFIID riid, void **ppFactory); +void WINAPI ULTGetSystemInfo(SYSTEM_INFO *pSystemInfo); + +} // namespace NEO diff --git a/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.cpp b/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.cpp index e32d63c02a..805519e038 100644 --- a/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.cpp +++ b/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.cpp @@ -18,12 +18,6 @@ HRESULT WINAPI ULTCreateDXGIFactory(REFIID riid, void **ppFactory) { return S_OK; } -void WINAPI ULTGetSystemInfo(SYSTEM_INFO *pSystemInfo) { - pSystemInfo->lpMaximumApplicationAddress = is32bit ? (LPVOID)MemoryConstants::max32BitAppAddress : (LPVOID)MemoryConstants::max64BitAppAddress; -} - const wchar_t *UltIDXGIAdapter1::description = L"Intel"; -extern uint32_t numRootDevicesToEnum = 1; - } // namespace NEO diff --git a/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.h b/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.h index ee97af6312..ece1b28f1e 100644 --- a/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.h +++ b/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.h @@ -187,6 +187,5 @@ class UltIDXGIFactory1 : public IDXGIFactory1 { } }; HRESULT WINAPI ULTCreateDXGIFactory(REFIID riid, void **ppFactory); -void WINAPI ULTGetSystemInfo(SYSTEM_INFO *pSystemInfo); } // namespace NEO 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 49c0c321b3..0b1578e165 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp +++ b/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp @@ -32,7 +32,7 @@ #include "opencl/test/unit_test/mocks/mock_memory_manager.h" #include "opencl/test/unit_test/mocks/mock_wddm_residency_logger.h" #include "opencl/test/unit_test/os_interface/windows/mock_wddm_allocation.h" -#include "opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.h" +#include "opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.h" #include "opencl/test/unit_test/os_interface/windows/wddm_fixture.h" #include "gtest/gtest.h" @@ -141,8 +141,8 @@ TEST(WddmDiscoverDevices, givenMultipleRootDevicesExposedWhenCreateMultipleRootD } TEST(WddmDiscoverDevices, WhenAdapterDescriptionContainsVirtualRenderThenAdapterIsDiscovered) { - VariableBackup descriptionBackup(&UltIDXGIAdapter1::description); - descriptionBackup = L"Virtual Render"; + VariableBackup descriptionBackup(&UltDxCoreAdapter::description); + descriptionBackup = "Virtual Render"; ExecutionEnvironment executionEnvironment; auto hwDeviceIds = OSInterface::discoverDevices(executionEnvironment); @@ -1552,4 +1552,4 @@ TEST_F(WddmTestWithMockGdiDll, givenValidInputwhenSettingAllocationPriorityThenT EXPECT_TRUE(wddm->setAllocationPriority(handles, 2, DXGI_RESOURCE_PRIORITY_NORMAL)); EXPECT_EQ(DXGI_RESOURCE_PRIORITY_NORMAL, getLastPriorityFcn()); -} \ No newline at end of file +} diff --git a/opencl/test/unit_test/os_interface/windows/wddm_calls.cpp b/opencl/test/unit_test/os_interface/windows/wddm_calls.cpp index 3489a7940c..5acd4a98c8 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm_calls.cpp +++ b/opencl/test/unit_test/os_interface/windows/wddm_calls.cpp @@ -8,6 +8,7 @@ #include "shared/source/memory_manager/host_ptr_defines.h" #include "opencl/test/unit_test/mocks/mock_wddm.h" +#include "opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.h" #include "opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.h" namespace NEO { @@ -19,11 +20,14 @@ BOOL WINAPI ULTVirtualFree(LPVOID ptr, SIZE_T size, DWORD flags) { LPVOID WINAPI ULTVirtualAlloc(LPVOID inPtr, SIZE_T size, DWORD flags, DWORD type) { return reinterpret_cast(virtualAllocAddress); } - Wddm::CreateDXGIFactoryFcn getCreateDxgiFactory() { return ULTCreateDXGIFactory; } +Wddm::DXCoreCreateAdapterFactoryFcn getDXCoreCreateAdapterFactory() { + return ULTDXCoreCreateAdapterFactory; +} + Wddm::GetSystemInfoFcn getGetSystemInfo() { return ULTGetSystemInfo; } diff --git a/shared/source/os_interface/windows/wddm/adapter_info.cpp b/shared/source/os_interface/windows/wddm/adapter_info.cpp index bc2351f561..076fd2e319 100644 --- a/shared/source/os_interface/windows/wddm/adapter_info.cpp +++ b/shared/source/os_interface/windows/wddm/adapter_info.cpp @@ -7,8 +7,10 @@ #include "shared/source/os_interface/windows/wddm/adapter_info.h" +#include "shared/source/debug_settings/debug_settings_manager.h" #include "shared/source/helpers/debug_helpers.h" #include "shared/source/os_interface/windows/gdi_interface.h" +#include "shared/source/utilities/stackvec.h" #include @@ -46,4 +48,178 @@ std::wstring queryAdapterDriverStorePath(const Gdi &gdi, D3DKMT_HANDLE adapter) return std::wstring(std::wstring(queryRegistryInfoValueDesc.OutputString, queryRegistryInfoValueDesc.OutputString + queryRegistryInfoValueDesc.OutputValueSize / sizeof(wchar_t)).c_str()); } + +bool canUseAdapterBasedOnDriverDesc(const char *driverDescription) { + return (strstr(driverDescription, "Intel") != nullptr) || + (strstr(driverDescription, "Citrix") != nullptr) || + (strstr(driverDescription, "Virtual Render") != nullptr); +} + +bool isAllowedDeviceId(uint32_t deviceId) { + if (DebugManager.flags.ForceDeviceId.get() == "unk") { + return true; + } + + char *endptr = nullptr; + auto reqDeviceId = strtoul(DebugManager.flags.ForceDeviceId.get().c_str(), &endptr, 16); + return (static_cast(reqDeviceId) == deviceId); +} + +DxCoreAdapterFactory::DxCoreAdapterFactory(DXCoreCreateAdapterFactoryFcn createAdapterFactoryFcn) : createAdapterFactoryFcn(createAdapterFactoryFcn) { + if (nullptr == createAdapterFactoryFcn) { + return; + } + + HRESULT hr = createAdapterFactoryFcn(__uuidof(IDXCoreAdapterFactory), (void **)(&adapterFactory)); + if (hr != S_OK) { + adapterFactory = nullptr; + } +} + +DxCoreAdapterFactory::~DxCoreAdapterFactory() { + destroyCurrentSnapshot(); + + if (adapterFactory) { + adapterFactory->Release(); + adapterFactory = nullptr; + } +} + +bool DxCoreAdapterFactory::createSnapshotOfAvailableAdapters() { + if (false == this->isSupported()) { + DEBUG_BREAK_IF(true); + return false; + } + destroyCurrentSnapshot(); + + GUID attributes[]{DXCORE_ADAPTER_ATTRIBUTE_D3D12_CORE_COMPUTE}; + HRESULT hr = adapterFactory->CreateAdapterList(1, attributes, __uuidof(IDXCoreAdapterList), (void **)(&adaptersInSnapshot)); + if ((hr != S_OK) || (adaptersInSnapshot == nullptr)) { + DEBUG_BREAK_IF(true); + destroyCurrentSnapshot(); + return false; + } + + return true; +} + +uint32_t DxCoreAdapterFactory::getNumAdaptersInSnapshot() { + if (nullptr == adaptersInSnapshot) { + return 0U; + } + return adaptersInSnapshot->GetAdapterCount(); +} + +bool DxCoreAdapterFactory::getAdapterDesc(uint32_t ordinal, AdapterDesc &outAdapter) { + if (ordinal >= getNumAdaptersInSnapshot()) { + DEBUG_BREAK_IF(true); + return false; + } + + IDXCoreAdapter *adapter = nullptr; + HRESULT hr = adaptersInSnapshot->GetAdapter(ordinal, __uuidof(IDXCoreAdapter), (void **)&adapter); + if ((hr != S_OK) || (adapter == nullptr)) { + return false; + } + + outAdapter = {}; + bool isHardware = false; + hr = adapter->GetProperty(DXCoreAdapterProperty::IsHardware, &isHardware); + DEBUG_BREAK_IF(S_OK != hr); + outAdapter.type = isHardware ? AdapterDesc::Type::Hardware : AdapterDesc::Type::NotHardware; + + static constexpr uint32_t maxDriverDescriptionStaticSize = 512; + StackVec driverDescription; + size_t driverDescSize = 0; + hr = adapter->GetPropertySize(DXCoreAdapterProperty::DriverDescription, &driverDescSize); + if (S_OK == hr) { + driverDescription.resize(driverDescSize); + } + hr = adapter->GetProperty(DXCoreAdapterProperty::DriverDescription, driverDescription.size(), driverDescription.data()); + if (S_OK != hr) { + adapter->Release(); + DEBUG_BREAK_IF(true); + return false; + } + outAdapter.driverDescription = driverDescription.data(); + + DXCoreHardwareID hwId = {}; + adapter->GetProperty(DXCoreAdapterProperty::HardwareID, sizeof(hwId), &hwId); + DEBUG_BREAK_IF(S_OK == hr); + outAdapter.deviceId = hwId.deviceID; + + LUID luid = {}; + hr = adapter->GetProperty(DXCoreAdapterProperty::InstanceLuid, &luid); + if (S_OK != hr) { + adapter->Release(); + DEBUG_BREAK_IF(true); + return false; + } + outAdapter.luid = luid; + adapter->Release(); + return true; +} + +void DxCoreAdapterFactory::destroyCurrentSnapshot() { + if (adaptersInSnapshot) { + adaptersInSnapshot->Release(); + adaptersInSnapshot = nullptr; + } +} + +DxgiAdapterFactory::DxgiAdapterFactory(CreateDXGIFactoryFcn createAdapterFactoryFcn) : createAdapterFactoryFcn(createAdapterFactoryFcn) { + if (nullptr == createAdapterFactoryFcn) { + return; + } + + HRESULT hr = createAdapterFactoryFcn(__uuidof(IDXGIFactory), (void **)(&adapterFactory)); + if (hr != S_OK) { + adapterFactory = nullptr; + } +} + +bool DxgiAdapterFactory::getAdapterDesc(uint32_t ordinal, AdapterDesc &outAdapter) { + if (ordinal >= getNumAdaptersInSnapshot()) { + DEBUG_BREAK_IF(true); + return false; + } + + outAdapter = adaptersInSnapshot[ordinal]; + return true; +} + +bool DxgiAdapterFactory::createSnapshotOfAvailableAdapters() { + if (false == this->isSupported()) { + DEBUG_BREAK_IF(true); + return false; + } + destroyCurrentSnapshot(); + + uint32_t ordinal = 0; + IDXGIAdapter1 *adapter = nullptr; + while (adapterFactory->EnumAdapters1(ordinal++, &adapter) != DXGI_ERROR_NOT_FOUND) { + DXGI_ADAPTER_DESC1 adapterDesc = {{0}}; + HRESULT hr = adapter->GetDesc1(&adapterDesc); + if (hr != S_OK) { + adapter->Release(); + DEBUG_BREAK_IF(true); + continue; + } + + adaptersInSnapshot.resize(adaptersInSnapshot.size() + 1); + auto &dstAdapterDesc = *adaptersInSnapshot.rbegin(); + dstAdapterDesc.luid = adapterDesc.AdapterLuid; + dstAdapterDesc.deviceId = adapterDesc.DeviceId; + static constexpr auto driverDescMaxChars = sizeof(adapterDesc.Description) / sizeof(adapterDesc.Description[0]); + dstAdapterDesc.driverDescription.reserve(driverDescMaxChars); + for (auto wchar : std::wstring(std::wstring(adapterDesc.Description, adapterDesc.Description + driverDescMaxChars).c_str())) { + dstAdapterDesc.driverDescription.push_back(static_cast(wchar)); + } + + adapter->Release(); + } + + return true; +} + } // namespace NEO diff --git a/shared/source/os_interface/windows/wddm/adapter_info.h b/shared/source/os_interface/windows/wddm/adapter_info.h index 59e10cc369..6d6c6e855c 100644 --- a/shared/source/os_interface/windows/wddm/adapter_info.h +++ b/shared/source/os_interface/windows/wddm/adapter_info.h @@ -7,7 +7,15 @@ #pragma once +// clang-format off +#include +#include +#include +// clang-format on + #include +#include +#include typedef unsigned int D3DKMT_HANDLE; @@ -17,4 +25,122 @@ class Gdi; std::wstring queryAdapterDriverStorePath(const Gdi &gdi, D3DKMT_HANDLE adapter); +bool canUseAdapterBasedOnDriverDesc(const char *driverDescription); + +bool isAllowedDeviceId(uint32_t deviceId); + +class AdapterFactory { + public: + struct AdapterDesc { + enum class Type { + Unknown, + Hardware, + NotHardware + }; + + Type type = Type::Unknown; + std::string driverDescription; + uint32_t deviceId = {}; + LUID luid = {}; + }; + + virtual ~AdapterFactory() = default; + + virtual bool createSnapshotOfAvailableAdapters() = 0; + virtual uint32_t getNumAdaptersInSnapshot() = 0; + virtual bool getAdapterDesc(uint32_t ordinal, AdapterDesc &outAdapter) = 0; + virtual bool isSupported() = 0; +}; + +class DxCoreAdapterFactory : public AdapterFactory { + public: + using DXCoreCreateAdapterFactoryFcn = HRESULT(WINAPI *)(REFIID riid, void **ppFactory); + DxCoreAdapterFactory(DXCoreCreateAdapterFactoryFcn createAdapterFactoryFcn); + + ~DxCoreAdapterFactory() override; + + bool createSnapshotOfAvailableAdapters() override; + + bool isSupported() { + return nullptr != adapterFactory; + } + + uint32_t getNumAdaptersInSnapshot() override; + + bool getAdapterDesc(uint32_t ordinal, AdapterDesc &outAdapter) override; + + protected: + void destroyCurrentSnapshot(); + + DXCoreCreateAdapterFactoryFcn createAdapterFactoryFcn = nullptr; + IDXCoreAdapterFactory *adapterFactory = nullptr; + IDXCoreAdapterList *adaptersInSnapshot = nullptr; +}; + +class DxgiAdapterFactory : public AdapterFactory { + public: + using CreateDXGIFactoryFcn = HRESULT(WINAPI *)(REFIID riid, void **ppFactory); + DxgiAdapterFactory(CreateDXGIFactoryFcn createAdapterFactoryFcn); + + ~DxgiAdapterFactory() override { + destroyCurrentSnapshot(); + if (adapterFactory) { + adapterFactory->Release(); + } + } + + bool createSnapshotOfAvailableAdapters() override; + + bool isSupported() { + return nullptr != adapterFactory; + } + + uint32_t getNumAdaptersInSnapshot() { + return static_cast(adaptersInSnapshot.size()); + } + + bool getAdapterDesc(uint32_t ordinal, AdapterDesc &outAdapter) override; + + protected: + void destroyCurrentSnapshot() { + adaptersInSnapshot.clear(); + } + + CreateDXGIFactoryFcn createAdapterFactoryFcn = nullptr; + IDXGIFactory1 *adapterFactory = nullptr; + std::vector adaptersInSnapshot; +}; + +class WddmAdapterFactory : public AdapterFactory { + public: + WddmAdapterFactory(DxCoreAdapterFactory::DXCoreCreateAdapterFactoryFcn dxCoreCreateAdapterFactoryF, + DxgiAdapterFactory::CreateDXGIFactoryFcn dxgiCreateAdapterFactoryF) { + underlyingFactory = std::make_unique(dxCoreCreateAdapterFactoryF); + if (false == underlyingFactory->isSupported()) { + underlyingFactory = std::make_unique(dxgiCreateAdapterFactoryF); + } + } + + ~WddmAdapterFactory() override = default; + + bool createSnapshotOfAvailableAdapters() override { + return underlyingFactory->createSnapshotOfAvailableAdapters(); + } + + bool isSupported() override { + return underlyingFactory->isSupported(); + } + + uint32_t getNumAdaptersInSnapshot() override { + return underlyingFactory->getNumAdaptersInSnapshot(); + } + + bool getAdapterDesc(uint32_t ordinal, AdapterDesc &outAdapter) override { + return underlyingFactory->getAdapterDesc(ordinal, outAdapter); + } + + protected: + std::unique_ptr underlyingFactory; +}; + } // namespace NEO diff --git a/shared/source/os_interface/windows/wddm/wddm.cpp b/shared/source/os_interface/windows/wddm/wddm.cpp index fb2b2ddec4..b7431bfb25 100644 --- a/shared/source/os_interface/windows/wddm/wddm.cpp +++ b/shared/source/os_interface/windows/wddm/wddm.cpp @@ -25,6 +25,7 @@ #include "shared/source/os_interface/windows/os_context_win.h" #include "shared/source/os_interface/windows/os_environment_win.h" #include "shared/source/os_interface/windows/os_interface.h" +#include "shared/source/os_interface/windows/wddm/adapter_info.h" #include "shared/source/os_interface/windows/wddm/um_km_data_translator.h" #include "shared/source/os_interface/windows/wddm/wddm_interface.h" #include "shared/source/os_interface/windows/wddm/wddm_residency_logger.h" @@ -37,14 +38,20 @@ #include "gmm_client_context.h" #include "gmm_memory.h" +// clang-format off +#include +#include #include +// clang-format on namespace NEO { extern Wddm::CreateDXGIFactoryFcn getCreateDxgiFactory(); +extern Wddm::DXCoreCreateAdapterFactoryFcn getDXCoreCreateAdapterFactory(); extern Wddm::GetSystemInfoFcn getGetSystemInfo(); extern Wddm::VirtualAllocFcn getVirtualAlloc(); extern Wddm::VirtualFreeFcn getVirtualFree(); +Wddm::DXCoreCreateAdapterFactoryFcn Wddm::dXCoreCreateAdapterFactory = getDXCoreCreateAdapterFactory(); Wddm::CreateDXGIFactoryFcn Wddm::createDxgiFactory = getCreateDxgiFactory(); Wddm::GetSystemInfoFcn Wddm::getSystemInfo = getGetSystemInfo(); Wddm::VirtualAllocFcn Wddm::virtualAllocFnc = getVirtualAlloc(); @@ -61,9 +68,6 @@ Wddm::Wddm(std::unique_ptr hwDeviceIdIn, RootDeviceEnvironment &root this->registryReader.reset(new RegistryReader(false, "System\\CurrentControlSet\\Control\\GraphicsDrivers\\Scheduler")); kmDafListener = std::unique_ptr(new KmDafListener); temporaryResources = std::make_unique(this); - if (hwDeviceIdIn && this->rootDeviceEnvironment.getGmmHelper()) { - this->rootDeviceEnvironment.getGmmClientContext()->setHandleAllocator(hwDeviceIdIn->getUmKmDataTranslator()->createGmmHandleAllocator()); - } } Wddm::~Wddm() { @@ -107,6 +111,7 @@ bool Wddm::init() { auto preemptionMode = PreemptionHelper::getDefaultPreemptionMode(*hardwareInfo); rootDeviceEnvironment.setHwInfo(hardwareInfo.get()); rootDeviceEnvironment.initGmm(); + this->rootDeviceEnvironment.getGmmClientContext()->setHandleAllocator(this->hwDeviceId->getUmKmDataTranslator()->createGmmHandleAllocator()); if (WddmVersion::WDDM_2_3 == getWddmVersion()) { wddmInterface = std::make_unique(*this); @@ -292,24 +297,19 @@ std::unique_ptr createHwDeviceIdFromAdapterLuid(OsEnvironmentWin &os } std::vector> OSInterface::discoverDevices(ExecutionEnvironment &executionEnvironment) { - std::vector> hwDeviceIds; auto osEnvironment = new OsEnvironmentWin(); auto gdi = osEnvironment->gdi.get(); executionEnvironment.osEnvironment.reset(osEnvironment); if (!gdi->isInitialized()) { - return hwDeviceIds; + return {}; } - DXGI_ADAPTER_DESC1 OpenAdapterDesc = {{0}}; + WddmAdapterFactory adapterFactory{Wddm::dXCoreCreateAdapterFactory, Wddm::createDxgiFactory}; - IDXGIFactory1 *pFactory = nullptr; - IDXGIAdapter1 *pAdapter = nullptr; - - HRESULT hr = Wddm::createDxgiFactory(__uuidof(IDXGIFactory), (void **)(&pFactory)); - if ((hr != S_OK) || (pFactory == nullptr)) { - return hwDeviceIds; + if (false == adapterFactory.isSupported()) { + return {}; } size_t numRootDevices = 0u; @@ -317,32 +317,38 @@ std::vector> OSInterface::discoverDevices(ExecutionE numRootDevices = DebugManager.flags.CreateMultipleRootDevices.get(); } + std::vector> hwDeviceIds; do { - DWORD iDevNum = 0; - while (pFactory->EnumAdapters1(iDevNum++, &pAdapter) != DXGI_ERROR_NOT_FOUND) { - hr = pAdapter->GetDesc1(&OpenAdapterDesc); - if (hr == S_OK) { - bool createHwDeviceId = false; - // Check for adapters that include either "Intel" or "Citrix" (which may - // be virtualizing one of our adapters) in the description - if ((wcsstr(OpenAdapterDesc.Description, L"Intel") != 0) || - (wcsstr(OpenAdapterDesc.Description, L"Citrix") != 0) || - (wcsstr(OpenAdapterDesc.Description, L"Virtual Render") != 0)) { - char deviceId[16]; - sprintf_s(deviceId, "%X", OpenAdapterDesc.DeviceId); - createHwDeviceId = (DebugManager.flags.ForceDeviceId.get() == "unk") || (DebugManager.flags.ForceDeviceId.get() == deviceId); - } - if (createHwDeviceId) { - auto hwDeviceId = createHwDeviceIdFromAdapterLuid(*osEnvironment, OpenAdapterDesc.AdapterLuid); - if (hwDeviceId) { - hwDeviceIds.push_back(std::move(hwDeviceId)); - } - } + if (false == adapterFactory.createSnapshotOfAvailableAdapters()) { + return hwDeviceIds; + } + + auto adapterCount = adapterFactory.getNumAdaptersInSnapshot(); + for (uint32_t i = 0; i < adapterCount; ++i) { + AdapterFactory::AdapterDesc adapterDesc; + if (false == adapterFactory.getAdapterDesc(i, adapterDesc)) { + DEBUG_BREAK_IF(true); + continue; } - // Release all the non-Intel adapters - pAdapter->Release(); - pAdapter = nullptr; - if (!hwDeviceIds.empty() && hwDeviceIds.size() == numRootDevices) { + + if (adapterDesc.type == AdapterFactory::AdapterDesc::Type::NotHardware) { + continue; + } + + if (false == canUseAdapterBasedOnDriverDesc(adapterDesc.driverDescription.c_str())) { + continue; + } + + if (false == isAllowedDeviceId(adapterDesc.deviceId)) { + continue; + } + + auto hwDeviceId = createHwDeviceIdFromAdapterLuid(*osEnvironment, adapterDesc.luid); + if (hwDeviceId) { + hwDeviceIds.push_back(std::move(hwDeviceId)); + } + + if (hwDeviceIds.size() == numRootDevices) { break; } } @@ -351,10 +357,6 @@ std::vector> OSInterface::discoverDevices(ExecutionE } } while (hwDeviceIds.size() < numRootDevices); - if (pFactory != nullptr) { - pFactory->Release(); - pFactory = nullptr; - } return hwDeviceIds; } diff --git a/shared/source/os_interface/windows/wddm/wddm.h b/shared/source/os_interface/windows/wddm/wddm.h index 2ad2f70d27..3355656ad0 100644 --- a/shared/source/os_interface/windows/wddm/wddm.h +++ b/shared/source/os_interface/windows/wddm/wddm.h @@ -44,6 +44,7 @@ enum class HeapIndex : uint32_t; class Wddm { public: typedef HRESULT(WINAPI *CreateDXGIFactoryFcn)(REFIID riid, void **ppFactory); + typedef HRESULT(WINAPI *DXCoreCreateAdapterFactoryFcn)(REFIID riid, void **ppFactory); 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); @@ -158,6 +159,7 @@ class Wddm { WddmVersion getWddmVersion(); static CreateDXGIFactoryFcn createDxgiFactory; + static DXCoreCreateAdapterFactoryFcn dXCoreCreateAdapterFactory; uint32_t getRequestedEUCount() const; diff --git a/shared/source/os_interface/windows/wddm/wddm_calls.cpp b/shared/source/os_interface/windows/wddm/wddm_calls.cpp index 3d4bcc7e5b..3b319a3f43 100644 --- a/shared/source/os_interface/windows/wddm/wddm_calls.cpp +++ b/shared/source/os_interface/windows/wddm/wddm_calls.cpp @@ -7,11 +7,16 @@ #include "shared/source/os_interface/windows/wddm/wddm.h" +#include #include namespace NEO { Wddm::CreateDXGIFactoryFcn getCreateDxgiFactory() { - return CreateDXGIFactory; + return DXCoreCreateAdapterFactory; +} + +Wddm::DXCoreCreateAdapterFactoryFcn getDXCoreCreateAdapterFactory() { + return DXCoreCreateAdapterFactory; } Wddm::GetSystemInfoFcn getGetSystemInfo() { diff --git a/shared/test/unit_test/CMakeLists.txt b/shared/test/unit_test/CMakeLists.txt index a9963ef2d7..7ad323665e 100644 --- a/shared/test/unit_test/CMakeLists.txt +++ b/shared/test/unit_test/CMakeLists.txt @@ -83,6 +83,7 @@ if(NOT SKIP_UNIT_TESTS) ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/create_wddm_memory_manager.cpp ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/options.cpp ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/sys_calls.cpp + ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.cpp ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.cpp ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/wddm_calls.cpp ${NEO_SOURCE_DIR}/opencl/test/unit_test/os_interface/windows/wddm_create.cpp diff --git a/shared/test/unit_test/os_interface/windows/adapter_info_tests.cpp b/shared/test/unit_test/os_interface/windows/adapter_info_tests.cpp index 261db82780..bbc9165c44 100644 --- a/shared/test/unit_test/os_interface/windows/adapter_info_tests.cpp +++ b/shared/test/unit_test/os_interface/windows/adapter_info_tests.cpp @@ -7,8 +7,29 @@ #include "shared/test/unit_test/os_interface/windows/adapter_info_tests.h" +#include "shared/source/os_interface/windows/wddm/adapter_info.h" +#include "shared/test/common/helpers/debug_manager_state_restore.h" + +#include "opencl/test/unit_test/os_interface/windows/ult_dxcore_factory.h" +#include "opencl/test/unit_test/os_interface/windows/ult_dxgi_factory.h" #include "test.h" +#include + +HRESULT(WINAPI failCreateTopLevelInterface) +(REFIID riid, void **ppFactory) { + return -1; +} + +template +HRESULT(WINAPI createTopLevelInterface) +(REFIID riid, void **ppFactory) { + auto obj = std::make_unique(); + *reinterpret_cast(ppFactory) = obj.get(); + obj.release(); + return S_OK; +} + TEST(AdapterInfoTest, whenQueryingForDriverStorePathThenProvidesEnoughMemoryForReturnString) { NEO::Gdi gdi; auto handle = validHandle; @@ -18,3 +39,147 @@ TEST(AdapterInfoTest, whenQueryingForDriverStorePathThenProvidesEnoughMemoryForR EXPECT_EQ(std::wstring(driverStorePathStr), ret) << "Expected " << driverStorePathStr << ", got : " << ret; } + +TEST(DxCoreAdapterFactory, whenCouldNotCreateAdapterFactoryThenReturnsUnsupported) { + { + NEO::DxCoreAdapterFactory adapterFactor{nullptr}; + EXPECT_FALSE(adapterFactor.isSupported()); + } + + { + NEO::DxCoreAdapterFactory adapterFactory{failCreateTopLevelInterface}; + EXPECT_FALSE(adapterFactory.isSupported()); + } +} + +TEST(DxCoreAdapterFactory, whenCreatedAdapterFactoryThenReturnsSupported) { + NEO::DxCoreAdapterFactory adapterFactory{&createTopLevelInterface}; + EXPECT_TRUE(adapterFactory.isSupported()); +} + +TEST(DxCoreAdapterFactory, whenSupportedButSnapshotOfAdaptersNotCreatedThenReturnsEmptyListOfAdapters) { + NEO::DxCoreAdapterFactory adapterFactory{&createTopLevelInterface}; + EXPECT_EQ(0U, adapterFactory.getNumAdaptersInSnapshot()); + + NEO::AdapterFactory::AdapterDesc adapterDesc; + EXPECT_FALSE(adapterFactory.getAdapterDesc(0, adapterDesc)); +} + +TEST(DxCoreAdapterFactory, whenSupportedThenGiveAccessToUnderlyingAdapterDesc) { + NEO::DxCoreAdapterFactory adapterFactory{&createTopLevelInterface}; + + bool createdSnapshot = adapterFactory.createSnapshotOfAvailableAdapters(); + EXPECT_TRUE(createdSnapshot); + EXPECT_EQ(1U, adapterFactory.getNumAdaptersInSnapshot()); + + NEO::AdapterFactory::AdapterDesc adapterDesc; + bool retreivedAdapterDesc = adapterFactory.getAdapterDesc(0, adapterDesc); + EXPECT_TRUE(retreivedAdapterDesc); + EXPECT_EQ(NEO::AdapterFactory::AdapterDesc::Type::Hardware, adapterDesc.type); + EXPECT_EQ(0x1234U, adapterDesc.deviceId); + EXPECT_EQ(0x1234U, adapterDesc.luid.HighPart); + EXPECT_EQ(0U, adapterDesc.luid.LowPart); + EXPECT_STREQ("Intel", adapterDesc.driverDescription.c_str()); +} + +TEST(DxgiAdapterFactory, whenCouldNotCreateAdapterFactoryThenReturnsUnsupported) { + { + NEO::DxgiAdapterFactory adapterFactory{nullptr}; + EXPECT_FALSE(adapterFactory.isSupported()); + } + + { + NEO::DxgiAdapterFactory adapterFactory{failCreateTopLevelInterface}; + EXPECT_FALSE(adapterFactory.isSupported()); + } +} + +TEST(DxgiAdapterFactory, whenCreatedAdapterFactoryThenReturnsSupported) { + NEO::DxgiAdapterFactory adapterFactory{&createTopLevelInterface}; + EXPECT_TRUE(adapterFactory.isSupported()); +} + +TEST(DxgiAdapterFactory, whenSupportedButSnapshotOfAdaptersNotCreatedThenReturnsEmptyListOfAdapters) { + NEO::DxgiAdapterFactory adapterFactory{&createTopLevelInterface}; + EXPECT_EQ(0U, adapterFactory.getNumAdaptersInSnapshot()); + + NEO::AdapterFactory::AdapterDesc adapterDesc; + EXPECT_FALSE(adapterFactory.getAdapterDesc(0, adapterDesc)); +} + +TEST(DxgiAdapterFactory, whenSupportedThenGiveAccessToUnderlyingAdapterDesc) { + NEO::DxgiAdapterFactory adapterFactory{&createTopLevelInterface}; + + bool createdSnapshot = adapterFactory.createSnapshotOfAvailableAdapters(); + EXPECT_TRUE(createdSnapshot); + EXPECT_EQ(1U, adapterFactory.getNumAdaptersInSnapshot()); + + NEO::AdapterFactory::AdapterDesc adapterDesc; + bool retreivedAdapterDesc = adapterFactory.getAdapterDesc(0, adapterDesc); + EXPECT_TRUE(retreivedAdapterDesc); + EXPECT_EQ(NEO::AdapterFactory::AdapterDesc::Type::Unknown, adapterDesc.type); + EXPECT_EQ(0x1234U, adapterDesc.deviceId); + EXPECT_EQ(0x1234U, adapterDesc.luid.HighPart); + EXPECT_EQ(0U, adapterDesc.luid.LowPart); + EXPECT_STREQ("Intel", adapterDesc.driverDescription.c_str()); +} + +TEST(WddmAdapterFactory, whenCouldNotCreateAdapterFactoryThenReturnsUnsupported) { + { + NEO::WddmAdapterFactory adapterFactory{nullptr, nullptr}; + EXPECT_FALSE(adapterFactory.isSupported()); + } + + { + NEO::WddmAdapterFactory adapterFactory{failCreateTopLevelInterface, failCreateTopLevelInterface}; + EXPECT_FALSE(adapterFactory.isSupported()); + } +} + +TEST(WddmAdapterFactory, whenDxCoreAdapterFactoryNotAvailableThenFallbacksToDxgiAdapterFactory) { + NEO::WddmAdapterFactory adapterFactory{failCreateTopLevelInterface, &createTopLevelInterface}; + EXPECT_TRUE(adapterFactory.isSupported()); +} + +TEST(WddmAdapterFactory, whenSupportedThenGiveAccessToUnderlyingAdapterDesc) { + NEO::WddmAdapterFactory adapterFactory{&createTopLevelInterface, &createTopLevelInterface}; + + bool createdSnapshot = adapterFactory.createSnapshotOfAvailableAdapters(); + EXPECT_TRUE(createdSnapshot); + EXPECT_EQ(1U, adapterFactory.getNumAdaptersInSnapshot()); + + NEO::AdapterFactory::AdapterDesc adapterDesc; + bool retreivedAdapterDesc = adapterFactory.getAdapterDesc(0, adapterDesc); + EXPECT_TRUE(retreivedAdapterDesc); + EXPECT_EQ(NEO::AdapterFactory::AdapterDesc::Type::Hardware, adapterDesc.type); + EXPECT_EQ(0x1234U, adapterDesc.deviceId); + EXPECT_EQ(0x1234U, adapterDesc.luid.HighPart); + EXPECT_EQ(0U, adapterDesc.luid.LowPart); + EXPECT_STREQ("Intel", adapterDesc.driverDescription.c_str()); +} + +TEST(IsAllowedDeviceId, whenDebugKeyNotSetThenReturnTrue) { + EXPECT_TRUE(NEO::isAllowedDeviceId(0xdeadbeef)); +} + +TEST(IsAllowedDeviceId, whenDebugKeySetThenExpectSpecificValue) { + DebugManagerStateRestore rest; + DebugManager.flags.ForceDeviceId.set("167"); + EXPECT_FALSE(NEO::isAllowedDeviceId(0xdeadbeef)); + + DebugManager.flags.ForceDeviceId.set("1678"); + EXPECT_FALSE(NEO::isAllowedDeviceId(0x167)); + + DebugManager.flags.ForceDeviceId.set("167"); + EXPECT_TRUE(NEO::isAllowedDeviceId(0x167)); +} + +TEST(IsAllowedDeviceId, whenDebugKeySetThenTreatAsHex) { + DebugManagerStateRestore rest; + + DebugManager.flags.ForceDeviceId.set("167"); + EXPECT_FALSE(NEO::isAllowedDeviceId(167)); + + DebugManager.flags.ForceDeviceId.set("167"); + EXPECT_TRUE(NEO::isAllowedDeviceId(0x167)); +}