2 * Copyright (c) 2016-2019 The Khronos Group Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 * OpenCL is a trademark of Apple Inc. used under license by Khronos.
22 #include "icd_windows.h"
23 #include "icd_windows_hkr.h"
24 #include "icd_windows_dxgk.h"
25 #include "icd_windows_apppackage.h"
31 typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID, void **);
33 static INIT_ONCE initialized = INIT_ONCE_STATIC_INIT;
35 typedef struct WinAdapter
41 const LUID ZeroLuid = { 0, 0 };
43 static WinAdapter* pWinAdapterBegin = NULL;
44 static WinAdapter* pWinAdapterEnd = NULL;
45 static WinAdapter* pWinAdapterCapacity = NULL;
47 BOOL adapterAdd(const char* szName, LUID luid)
50 if (pWinAdapterEnd == pWinAdapterCapacity)
52 size_t oldCapacity = pWinAdapterCapacity - pWinAdapterBegin;
53 size_t newCapacity = oldCapacity;
58 else if(newCapacity < UINT_MAX/2)
63 WinAdapter* pNewBegin = malloc(newCapacity * sizeof(*pWinAdapterBegin));
70 memcpy(pNewBegin, pWinAdapterBegin, oldCapacity * sizeof(*pWinAdapterBegin));
71 free(pWinAdapterBegin);
73 pWinAdapterCapacity = pNewBegin + newCapacity;
74 pWinAdapterEnd = pNewBegin + oldCapacity;
75 pWinAdapterBegin = pNewBegin;
78 if (pWinAdapterEnd != pWinAdapterCapacity)
80 size_t nameLen = (strlen(szName) + 1)*sizeof(szName[0]);
81 pWinAdapterEnd->szName = malloc(nameLen);
82 if (!pWinAdapterEnd->szName)
86 memcpy(pWinAdapterEnd->szName, szName, nameLen);
87 pWinAdapterEnd->luid = luid;
94 void adapterFree(WinAdapter *pWinAdapter)
96 free(pWinAdapter->szName);
97 pWinAdapter->szName = NULL;
102 * Vendor enumeration functions
106 // go through the list of vendors in the registry and call khrIcdVendorAdd
107 // for each vendor encountered
108 BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext)
112 const char* platformsName = "SOFTWARE\\Khronos\\OpenCL\\Vendors";
113 HKEY platformsKey = NULL;
116 khrIcdVendorsEnumerateEnv();
118 status |= khrIcdOsVendorsEnumerateDXGK();
121 KHR_ICD_TRACE("Failed to load via DXGK interface on RS4, continuing\n");
122 status |= khrIcdOsVendorsEnumerateHKR();
125 KHR_ICD_TRACE("Failed to enumerate HKR entries, continuing\n");
129 status |= khrIcdOsVendorsEnumerateAppPackage();
131 KHR_ICD_TRACE("Opening key HKLM\\%s...\n", platformsName);
132 result = RegOpenKeyExA(
138 if (ERROR_SUCCESS != result)
140 KHR_ICD_TRACE("Failed to open platforms key %s, continuing\n", platformsName);
145 for (dwIndex = 0;; ++dwIndex)
147 char cszLibraryName[1024] = {0};
148 DWORD dwLibraryNameSize = sizeof(cszLibraryName);
149 DWORD dwLibraryNameType = 0;
151 DWORD dwValueSize = sizeof(dwValue);
153 // read the value name
154 KHR_ICD_TRACE("Reading value %d...\n", dwIndex);
155 result = RegEnumValueA(
164 // if RegEnumKeyEx fails, we are done with the enumeration
165 if (ERROR_SUCCESS != result)
167 KHR_ICD_TRACE("Failed to read value %d, done reading key.\n", dwIndex);
170 KHR_ICD_TRACE("Value %s found...\n", cszLibraryName);
172 // Require that the value be a DWORD and equal zero
173 if (REG_DWORD != dwLibraryNameType)
175 KHR_ICD_TRACE("Value not a DWORD, skipping\n");
180 KHR_ICD_TRACE("Value not zero, skipping\n");
184 status |= adapterAdd(cszLibraryName, ZeroLuid);
188 // Add adapters according to DXGI's preference order
189 HMODULE hDXGI = LoadLibrary("dxgi.dll");
192 IDXGIFactory* pFactory = NULL;
193 PFN_CREATE_DXGI_FACTORY pCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(hDXGI, "CreateDXGIFactory");
194 if (pCreateDXGIFactory)
196 HRESULT hr = pCreateDXGIFactory(&IID_IDXGIFactory, &pFactory);
200 IDXGIAdapter* pAdapter = NULL;
201 while (SUCCEEDED(pFactory->lpVtbl->EnumAdapters(pFactory, i++, &pAdapter)))
203 DXGI_ADAPTER_DESC AdapterDesc;
204 if (SUCCEEDED(pAdapter->lpVtbl->GetDesc(pAdapter, &AdapterDesc)))
206 for (WinAdapter* iterAdapter = pWinAdapterBegin; iterAdapter != pWinAdapterEnd; ++iterAdapter)
208 if (iterAdapter->luid.LowPart == AdapterDesc.AdapterLuid.LowPart
209 && iterAdapter->luid.HighPart == AdapterDesc.AdapterLuid.HighPart)
211 khrIcdVendorAdd(iterAdapter->szName);
217 pAdapter->lpVtbl->Release(pAdapter);
219 pFactory->lpVtbl->Release(pFactory);
225 // Go through the list again, putting any remaining adapters at the end of the list in an undefined order
226 for (WinAdapter* iterAdapter = pWinAdapterBegin; iterAdapter != pWinAdapterEnd; ++iterAdapter)
228 khrIcdVendorAdd(iterAdapter->szName);
229 adapterFree(iterAdapter);
232 free(pWinAdapterBegin);
233 pWinAdapterBegin = NULL;
234 pWinAdapterEnd = NULL;
235 pWinAdapterCapacity = NULL;
237 result = RegCloseKey(platformsKey);
238 if (ERROR_SUCCESS != result)
240 KHR_ICD_TRACE("Failed to close platforms key %s, ignoring\n", platformsName);
245 // go through the list of vendors only once
246 void khrIcdOsVendorsEnumerateOnce()
248 InitOnceExecuteOnce(&initialized, khrIcdOsVendorsEnumerate, NULL, NULL);
253 * Dynamic library loading functions
257 // dynamically load a library. returns NULL on failure
258 void *khrIcdOsLibraryLoad(const char *libraryName)
260 HMODULE hTemp = LoadLibraryExA(libraryName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
261 if (!hTemp && GetLastError() == ERROR_INVALID_PARAMETER)
263 hTemp = LoadLibraryExA(libraryName, NULL, 0);
268 // get a function pointer from a loaded library. returns NULL on failure.
269 void *khrIcdOsLibraryGetFunctionAddress(void *library, const char *functionName)
271 if (!library || !functionName)
275 return GetProcAddress( (HMODULE)library, functionName);
279 void khrIcdOsLibraryUnload(void *library)
281 FreeLibrary( (HMODULE)library);