2 * Copyright (c) 2017 The Khronos Group Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software source and associated documentation files (the "Materials"),
6 * to deal in the Materials without restriction, including without limitation
7 * the rights to use, copy, modify, compile, merge, publish, distribute,
8 * sublicense, and/or sell copies of the Materials, and to permit persons to
9 * whom the Materials are furnished to do so, subject the following terms and
12 * All modifications to the Materials used to create a binary that is
13 * distributed to third parties shall be provided to Khronos with an
14 * unrestricted license to use for the purposes of implementing bug fixes and
15 * enhancements to the Materials;
17 * If the binary is used as part of an OpenCL(TM) implementation, whether binary
18 * is distributed together with or separately to that implementation, then
19 * recipient must become an OpenCL Adopter and follow the published OpenCL
20 * conformance process for that implementation, details at:
21 * http://www.khronos.org/conformance/;
23 * The above copyright notice, the OpenCL trademark license, and this permission
24 * notice shall be included in all copies or substantial portions of the
27 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 * OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN
35 * OpenCL is a trademark of Apple Inc. used under license by Khronos.
39 #include "icd_windows_hkr.h"
48 // This GUID was only added to devguid.h on Windows SDK v10.0.16232 which
49 // corresponds to Windows 10 Redstone 3 (Windows 10 Fall Creators Update).
50 DEFINE_GUID(OCL_GUID_DEVCLASS_SOFTWARECOMPONENT, 0x5c4c3332, 0x344d, 0x483c, 0x87, 0x39, 0x25, 0x9e, 0x93, 0x4c, 0x9c, 0xc8);
59 #define KHR_SAFE_RELEASE(mem) \
67 static const char OPENCL_REG_SUB_KEY[] = "OpenCLDriverName";
69 static const char OPENCL_REG_SUB_KEY[] = "OpenCLDriverNameWow";
72 static bool ReadOpenCLKey(DEVINST dnDevNode)
77 DWORD dwLibraryNameType = 0;
78 char *cszOclPath = NULL;
79 DWORD dwOclPathSize = 0;
82 ret = CM_Open_DevNode_Key(
86 RegDisposition_OpenExisting,
88 CM_REGISTRY_SOFTWARE);
90 if (CR_SUCCESS != ret)
92 KHR_ICD_TRACE("Failed with ret 0x%x\n", ret);
97 result = RegQueryValueExA(
105 if (ERROR_SUCCESS != result)
107 KHR_ICD_TRACE("Failed to open sub key 0x%x\n", result);
111 cszOclPath = malloc(dwOclPathSize);
112 if (NULL == cszOclPath)
114 KHR_ICD_TRACE("Failed to allocate %u bytes for registry value\n", dwOclPathSize);
118 result = RegQueryValueExA(
125 if (ERROR_SUCCESS != result)
127 KHR_ICD_TRACE("Failed to open sub key 0x%x\n", result);
131 if (REG_SZ != dwLibraryNameType)
133 KHR_ICD_TRACE("Unexpected registry entry 0x%x! continuing\n", dwLibraryNameType);
137 KHR_ICD_TRACE(" Path: %s\n", cszOclPath);
139 khrIcdVendorAdd(cszOclPath);
149 result = RegCloseKey(hkey);
150 if (ERROR_SUCCESS != result)
152 KHR_ICD_TRACE("WARNING: failed to close hkey 0x%x\n", result);
159 static DeviceProbeResult ProbeDevice(DEVINST devnode)
165 ret = CM_Get_DevNode_Status(
171 // TODO: consider extracting warning messages out of this function
172 if (CR_SUCCESS != ret)
174 KHR_ICD_TRACE(" WARNING: failed to probe the status of the device 0x%x\n", ret);
179 // Careful here, we need to check 2 scenarios:
180 // 1. DN_NEED_RESTART
181 // status flag indicates that a reboot is needed when an _already started_
182 // device cannot be stopped. This covers devices that are still started with their
183 // old KMD (because they couldn't be stopped/restarted) while the UMD is updated
184 // and possibly out of sync.
186 // 2. Status & DN_HAS_PROBLEM && Problem == CM_PROB_NEED_RESTART
187 // indicates that a reboot is needed when a _stopped device_ cannot be (re)started.
189 if (((ulStatus & DN_HAS_PROBLEM) && ulProblem == CM_PROB_NEED_RESTART) ||
190 ulStatus & DN_NEED_RESTART)
192 KHR_ICD_TRACE(" WARNING: device is pending reboot (0x%x), skipping...\n", ulStatus);
193 return PendingReboot;
199 // Tries to look for the OpenCL key under the display devices and
200 // if not found, falls back to software component devices.
201 bool khrIcdOsVendorsEnumerateHKR(void)
205 bool foundOpenCLKey = false;
207 DEVINST devchild = 0;
208 wchar_t *deviceIdList = NULL;
211 OLECHAR display_adapter_guid_str[MAX_GUID_STRING_LEN];
212 ULONG ulFlags = CM_GETIDLIST_FILTER_CLASS |
213 CM_GETIDLIST_FILTER_PRESENT;
215 iret = StringFromGUID2(
216 &GUID_DEVCLASS_DISPLAY,
217 display_adapter_guid_str,
218 MAX_GUID_STRING_LEN);
220 if (MAX_GUID_STRING_LEN != iret)
222 KHR_ICD_TRACE("StringFromGUID2 failed with %d\n", iret);
226 // Paranoia: we might have a new device added to the list between the call
227 // to CM_Get_Device_ID_List_Size() and the call to CM_Get_Device_ID_List().
230 ret = CM_Get_Device_ID_List_SizeW(
232 display_adapter_guid_str,
235 if (CR_SUCCESS != ret)
237 KHR_ICD_TRACE("CM_Get_Device_ID_List_size failed with 0x%x\n", ret);
241 // "pulLen [out] Receives a value representing the required buffer
242 // size, in characters."
243 // So we need to allocate the right size in bytes but we still need
244 // to keep szBuffer as it was returned from CM_Get_Device_ID_List_Size so
245 // the call to CM_Get_Device_ID_List will receive the correct size.
246 deviceIdList = malloc(szBuffer * sizeof(wchar_t));
247 if (NULL == deviceIdList)
249 KHR_ICD_TRACE("Failed to allocate %u bytes for device ID strings\n", szBuffer);
253 ret = CM_Get_Device_ID_ListW(
254 display_adapter_guid_str,
259 if (CR_SUCCESS != ret)
261 KHR_ICD_TRACE("CM_Get_Device_ID_List failed with 0x%x\n", ret);
262 KHR_SAFE_RELEASE(deviceIdList);
264 } while (CR_BUFFER_SMALL == ret);
266 if (NULL == deviceIdList)
271 for (PWSTR deviceId = deviceIdList; *deviceId; deviceId += wcslen(deviceId) + 1)
273 DEVPROPTYPE devpropType;
275 KHR_ICD_WIDE_TRACE(L"Device ID: %ls\n", deviceId);
277 ret = CM_Locate_DevNodeW(&devinst, deviceId, 0);
278 if (CR_SUCCESS == ret)
280 KHR_ICD_TRACE(" devinst: %d\n", devinst);
284 KHR_ICD_TRACE("CM_Locate_DevNode failed with 0x%x\n", ret);
288 if (ProbeDevice(devinst) != Valid)
293 KHR_ICD_TRACE(" Trying to look for the key in the display adapter HKR...\n");
294 if (ReadOpenCLKey(devinst))
296 foundOpenCLKey = true;
300 KHR_ICD_TRACE(" Could not find the key, proceeding to children software components...\n");
307 if (CR_SUCCESS != ret)
309 KHR_ICD_TRACE(" CM_Get_Child returned 0x%x, skipping children...\n", ret);
315 wchar_t deviceInstanceID[MAX_DEVICE_ID_LEN] = { 0 };
317 ULONG szGuid = sizeof(guid);
319 KHR_ICD_TRACE(" devchild: %d\n", devchild);
320 ret = CM_Get_Device_IDW(
323 sizeof(deviceInstanceID),
326 if (CR_SUCCESS != ret)
328 KHR_ICD_TRACE(" CM_Get_Device_ID returned 0x%x, skipping device...\n", ret);
333 KHR_ICD_WIDE_TRACE(L" deviceInstanceID: %ls\n", deviceInstanceID);
336 ret = CM_Get_DevNode_PropertyW(
338 &DEVPKEY_Device_ClassGuid,
344 KHR_ICD_ASSERT(devpropType == DEVPROP_TYPE_GUID);
346 if (CR_SUCCESS != ret ||
347 !IsEqualGUID(&OCL_GUID_DEVCLASS_SOFTWARECOMPONENT, &guid))
352 if (ProbeDevice(devchild) != Valid)
357 if (ReadOpenCLKey(devchild))
359 foundOpenCLKey = true;
362 } while (CM_Get_Sibling(&devchild, devchild, 0) == CR_SUCCESS);
368 return foundOpenCLKey;