Correct CreateMultipleRootDevices logic on Windows

respect CreateMultipleRootDevices flag when multiple adapters are exposed
dont duplicate adapter handles when simulating multiple root devices

Related-To: NEO-3691

Change-Id: I838f831723aeebd8b175502d737ed73eb5df2f21
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski
2020-05-20 17:06:32 +02:00
committed by sys_ocldev
parent 7f02a39f75
commit 3c288df339
4 changed files with 63 additions and 49 deletions

View File

@@ -24,6 +24,6 @@ void WINAPI ULTGetSystemInfo(SYSTEM_INFO *pSystemInfo) {
const wchar_t *UltIDXGIAdapter1::description = L"Intel";
extern uint32_t numRootDevicesToEnum = 0;
extern uint32_t numRootDevicesToEnum = 1;
} // namespace NEO

View File

@@ -7,7 +7,6 @@
#pragma once
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/helpers/constants.h"
#include <cwchar>
@@ -100,13 +99,7 @@ class UltIDXGIFactory1 : public IDXGIFactory1 {
HRESULT STDMETHODCALLTYPE EnumAdapters1(
UINT Adapter,
IDXGIAdapter1 **ppAdapter) {
UINT numRootDevices = 1u;
if (numRootDevicesToEnum > 0u) {
numRootDevices = numRootDevicesToEnum;
} else if (DebugManager.flags.CreateMultipleRootDevices.get()) {
numRootDevices = static_cast<UINT>(DebugManager.flags.CreateMultipleRootDevices.get());
}
if (Adapter >= numRootDevices) {
if (Adapter >= numRootDevicesToEnum) {
*(IDXGIAdapter1 **)ppAdapter = nullptr;
return DXGI_ERROR_NOT_FOUND;
}

View File

@@ -115,6 +115,30 @@ TEST(WddmDiscoverDevices, WhenMultipleRootDevicesAreAvailableThenAllAreDiscovere
EXPECT_EQ(numRootDevicesToEnum, hwDeviceIds.size());
}
TEST(WddmDiscoverDevices, givenMultipleRootDevicesExposedWhenCreateMultipleRootDevicesFlagIsSetToLowerValueThenDiscoverOnlySpecifiedNumberOfDevices) {
DebugManagerStateRestore restorer{};
VariableBackup<uint32_t> backup{&numRootDevicesToEnum};
numRootDevicesToEnum = 3u;
uint32_t requestedNumRootDevices = 2u;
DebugManager.flags.CreateMultipleRootDevices.set(requestedNumRootDevices);
ExecutionEnvironment executionEnvironment;
auto hwDeviceIds = OSInterface::discoverDevices(executionEnvironment);
EXPECT_EQ(requestedNumRootDevices, hwDeviceIds.size());
}
TEST(WddmDiscoverDevices, givenMultipleRootDevicesExposedWhenCreateMultipleRootDevicesFlagIsSetToGreaterValueThenDiscoverSpecifiedNumberOfDevices) {
DebugManagerStateRestore restorer{};
VariableBackup<uint32_t> backup{&numRootDevicesToEnum};
numRootDevicesToEnum = 3u;
uint32_t requestedNumRootDevices = 4u;
DebugManager.flags.CreateMultipleRootDevices.set(requestedNumRootDevices);
ExecutionEnvironment executionEnvironment;
auto hwDeviceIds = OSInterface::discoverDevices(executionEnvironment);
EXPECT_EQ(requestedNumRootDevices, hwDeviceIds.size());
}
TEST(WddmDiscoverDevices, WhenAdapterDescriptionContainsVirtualRenderThenAdapterIsDiscovered) {
VariableBackup<const wchar_t *> descriptionBackup(&UltIDXGIAdapter1::description);
descriptionBackup = L"Virtual Render";

View File

@@ -262,58 +262,55 @@ std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevices(ExecutionE
IDXGIFactory1 *pFactory = nullptr;
IDXGIAdapter1 *pAdapter = nullptr;
DWORD iDevNum = 0;
HRESULT hr = Wddm::createDxgiFactory(__uuidof(IDXGIFactory), (void **)(&pFactory));
if ((hr != S_OK) || (pFactory == nullptr)) {
return hwDeviceIds;
}
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));
}
}
}
// Release all the non-Intel adapters
pAdapter->Release();
pAdapter = nullptr;
size_t numRootDevices = 0u;
if (DebugManager.flags.CreateMultipleRootDevices.get()) {
numRootDevices = DebugManager.flags.CreateMultipleRootDevices.get();
}
if (pAdapter != nullptr) {
pAdapter->Release();
pAdapter = nullptr;
}
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));
}
}
}
// Release all the non-Intel adapters
pAdapter->Release();
pAdapter = nullptr;
if (!hwDeviceIds.empty() && hwDeviceIds.size() == numRootDevices) {
break;
}
}
if (hwDeviceIds.empty()) {
break;
}
} while (hwDeviceIds.size() < numRootDevices);
if (pFactory != nullptr) {
pFactory->Release();
pFactory = nullptr;
}
size_t numRootDevices = 1u;
if (DebugManager.flags.CreateMultipleRootDevices.get()) {
numRootDevices = DebugManager.flags.CreateMultipleRootDevices.get();
}
if (hwDeviceIds.empty()) {
return hwDeviceIds;
}
while (hwDeviceIds.size() < numRootDevices) {
hwDeviceIds.push_back(std::make_unique<HwDeviceId>(hwDeviceIds[0]->getAdapter(), hwDeviceIds[0]->getAdapterLuid(), osEnvironment));
}
return hwDeviceIds;
}