From 47f05fad43621aa1637427d857d639d0ecfbb7cd Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Thu, 16 Apr 2020 15:37:11 -0700 Subject: [PATCH] Add support for OpenCLOn12 ICD (#103) * Add search for OpenCLOn12 mapping layer package. * Use altered search path for ICD loading. * Update version to 2.2.7 --- CMakeLists.txt | 4 +- loader/windows/OpenCL.rc | 2 +- loader/windows/icd_windows.c | 10 +- loader/windows/icd_windows_apppackage.cpp | 167 ++++++++++++++++++++++ loader/windows/icd_windows_apppackage.h | 25 ++++ 5 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 loader/windows/icd_windows_apppackage.cpp create mode 100644 loader/windows/icd_windows_apppackage.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bafa862..7e0b2254 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,8 @@ if (WIN32) loader/windows/icd_windows_envvars.c loader/windows/icd_windows_hkr.c loader/windows/icd_windows_hkr.h + loader/windows/icd_windows_apppackage.cpp + loader/windows/icd_windows_apppackage.h loader/windows/OpenCL.def loader/windows/OpenCL.rc) # Only add the DXSDK include directory if the environment variable is @@ -78,7 +80,7 @@ add_library (OpenCL ${OPENCL_ICD_LOADER_SOURCES}) set_target_properties (OpenCL PROPERTIES VERSION "1.2" SOVERSION "1") if (WIN32) - target_link_libraries (OpenCL cfgmgr32.lib) + target_link_libraries (OpenCL cfgmgr32.lib RuntimeObject.lib) option (OPENCL_ICD_LOADER_REQUIRE_WDK "Build with D3DKMT support, which requires the Windows WDK." ON) if (OPENCL_ICD_LOADER_REQUIRE_WDK) diff --git a/loader/windows/OpenCL.rc b/loader/windows/OpenCL.rc index db25dfec..38f2c84e 100644 --- a/loader/windows/OpenCL.rc +++ b/loader/windows/OpenCL.rc @@ -20,7 +20,7 @@ #define OPENCL_ICD_LOADER_VERSION_MAJOR 2 #define OPENCL_ICD_LOADER_VERSION_MINOR 2 -#define OPENCL_ICD_LOADER_VERSION_REV 6 +#define OPENCL_ICD_LOADER_VERSION_REV 7 #ifdef RC_INVOKED diff --git a/loader/windows/icd_windows.c b/loader/windows/icd_windows.c index 1350f118..25f1b9b6 100644 --- a/loader/windows/icd_windows.c +++ b/loader/windows/icd_windows.c @@ -20,6 +20,7 @@ #include "icd_windows.h" #include "icd_windows_hkr.h" #include "icd_windows_dxgk.h" +#include "icd_windows_apppackage.h" #include #include #include @@ -123,6 +124,8 @@ BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVO KHR_ICD_TRACE("Failed to enumerate HKR entries, continuing\n"); } } + + status |= khrIcdOsVendorsEnumerateAppPackage(); KHR_ICD_TRACE("Opening key HKLM\\%s...\n", platformsName); result = RegOpenKeyExA( @@ -253,7 +256,12 @@ void khrIcdOsVendorsEnumerateOnce() // dynamically load a library. returns NULL on failure void *khrIcdOsLibraryLoad(const char *libraryName) { - return (void *)LoadLibraryA(libraryName); + HMODULE hTemp = LoadLibraryExA(libraryName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!hTemp && GetLastError() == ERROR_INVALID_PARAMETER) + { + hTemp = LoadLibraryExA(libraryName, NULL, 0); + } + return (void*)hTemp; } // get a function pointer from a loaded library. returns NULL on failure. diff --git a/loader/windows/icd_windows_apppackage.cpp b/loader/windows/icd_windows_apppackage.cpp new file mode 100644 index 00000000..0092c2a1 --- /dev/null +++ b/loader/windows/icd_windows_apppackage.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2017-2019 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +extern "C" +{ +#include "icd.h" +#include "icd_windows.h" +} + +#include "icd_windows_apppackage.h" + +#include +#include +#include + +#include +#include + +template +struct ScopeExit { + ScopeExit(F&& f) : f(std::forward(f)) {} + ~ScopeExit() { f(); } + F f; +}; + +template +inline ScopeExit MakeScopeExit(F&& f) { + return ScopeExit(std::forward(f)); +}; + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +extern "C" bool khrIcdOsVendorsEnumerateAppPackage() +{ + HRESULT hrInit = Windows::Foundation::Initialize(RO_INIT_MULTITHREADED); + if (hrInit == RPC_E_CHANGED_MODE) + { + hrInit = Windows::Foundation::Initialize(RO_INIT_SINGLETHREADED); + } + if (FAILED(hrInit)) + { + KHR_ICD_TRACE("Failed to init WinRT\n"); + return false; + } + auto Cleanup = MakeScopeExit([]() + { + Windows::Foundation::Uninitialize(); + }); + + using ABI::Windows::Management::Deployment::IPackageManager; + ComPtr packageManager; + if (FAILED(Windows::Foundation::ActivateInstance( + HStringReference(RuntimeClass_Windows_Management_Deployment_PackageManager).Get(), + &packageManager))) + { + KHR_ICD_TRACE("Failed to get package manager\n"); + return false; + } + + using IPackageCollection = ABI::Windows::Foundation::Collections::__FIIterable_1_Windows__CApplicationModel__CPackage_t; + ComPtr collection; + if (FAILED(packageManager->FindPackagesByUserSecurityIdPackageFamilyName( + HStringReference(L"").Get(), + HStringReference(L"Microsoft.D3DMappingLayers_8wekyb3d8bbwe").Get(), + &collection))) + { + KHR_ICD_TRACE("Failed to find mapping layers package\n"); + return false; + } + + using IPackageIterator = ABI::Windows::Foundation::Collections::IIterator< + ABI::Windows::ApplicationModel::Package*>; + ComPtr iter; + if (FAILED(collection->First(&iter))) + { + KHR_ICD_TRACE("Failed to get package collection iterator\n"); + return false; + } + + while ([&iter]() + { + boolean hasCurrent = false; + return SUCCEEDED(iter->get_HasCurrent(&hasCurrent)) && hasCurrent; + }()) + { + using ABI::Windows::ApplicationModel::IPackage; + ComPtr package; + if (FAILED(iter->get_Current(&package))) + { + KHR_ICD_TRACE("Failed to get package\n"); + boolean hasCurrent = false; + (void)iter->MoveNext(&hasCurrent); + continue; + } + + boolean hasCurrent = false; + (void)iter->MoveNext(&hasCurrent); + + using ABI::Windows::Storage::IStorageFolder; + ComPtr folder; + if (FAILED(package->get_InstalledLocation(&folder))) + { + KHR_ICD_TRACE("Failed to get package install folder\n"); + continue; + } + + using ABI::Windows::Storage::IStorageItem; + ComPtr item; + if (FAILED(folder.As(&item))) + { + KHR_ICD_TRACE("Failed to convert folder to storage item\n"); + continue; + } + + HString path; + if (FAILED(item->get_Path(path.GetAddressOf()))) + { + KHR_ICD_TRACE("Failed to get path\n"); + continue; + } + + UINT pathSize = 0; + auto rawPath = path.GetRawBuffer(&pathSize); + if (pathSize == 0 || rawPath == nullptr) + { + KHR_ICD_TRACE("Failed to get path\n"); + continue; + } + +#if defined(_M_AMD64) +#define PLATFORM_PATH L"x64" +#elif defined(_M_ARM) +#define PLATFORM_PATH L"arm" +#elif defined(_M_ARM64) +#define PLATFORM_PATH L"arm64" +#elif defined(_M_IX86) +#define PLATFORM_PATH L"x86" +#endif + + wchar_t dllPath[MAX_PATH]; + wcscpy_s(dllPath, rawPath); + wcscat_s(dllPath, L"\\" PLATFORM_PATH L"\\OpenCLOn12.dll"); + + std::wstring_convert> convert; + std::string narrowDllPath = convert.to_bytes(dllPath); + + adapterAdd(narrowDllPath.c_str(), {}); + return true; + } + return false; +} \ No newline at end of file diff --git a/loader/windows/icd_windows_apppackage.h b/loader/windows/icd_windows_apppackage.h new file mode 100644 index 00000000..d4c55da3 --- /dev/null +++ b/loader/windows/icd_windows_apppackage.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017-2019 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +#include +#include "icd_windows.h" + +#ifdef __cplusplus +extern "C" +#endif +bool khrIcdOsVendorsEnumerateAppPackage(void);