Add support for OpenCLOn12 ICD (#103)
authorJesse Natalie <jenatali@microsoft.com>
Thu, 16 Apr 2020 22:37:11 +0000 (15:37 -0700)
committerGitHub <noreply@github.com>
Thu, 16 Apr 2020 22:37:11 +0000 (15:37 -0700)
* Add search for OpenCLOn12 mapping layer package.

* Use altered search path for ICD loading.

* Update version to 2.2.7

CMakeLists.txt
loader/windows/OpenCL.rc
loader/windows/icd_windows.c
loader/windows/icd_windows_apppackage.cpp [new file with mode: 0644]
loader/windows/icd_windows_apppackage.h [new file with mode: 0644]

index 4bafa862e2dd336f80fa3c31948dbef0169d8589..7e0b2254b5d9c241c89d5bbc186522db3d9cc2da 100644 (file)
@@ -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)
index db25dfecbcc854548dbe0463e935980216a3b9f4..38f2c84ebd466a97cfac93c77b7a5bfe3ddddeca 100644 (file)
@@ -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
 
index 1350f118cccd3a89a2a17ff3ef5da50a4adca644..25f1b9b6f846a078c68954c77e602e3b84050efa 100644 (file)
@@ -20,6 +20,7 @@
 #include "icd_windows.h"
 #include "icd_windows_hkr.h"
 #include "icd_windows_dxgk.h"
+#include "icd_windows_apppackage.h"
 #include <stdio.h>
 #include <windows.h>
 #include <winreg.h>
@@ -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 (file)
index 0000000..0092c2a
--- /dev/null
@@ -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 <windows.management.deployment.h>
+#include <wrl/client.h>
+#include <wrl/wrappers/corewrappers.h>
+
+#include <locale>
+#include <codecvt>
+
+template <typename F>
+struct ScopeExit {
+    ScopeExit(F&& f) : f(std::forward<F>(f)) {}
+    ~ScopeExit() { f(); }
+    F f;
+};
+
+template <typename F>
+inline ScopeExit<F> MakeScopeExit(F&& f) {
+    return ScopeExit<F>(std::forward<F>(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<IPackageManager> 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<IPackageCollection> 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<IPackageIterator> 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<IPackage> 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<IStorageFolder> folder;
+        if (FAILED(package->get_InstalledLocation(&folder)))
+        {
+            KHR_ICD_TRACE("Failed to get package install folder\n");
+            continue;
+        }
+
+        using ABI::Windows::Storage::IStorageItem;
+        ComPtr<IStorageItem> 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<std::codecvt_utf8<wchar_t>> 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 (file)
index 0000000..d4c55da
--- /dev/null
@@ -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 <stdbool.h>
+#include "icd_windows.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+bool khrIcdOsVendorsEnumerateAppPackage(void);