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.
20 #include "icd_windows_hkr.h"
21 #include "icd_windows_dxgk.h"
28 typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID, void **);
30 static INIT_ONCE initialized = INIT_ONCE_STATIC_INIT;
32 typedef struct WinAdapter
38 const LUID ZeroLuid = { 0, 0 };
40 static WinAdapter* pWinAdapterBegin = NULL;
41 static WinAdapter* pWinAdapterEnd = NULL;
42 static WinAdapter* pWinAdapterCapacity = NULL;
44 BOOL adapterAdd(const char* szName, LUID luid)
47 if (pWinAdapterEnd == pWinAdapterCapacity)
49 size_t oldCapacity = pWinAdapterCapacity - pWinAdapterBegin;
50 size_t newCapacity = oldCapacity;
58 WinAdapter* pNewBegin = malloc(newCapacity * sizeof(*pWinAdapterBegin));
65 memcpy(pNewBegin, pWinAdapterBegin, oldCapacity * sizeof(*pWinAdapterBegin));
66 free(pWinAdapterBegin);
68 pWinAdapterCapacity = pNewBegin + newCapacity;
69 pWinAdapterEnd = pNewBegin + oldCapacity;
70 pWinAdapterBegin = pNewBegin;
73 if (pWinAdapterEnd != pWinAdapterCapacity)
75 size_t nameLen = (strlen(szName) + 1)*sizeof(szName[0]);
76 pWinAdapterEnd->szName = malloc(nameLen);
77 if (!pWinAdapterEnd->szName)
81 memcpy(pWinAdapterEnd->szName, szName, nameLen);
82 pWinAdapterEnd->luid = luid;
89 void adapterFree(WinAdapter *pWinAdapter)
91 if(pWinAdapter->szName)
92 free(pWinAdapter->szName);
97 * Vendor enumeration functions
101 // go through the list of vendors in the registry and call khrIcdVendorAdd
102 // for each vendor encountered
103 BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext)
107 const char* platformsName = "SOFTWARE\\Khronos\\OpenCL\\Vendors";
108 HKEY platformsKey = NULL;
111 khrIcdVendorsEnumerateEnv();
113 if (!khrIcdOsVendorsEnumerateDXGK())
115 KHR_ICD_TRACE("Failed to load via DXGK interface on RS4, continuing\n");
116 if (!khrIcdOsVendorsEnumerateHKR())
118 KHR_ICD_TRACE("Failed to enumerate HKR entries, continuing\n");
122 KHR_ICD_TRACE("Opening key HKLM\\%s...\n", platformsName);
123 result = RegOpenKeyExA(
129 if (ERROR_SUCCESS != result)
131 KHR_ICD_TRACE("Failed to open platforms key %s, continuing\n", platformsName);
136 for (dwIndex = 0;; ++dwIndex)
138 char cszLibraryName[1024] = {0};
139 DWORD dwLibraryNameSize = sizeof(cszLibraryName);
140 DWORD dwLibraryNameType = 0;
142 DWORD dwValueSize = sizeof(dwValue);
144 // read the value name
145 KHR_ICD_TRACE("Reading value %d...\n", dwIndex);
146 result = RegEnumValueA(
155 // if RegEnumKeyEx fails, we are done with the enumeration
156 if (ERROR_SUCCESS != result)
158 KHR_ICD_TRACE("Failed to read value %d, done reading key.\n", dwIndex);
161 KHR_ICD_TRACE("Value %s found...\n", cszLibraryName);
163 // Require that the value be a DWORD and equal zero
164 if (REG_DWORD != dwLibraryNameType)
166 KHR_ICD_TRACE("Value not a DWORD, skipping\n");
171 KHR_ICD_TRACE("Value not zero, skipping\n");
175 status |= adapterAdd(cszLibraryName, ZeroLuid);
179 // Add adapters according to DXGI's preference order
180 HMODULE hDXGI = LoadLibrary("dxgi.dll");
183 IDXGIFactory* pFactory = NULL;
184 PFN_CREATE_DXGI_FACTORY pCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(hDXGI, "CreateDXGIFactory");
185 if (pCreateDXGIFactory)
187 HRESULT hr = pCreateDXGIFactory(&IID_IDXGIFactory, &pFactory);
191 IDXGIAdapter* pAdapter = NULL;
192 while (SUCCEEDED(pFactory->lpVtbl->EnumAdapters(pFactory, i++, &pAdapter)))
194 DXGI_ADAPTER_DESC AdapterDesc;
195 pAdapter->lpVtbl->GetDesc(pAdapter, &AdapterDesc);
197 for (WinAdapter* iterAdapter = pWinAdapterBegin; iterAdapter != pWinAdapterEnd; ++iterAdapter)
199 if (iterAdapter->luid.LowPart == AdapterDesc.AdapterLuid.LowPart
200 && iterAdapter->luid.HighPart == AdapterDesc.AdapterLuid.HighPart)
202 khrIcdVendorAdd(iterAdapter->szName);
207 pAdapter->lpVtbl->Release(pAdapter);
209 pFactory->lpVtbl->Release(pFactory);
215 // Go through the list again, putting any remaining adapters at the end of the list in an undefined order
216 for (WinAdapter* iterAdapter = pWinAdapterBegin; iterAdapter != pWinAdapterEnd; ++iterAdapter)
218 khrIcdVendorAdd(iterAdapter->szName);
219 adapterFree(iterAdapter);
222 free(pWinAdapterBegin);
224 result = RegCloseKey(platformsKey);
225 if (ERROR_SUCCESS != result)
227 KHR_ICD_TRACE("Failed to close platforms key %s, ignoring\n", platformsName);
232 // go through the list of vendors only once
233 void khrIcdOsVendorsEnumerateOnce()
235 InitOnceExecuteOnce(&initialized, khrIcdOsVendorsEnumerate, NULL, NULL);
240 * Dynamic library loading functions
244 // dynamically load a library. returns NULL on failure
245 void *khrIcdOsLibraryLoad(const char *libraryName)
247 return (void *)LoadLibraryA(libraryName);
250 // get a function pointer from a loaded library. returns NULL on failure.
251 void *khrIcdOsLibraryGetFunctionAddress(void *library, const char *functionName)
253 if (!library || !functionName)
257 return GetProcAddress( (HMODULE)library, functionName);
261 void khrIcdOsLibraryUnload(void *library)
263 FreeLibrary( (HMODULE)library);