2 * Copyright (c) 2017-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"
29 // This GUID was only added to devguid.h on Windows SDK v10.0.16232 which
30 // corresponds to Windows 10 Redstone 3 (Windows 10 Fall Creators Update).
31 DEFINE_GUID(OCL_GUID_DEVCLASS_SOFTWARECOMPONENT, 0x5c4c3332, 0x344d, 0x483c, 0x87, 0x39, 0x25, 0x9e, 0x93, 0x4c, 0x9c, 0xc8);
40 #define KHR_SAFE_RELEASE(mem) \
47 static const char OPENCL_REG_SUB_KEY[] = "OpenCLDriverName";
50 static const char OPENCL_REG_SUB_KEY_WOW[] = "OpenCLDriverNameWow";
53 // Do not free the memory returned by this function.
54 static const char* GetOpenCLRegKeyName(void)
57 return OPENCL_REG_SUB_KEY;
59 // The suffix/substring "WoW" is meaningful only when a 32-bit
60 // application is running on a 64-bit Windows OS. A 32-bit application
61 // running on a 32-bit OS uses non-WoW names.
63 if (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)
65 return OPENCL_REG_SUB_KEY_WOW;
68 return OPENCL_REG_SUB_KEY;
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(
99 GetOpenCLRegKeyName(),
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_MULTI_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;