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;
91 * Vendor enumeration functions
95 // go through the list of vendors in the registry and call khrIcdVendorAdd
96 // for each vendor encountered
97 BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContext)
101 const char* platformsName = "SOFTWARE\\Khronos\\OpenCL\\Vendors";
102 HKEY platformsKey = NULL;
105 khrIcdVendorsEnumerateEnv();
107 if (!khrIcdOsVendorsEnumerateDXGK())
109 KHR_ICD_TRACE("Failed to load via DXGK interface on RS4, continuing\n");
110 if (!khrIcdOsVendorsEnumerateHKR())
112 KHR_ICD_TRACE("Failed to enumerate HKR entries, continuing\n");
116 KHR_ICD_TRACE("Opening key HKLM\\%s...\n", platformsName);
117 result = RegOpenKeyExA(
123 if (ERROR_SUCCESS != result)
125 KHR_ICD_TRACE("Failed to open platforms key %s, continuing\n", platformsName);
130 for (dwIndex = 0;; ++dwIndex)
132 char cszLibraryName[1024] = {0};
133 DWORD dwLibraryNameSize = sizeof(cszLibraryName);
134 DWORD dwLibraryNameType = 0;
136 DWORD dwValueSize = sizeof(dwValue);
138 // read the value name
139 KHR_ICD_TRACE("Reading value %d...\n", dwIndex);
140 result = RegEnumValueA(
149 // if RegEnumKeyEx fails, we are done with the enumeration
150 if (ERROR_SUCCESS != result)
152 KHR_ICD_TRACE("Failed to read value %d, done reading key.\n", dwIndex);
155 KHR_ICD_TRACE("Value %s found...\n", cszLibraryName);
157 // Require that the value be a DWORD and equal zero
158 if (REG_DWORD != dwLibraryNameType)
160 KHR_ICD_TRACE("Value not a DWORD, skipping\n");
165 KHR_ICD_TRACE("Value not zero, skipping\n");
169 status |= adapterAdd(cszLibraryName, ZeroLuid);
173 // Add adapters according to DXGI's preference order
174 HMODULE hDXGI = LoadLibrary("dxgi.dll");
177 IDXGIFactory* pFactory = NULL;
178 PFN_CREATE_DXGI_FACTORY pCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(hDXGI, "CreateDXGIFactory");
179 HRESULT hr = pCreateDXGIFactory(&IID_IDXGIFactory, &pFactory);
183 IDXGIAdapter* pAdapter = NULL;
184 while (SUCCEEDED(pFactory->lpVtbl->EnumAdapters(pFactory, i++, &pAdapter)))
186 DXGI_ADAPTER_DESC AdapterDesc;
187 pAdapter->lpVtbl->GetDesc(pAdapter, &AdapterDesc);
189 for (WinAdapter* iterAdapter = pWinAdapterBegin; iterAdapter != pWinAdapterEnd; ++iterAdapter)
191 if (iterAdapter->luid.LowPart == AdapterDesc.AdapterLuid.LowPart
192 && iterAdapter->luid.HighPart == AdapterDesc.AdapterLuid.HighPart)
194 khrIcdVendorAdd(iterAdapter->szName);
199 pAdapter->lpVtbl->Release(pAdapter);
201 pFactory->lpVtbl->Release(pFactory);
206 // Go through the list again, putting any remaining adapters at the end of the list in an undefined order
207 for (WinAdapter* iterAdapter = pWinAdapterBegin; iterAdapter != pWinAdapterEnd; ++iterAdapter)
209 khrIcdVendorAdd(iterAdapter->szName);
212 free(pWinAdapterBegin);
214 result = RegCloseKey(platformsKey);
215 if (ERROR_SUCCESS != result)
217 KHR_ICD_TRACE("Failed to close platforms key %s, ignoring\n", platformsName);
222 // go through the list of vendors only once
223 void khrIcdOsVendorsEnumerateOnce()
225 InitOnceExecuteOnce(&initialized, khrIcdOsVendorsEnumerate, NULL, NULL);
230 * Dynamic library loading functions
234 // dynamically load a library. returns NULL on failure
235 void *khrIcdOsLibraryLoad(const char *libraryName)
237 return (void *)LoadLibraryA(libraryName);
240 // get a function pointer from a loaded library. returns NULL on failure.
241 void *khrIcdOsLibraryGetFunctionAddress(void *library, const char *functionName)
243 if (!library || !functionName)
247 return GetProcAddress( (HMODULE)library, functionName);
251 void khrIcdOsLibraryUnload(void *library)
253 FreeLibrary( (HMODULE)library);