Skip to content

Commit

Permalink
Adding driver discovery on windows
Browse files Browse the repository at this point in the history
Signed-off-by: Jaroslaw Chodor <[email protected]>
  • Loading branch information
jchodor committed Mar 20, 2020
1 parent 136a07f commit c9fbe91
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 12 deletions.
4 changes: 4 additions & 0 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ target_link_libraries(${TARGET_LOADER_NAME}
${CMAKE_DL_LIBS}
)

if(WIN32)
target_link_libraries (${TARGET_LOADER_NAME} cfgmgr32.lib)
endif()

install(TARGETS ze_loader
LIBRARY
DESTINATION ${CMAKE_INSTALL_LIBDIR}
Expand Down
13 changes: 13 additions & 0 deletions source/loader/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,26 @@

target_sources(${TARGET_LOADER_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/driver_discovery.h
${CMAKE_CURRENT_SOURCE_DIR}/ze_object.h
${CMAKE_CURRENT_SOURCE_DIR}/ze_loader.h
${CMAKE_CURRENT_SOURCE_DIR}/ze_loader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ze_core_loader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ze_tools_loader.cpp
)

if(WIN32)
target_sources(${TARGET_LOADER_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/windows/driver_discovery_win.cpp
)
else()
target_sources(${TARGET_LOADER_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/linux/driver_discovery_lin.cpp
)
endif()

file(GLOB LEVEL_ZERO_LOADER_INCLUDES
"*.h"
)
Expand Down
20 changes: 20 additions & 0 deletions source/loader/driver_discovery.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/

#pragma once

#include <string>
#include <vector>

namespace loader {

using DriverLibraryPath = std::string;

std::vector<DriverLibraryPath> discoverEnabledDrivers();

} // namespace loader
27 changes: 27 additions & 0 deletions source/loader/linux/driver_discovery_lin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/

#include "source/loader/driver_discovery.h"

#include "source/inc/ze_util.h"

namespace loader {

static const char *knownDriverNames[] = {
MAKE_LIBRARY_NAME("ze_intel_gpu", "0.8"),
};

std::vector<DriverLibraryPath> discoverEnabledDrivers() {
std::vector<DriverLibraryPath> enabledDrivers;
for (auto path : knownDriverNames) {
enabledDrivers.emplace_back(path);
}
return enabledDrivers;
}

} // namespace loader
150 changes: 150 additions & 0 deletions source/loader/windows/driver_discovery_win.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/*
*
* Copyright (C) 2020 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/

#include "source/loader/driver_discovery.h"

#include <Windows.h>

#include <cassert>
#include <cfgmgr32.h>
#include <devpkey.h>
#include <devguid.h>

namespace loader {

std::vector<DriverLibraryPath> discoverDriversBasedOnDisplayAdapters();

std::vector<DriverLibraryPath> discoverEnabledDrivers() {
return discoverDriversBasedOnDisplayAdapters();
}

bool isDeviceAvailable(DEVINST devnode) {
ULONG devStatus = {};
ULONG devProblem = {};
auto configErr = CM_Get_DevNode_Status(&devStatus, &devProblem, devnode, 0);

if (CR_SUCCESS != configErr) {
assert(false && "CM_Get_DevNode_Status failed");
return false;
}

bool isInInvalidState = (devStatus & DN_HAS_PROBLEM)
&& (devProblem == CM_PROB_NEED_RESTART);
isInInvalidState |= (DN_NEED_RESTART == (devStatus & DN_NEED_RESTART));

return false == isInInvalidState;
}

DriverLibraryPath readDriverPathForDisplayAdapter(DEVINST dnDevNode) {
static constexpr char levelZeroDriverPathKey[] = "LevelZeroDriverPath";

HKEY hkey = {};
CONFIGRET configErr = CM_Open_DevNode_Key(dnDevNode, KEY_QUERY_VALUE, 0,
RegDisposition_OpenExisting, &hkey,
CM_REGISTRY_SOFTWARE);

if (CR_SUCCESS != configErr) {
assert(false && "CM_Open_DevNode_Key failed");
return "";
}

DWORD regValueType = {};
DWORD pathSize = {};
LSTATUS regOpStatus = RegQueryValueExA(hkey, levelZeroDriverPathKey, NULL,
&regValueType, NULL, &pathSize);

std::string driverPath;
if ((ERROR_SUCCESS == regOpStatus) && (REG_SZ == regValueType)) {
driverPath.resize(pathSize);
regOpStatus = RegQueryValueExA(hkey, levelZeroDriverPathKey, NULL,
&regValueType, (LPBYTE) & *driverPath.begin(),
&pathSize);
if (ERROR_SUCCESS != regOpStatus) {
assert(false && "RegQueryValueExA failed");
driverPath.clear();
}
}

regOpStatus = RegCloseKey(hkey);
assert((ERROR_SUCCESS == regOpStatus) && "RegCloseKey failed");

return driverPath;
}

std::wstring readDisplayAdaptersDeviceIdsList() {
OLECHAR displayGuidStr[MAX_GUID_STRING_LEN];

int strFromGuidErr = StringFromGUID2(GUID_DEVCLASS_DISPLAY, displayGuidStr,
MAX_GUID_STRING_LEN);
if (MAX_GUID_STRING_LEN != strFromGuidErr) {
assert(false && "StringFromGUID2 failed");
return L"";
}

std::wstring deviceIdList;
CONFIGRET getDeviceIdListErr = CR_BUFFER_SMALL;
while (CR_BUFFER_SMALL == getDeviceIdListErr) {
ULONG deviceIdListSize = {};
ULONG deviceIdListFlags = CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT;
auto getDeviceIdListSizeErr = CM_Get_Device_ID_List_SizeW(&deviceIdListSize,
displayGuidStr,
deviceIdListFlags);
if (CR_SUCCESS != getDeviceIdListSizeErr) {
assert(false && "CM_Get_Device_ID_List_size failed");
break;
}

deviceIdList.resize(deviceIdListSize);
getDeviceIdListErr = CM_Get_Device_ID_ListW(displayGuidStr,
&*deviceIdList.begin(),
deviceIdListSize,
deviceIdListFlags);
}

return deviceIdList;
}

std::vector<DriverLibraryPath> discoverDriversBasedOnDisplayAdapters() {
std::vector<DriverLibraryPath> enabledDrivers;
auto deviceIdList = readDisplayAdaptersDeviceIdsList();
if (deviceIdList.empty()) {
return enabledDrivers;
}

auto isNotDeviceListEnd = [](wchar_t *it) { return '\0' != it[0]; };
auto getNextDeviceInList = [](wchar_t *it) { return it + wcslen(it) + 1; };

auto deviceIdIt = &*deviceIdList.begin();
for (; isNotDeviceListEnd(deviceIdIt); deviceIdIt = getNextDeviceInList(deviceIdIt)) {
DEVINST devinst = {};
if (CR_SUCCESS != CM_Locate_DevNodeW(&devinst, deviceIdIt, 0)) {
assert(false && "CM_Locate_DevNodeW failed");
continue;
}

if (false == isDeviceAvailable(devinst)) {
continue;
}

auto driverPath = readDriverPathForDisplayAdapter(devinst);

if (driverPath.empty()) {
continue;
}

bool alreadyOnTheList = (enabledDrivers.end() != std::find(enabledDrivers.begin(), enabledDrivers.end(), driverPath));
if (alreadyOnTheList) {
continue;
}

enabledDrivers.push_back(std::move(driverPath));
}
return enabledDrivers;
}

} // namespace loader
19 changes: 7 additions & 12 deletions source/loader/ze_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,23 @@
*/
#include "ze_loader.h"

#include "driver_discovery.h"

namespace loader
{
///////////////////////////////////////////////////////////////////////////////
static const char* known_driver_names[] = {
MAKE_LIBRARY_NAME( "ze_intel_gpu", "0.8"),
};

static const size_t num_known_driver_names =
sizeof( known_driver_names ) / sizeof( known_driver_names[ 0 ] );


///////////////////////////////////////////////////////////////////////////////
context_t context;


///////////////////////////////////////////////////////////////////////////////
context_t::context_t()
{
drivers.reserve( num_known_driver_names );
for( auto name : known_driver_names )
auto discoveredDrivers = discoverEnabledDrivers();

drivers.reserve( discoveredDrivers.size() );
for( auto name : discoveredDrivers )
{
auto handle = LOAD_DRIVER_LIBRARY( name );
auto handle = LOAD_DRIVER_LIBRARY( name.c_str() );
if( NULL != handle )
{
drivers.emplace_back();
Expand Down

0 comments on commit c9fbe91

Please sign in to comment.