Skip to content

Commit 957ac49

Browse files
bashbaugjoekilner
authored andcommitted
Windows 10 RS4 Support for the OpenCL ICD Loader w/ Build Option (KhronosGroup#78)
* Windows 10 RS4 support for OpenCL ICD as per MS directive Motivation - MS is adopting DCHU complaince and for For RS4 it will be mandatory for OpenCL to load via registry keys contained only within the HKR section of the registry as writes outside of HKR will not be allowed for the INF. It is also to support ParaV feature of the OS to make it "virtualization-ready". * Update Copyright year * Fix vendors enumeration on 32-bit Windows OS * Update CMake file for detecting necessary includes for the Windows WDK * Add option to build with or without the WDK (default: with) * Documented Windows WDK dependency
1 parent f45b6d8 commit 957ac49

7 files changed

Lines changed: 226 additions & 7 deletions

File tree

CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ if (WIN32)
4141
list (APPEND OPENCL_ICD_LOADER_SOURCES
4242
loader/windows/icd_windows.c
4343
loader/windows/icd_windows_hkr.c
44+
loader/windows/icd_windows_dxgk.c
4445
loader/windows/OpenCL.def
4546
loader/windows/OpenCL.rc)
4647
# Only add the DXSDK include directory if the environment variable is
@@ -62,6 +63,29 @@ set_target_properties (OpenCL PROPERTIES VERSION "1.2" SOVERSION "1")
6263

6364
if (WIN32)
6465
target_link_libraries (OpenCL cfgmgr32.lib)
66+
67+
option (OPENCL_ICD_LOADER_REQUIRE_WDK "Build with D3DKMT support, which requires the Windows WDK." ON)
68+
if (OPENCL_ICD_LOADER_REQUIRE_WDK)
69+
if(DEFINED ENV{WDKContentRoot})
70+
file(GLOB D3DKMT_HEADER "$ENV{WDKContentRoot}/Include/*/km/d3dkmthk.h")
71+
else()
72+
file(GLOB D3DKMT_HEADER "$ENV{HOMEDRIVE}/Program Files */Windows Kits/10/Include/*/km/d3dkmthk.h")
73+
endif()
74+
75+
if(D3DKMT_HEADER)
76+
list(GET D3DKMT_HEADER -1 LATEST_D3DKMT_HEADER)
77+
get_filename_component(WDK_DIRECTORY ${LATEST_D3DKMT_HEADER} DIRECTORY)
78+
get_filename_component(WDK_DIRECTORY ${WDK_DIRECTORY} DIRECTORY)
79+
message(STATUS "Found the Windows WDK in: ${WDK_DIRECTORY}")
80+
target_compile_definitions(OpenCL PRIVATE OPENCL_ICD_LOADER_REQUIRE_WDK)
81+
target_include_directories(OpenCL PRIVATE ${WDK_DIRECTORY}/um)
82+
target_include_directories(OpenCL PRIVATE ${WDK_DIRECTORY}/km)
83+
target_include_directories(OpenCL PRIVATE ${WDK_DIRECTORY}/shared)
84+
else()
85+
message(FATAL_ERROR "The Windows WDK was not found. Consider disabling OPENCL_ICD_LOADER_REQUIRE_WDK. Aborting.")
86+
endif()
87+
endif()
88+
6589
if(NOT USE_DYNAMIC_VCXX_RUNTIME)
6690
string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
6791
string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ The OpenCL ICD Loader requires OpenCL Headers.
3030
To use system OpenCL Headers, please specify the OpenCL Header location using the CMake variable `OPENCL_ICD_LOADER_HEADERS_DIR`.
3131
By default, the OpenCL ICD Loader will look for OpenCL Headers in the `inc` directory.
3232

33+
By default, the OpenCL ICD Loader on Windows requires the Windows Driver Kit (WDK).
34+
An OpenCL ICD Loader may be built without the Windows Driver Kit using the CMake variable `OPENCL_ICD_LOADER_REQUIRE_WDK`, however this option should be used with caution since it may prevent the OpenCL ICD Loader from enumerating some OpenCL implementations.
35+
This dependency may be removed in the future.
36+
3337
The OpenCL ICD Loader uses CMake for its build system.
3438
If CMake is not provided by your build system or OS package manager, please consult the [CMake website](https://cmake.org).
3539

loader/windows/OpenCL.rc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,22 @@
1818

1919
#include <windows.h>
2020

21+
#define OPENCL_ICD_LOADER_VERSION_MAJOR 2
22+
#define OPENCL_ICD_LOADER_VERSION_MINOR 2
23+
#define OPENCL_ICD_LOADER_VERSION_REV 2
24+
2125
#ifdef RC_INVOKED
2226

27+
#define OPENCL_ICD_LOADER_VAL(_v) #_v
28+
#define OPENCL_ICD_LOADER_TOSTRING(_d) OPENCL_ICD_LOADER_VAL(_d)
29+
#define OPENCL_ICD_LOADER_VERSION_STRING \
30+
OPENCL_ICD_LOADER_TOSTRING(OPENCL_ICD_LOADER_VERSION_MAJOR) "." \
31+
OPENCL_ICD_LOADER_TOSTRING(OPENCL_ICD_LOADER_VERSION_MINOR) "." \
32+
OPENCL_ICD_LOADER_TOSTRING(OPENCL_ICD_LOADER_VERSION_REV)
33+
2334
VS_VERSION_INFO VERSIONINFO
24-
FILEVERSION 2,2,1,0
25-
PRODUCTVERSION 2,2,1,0
35+
FILEVERSION OPENCL_ICD_LOADER_VERSION_MAJOR,OPENCL_ICD_LOADER_VERSION_MINOR,OPENCL_ICD_LOADER_VERSION_REV,0
36+
PRODUCTVERSION OPENCL_ICD_LOADER_VERSION_MAJOR,OPENCL_ICD_LOADER_VERSION_MINOR,OPENCL_ICD_LOADER_VERSION_REV,0
2637
FILETYPE VFT_DLL
2738

2839
BEGIN
@@ -31,9 +42,9 @@ BEGIN
3142
BLOCK "040904E4"
3243
BEGIN
3344
VALUE "FileDescription" ,"OpenCL Client DLL"
34-
VALUE "ProductName" ,"Khronos OpenCL ICD"
45+
VALUE "ProductName" ,"Khronos OpenCL ICD Loader"
3546
VALUE "LegalCopyright" ,"Copyright \251 The Khronos Group Inc 2016-2019"
36-
VALUE "FileVersion" ,"2.2.1.0"
47+
VALUE "FileVersion" ,OPENCL_ICD_LOADER_VERSION_STRING ".0"
3748
VALUE "CompanyName" ,"Khronos Group"
3849
VALUE "InternalName" ,"OpenCL"
3950
VALUE "OriginalFilename","OpenCL.dll"

loader/windows/icd_windows.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "icd.h"
2020
#include "icd_windows_hkr.h"
21+
#include "icd_windows_dxgk.h"
2122
#include <stdio.h>
2223
#include <windows.h>
2324
#include <winreg.h>
@@ -39,9 +40,13 @@ BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVO
3940
HKEY platformsKey = NULL;
4041
DWORD dwIndex;
4142

42-
if (!khrIcdOsVendorsEnumerateHKR())
43+
if (!khrIcdOsVendorsEnumerateDXGK())
4344
{
44-
KHR_ICD_TRACE("Failed to enumerate HKR entries, continuing\n");
45+
KHR_ICD_TRACE("Failed to load via DXGK interface on RS4, continuing\n");
46+
if (!khrIcdOsVendorsEnumerateHKR())
47+
{
48+
KHR_ICD_TRACE("Failed to enumerate HKR entries, continuing\n");
49+
}
4550
}
4651

4752
KHR_ICD_TRACE("Opening key HKLM\\%s...\n", platformsName);

loader/windows/icd_windows_dxgk.c

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Copyright (c) 2017-2019 The Khronos Group Inc.
3+
*
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
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
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.
15+
*
16+
* OpenCL is a trademark of Apple Inc. used under license by Khronos.
17+
*/
18+
19+
#include "icd.h"
20+
#include "icd_windows_dxgk.h"
21+
22+
#if defined(OPENCL_ICD_LOADER_REQUIRE_WDK)
23+
#include <windows.h>
24+
25+
#ifndef NTSTATUS
26+
typedef LONG NTSTATUS;
27+
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
28+
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023)
29+
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
30+
#endif
31+
32+
#include <d3dkmthk.h>
33+
#endif
34+
35+
bool khrIcdOsVendorsEnumerateDXGK(void)
36+
{
37+
bool ret = false;
38+
#if defined(OPENCL_ICD_LOADER_REQUIRE_WDK)
39+
#if defined(DXGKDDI_INTERFACE_VERSION_WDDM2_4) && (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_4)
40+
{
41+
D3DKMT_ADAPTERINFO* pAdapterInfo = NULL;
42+
D3DKMT_ENUMADAPTERS2 EnumAdapters;
43+
NTSTATUS Status = STATUS_SUCCESS;
44+
45+
// Get handle to GDI Runtime
46+
HMODULE h = LoadLibrary("gdi32.dll");
47+
KHR_ICD_ASSERT(h != NULL);
48+
49+
char cszLibraryName[MAX_PATH] = { 0 };
50+
PFND3DKMT_ENUMADAPTERS2 pEnumAdapters2 = (PFND3DKMT_ENUMADAPTERS2)GetProcAddress((HMODULE)h, "D3DKMTEnumAdapters2");
51+
if (!pEnumAdapters2)
52+
{
53+
KHR_ICD_TRACE("GetProcAddress failed for D3DKMT_ENUMADAPTERS2\n");
54+
goto out;
55+
}
56+
while (1)
57+
{
58+
EnumAdapters.NumAdapters = 0;
59+
EnumAdapters.pAdapters = NULL;
60+
Status = pEnumAdapters2(&EnumAdapters);
61+
if (Status == STATUS_BUFFER_TOO_SMALL)
62+
{
63+
// Number of Adapters increased between calls, retry;
64+
continue;
65+
}
66+
else if (!NT_SUCCESS(Status))
67+
{
68+
KHR_ICD_TRACE("D3DKMT_ENUMADAPTERS2 status != SUCCESS\n");
69+
goto out;
70+
}
71+
break;
72+
}
73+
pAdapterInfo = (D3DKMT_ADAPTERINFO*)malloc(sizeof(D3DKMT_ADAPTERINFO)*(EnumAdapters.NumAdapters));
74+
if (pAdapterInfo == NULL)
75+
{
76+
KHR_ICD_TRACE("Allocation failure for AdapterInfo buffer\n");
77+
goto out;
78+
}
79+
EnumAdapters.pAdapters = pAdapterInfo;
80+
Status = pEnumAdapters2(&EnumAdapters);
81+
if (!NT_SUCCESS(Status))
82+
{
83+
KHR_ICD_TRACE("D3DKMT_ENUMADAPTERS2 status != SUCCESS\n");
84+
goto out;
85+
}
86+
for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.NumAdapters; AdapterIndex++)
87+
{
88+
D3DDDI_QUERYREGISTRY_INFO QueryArgs = {0};
89+
D3DDDI_QUERYREGISTRY_INFO* pQueryArgs = &QueryArgs;
90+
D3DDDI_QUERYREGISTRY_INFO* pQueryBuffer = NULL;
91+
QueryArgs.QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY;
92+
QueryArgs.QueryFlags.TranslatePath = TRUE;
93+
QueryArgs.ValueType = REG_SZ;
94+
#ifdef _WIN64
95+
wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverName"), L"OpenCLDriverName");
96+
#else
97+
// There is no WOW prefix for 32bit Windows hence make a specific check
98+
BOOL is_wow64;
99+
if (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)
100+
{
101+
wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverNameWow"), L"OpenCLDriverNameWow");
102+
}
103+
else
104+
{
105+
wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverName"), L"OpenCLDriverName");
106+
}
107+
#endif
108+
D3DKMT_QUERYADAPTERINFO QueryAdapterInfo = {0};
109+
QueryAdapterInfo.hAdapter = pAdapterInfo[AdapterIndex].hAdapter;
110+
QueryAdapterInfo.Type = KMTQAITYPE_QUERYREGISTRY;
111+
QueryAdapterInfo.pPrivateDriverData = &QueryArgs;
112+
QueryAdapterInfo.PrivateDriverDataSize = sizeof(QueryArgs);
113+
Status = D3DKMTQueryAdapterInfo(&QueryAdapterInfo);
114+
if (!NT_SUCCESS(Status))
115+
{
116+
KHR_ICD_TRACE("D3DKMT_QUERYADAPTERINFO status != SUCCESS\n");
117+
goto out;
118+
}
119+
if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW)
120+
{
121+
ULONG QueryBufferSize = sizeof(D3DDDI_QUERYREGISTRY_INFO) + QueryArgs.OutputValueSize;
122+
pQueryBuffer = (D3DDDI_QUERYREGISTRY_INFO*)malloc(QueryBufferSize);
123+
memcpy(pQueryBuffer, &QueryArgs, sizeof(D3DDDI_QUERYREGISTRY_INFO));
124+
QueryAdapterInfo.pPrivateDriverData = pQueryBuffer;
125+
QueryAdapterInfo.PrivateDriverDataSize = QueryBufferSize;
126+
Status = D3DKMTQueryAdapterInfo(&QueryAdapterInfo);
127+
pQueryArgs = pQueryBuffer;
128+
}
129+
if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
130+
{
131+
wchar_t* pWchar = pQueryArgs->OutputString;
132+
memset(cszLibraryName, 0, sizeof(cszLibraryName));
133+
{
134+
size_t len = wcstombs(cszLibraryName, pWchar, sizeof(cszLibraryName));
135+
KHR_ICD_ASSERT(len == (sizeof(cszLibraryName) - 1));
136+
khrIcdVendorAdd(cszLibraryName);
137+
}
138+
}
139+
else if (Status == STATUS_INVALID_PARAMETER && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_FAIL)
140+
{
141+
free(pQueryBuffer);
142+
goto out;
143+
}
144+
free(pQueryBuffer);
145+
}
146+
ret = true;
147+
out:
148+
free(pAdapterInfo);
149+
FreeLibrary(h);
150+
}
151+
#endif
152+
#endif
153+
return ret;
154+
}

loader/windows/icd_windows_dxgk.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (c) 2017-2019 The Khronos Group Inc.
3+
*
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
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
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.
15+
*
16+
* OpenCL is a trademark of Apple Inc. used under license by Khronos.
17+
*/
18+
19+
#include <stdbool.h>
20+
21+
bool khrIcdOsVendorsEnumerateDXGK(void);

loader/windows/icd_windows_hkr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ static bool ReadOpenCLKey(DEVINST dnDevNode)
117117

118118
result = RegQueryValueExA(
119119
hkey,
120-
OPENCL_REG_SUB_KEY,
120+
GetOpenCLRegKeyName(),
121121
NULL,
122122
&dwLibraryNameType,
123123
(LPBYTE)cszOclPath,

0 commit comments

Comments
 (0)