diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e0b2254..9e2d7df8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ set (OPENCL_ICD_LOADER_SOURCES if (WIN32) list (APPEND OPENCL_ICD_LOADER_SOURCES + loader/windows/adapter.h loader/windows/icd_windows.c loader/windows/icd_windows.h loader/windows/icd_windows_dxgk.c @@ -82,28 +83,6 @@ set_target_properties (OpenCL PROPERTIES VERSION "1.2" SOVERSION "1") if (WIN32) target_link_libraries (OpenCL cfgmgr32.lib RuntimeObject.lib) - option (OPENCL_ICD_LOADER_REQUIRE_WDK "Build with D3DKMT support, which requires the Windows WDK." ON) - if (OPENCL_ICD_LOADER_REQUIRE_WDK) - if(DEFINED ENV{WDKContentRoot}) - file(GLOB D3DKMT_HEADER "$ENV{WDKContentRoot}/Include/*/km/d3dkmthk.h") - else() - file(GLOB D3DKMT_HEADER "$ENV{HOMEDRIVE}/Program Files */Windows Kits/10/Include/*/km/d3dkmthk.h") - endif() - - if(D3DKMT_HEADER) - list(GET D3DKMT_HEADER -1 LATEST_D3DKMT_HEADER) - get_filename_component(WDK_DIRECTORY ${LATEST_D3DKMT_HEADER} DIRECTORY) - get_filename_component(WDK_DIRECTORY ${WDK_DIRECTORY} DIRECTORY) - message(STATUS "Found the Windows WDK in: ${WDK_DIRECTORY}") - target_compile_definitions(OpenCL PRIVATE OPENCL_ICD_LOADER_REQUIRE_WDK) - target_include_directories(OpenCL PRIVATE ${WDK_DIRECTORY}/um) - target_include_directories(OpenCL PRIVATE ${WDK_DIRECTORY}/km) - target_include_directories(OpenCL PRIVATE ${WDK_DIRECTORY}/shared) - else() - message(FATAL_ERROR "The Windows WDK was not found. Consider disabling OPENCL_ICD_LOADER_REQUIRE_WDK. Aborting.") - endif() - endif() - if(NOT USE_DYNAMIC_VCXX_RUNTIME) string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") diff --git a/README.md b/README.md index 099f3a6c..fcea27c9 100644 --- a/README.md +++ b/README.md @@ -30,15 +30,6 @@ The OpenCL ICD Loader requires OpenCL Headers. To use system OpenCL Headers, please specify the OpenCL Header location using the CMake variable `OPENCL_ICD_LOADER_HEADERS_DIR`. By default, the OpenCL ICD Loader will look for OpenCL Headers in the `inc` directory. -By default, the OpenCL ICD Loader on Windows requires the Windows Driver Kit (WDK). -To build OpenCL ICD Loader with WDK support - -* Install recent Windows WDK currently at https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk - -* Establish environment variable WDK to include directory. Ex: set WDK=C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0 - -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. -This dependency may be removed in the future. - The OpenCL ICD Loader uses CMake for its build system. If CMake is not provided by your build system or OS package manager, please consult the [CMake website](https://cmake.org). diff --git a/loader/windows/OpenCL.rc b/loader/windows/OpenCL.rc index 38f2c84e..2d983f7a 100644 --- a/loader/windows/OpenCL.rc +++ b/loader/windows/OpenCL.rc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Khronos Group Inc. + * Copyright (c) 2016-2020 The Khronos Group Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ #define OPENCL_ICD_LOADER_VERSION_MAJOR 2 #define OPENCL_ICD_LOADER_VERSION_MINOR 2 -#define OPENCL_ICD_LOADER_VERSION_REV 7 +#define OPENCL_ICD_LOADER_VERSION_REV 8 #ifdef RC_INVOKED @@ -43,7 +43,7 @@ BEGIN BEGIN VALUE "FileDescription" ,"OpenCL Client DLL" VALUE "ProductName" ,"Khronos OpenCL ICD Loader" - VALUE "LegalCopyright" ,"Copyright \251 The Khronos Group Inc 2016-2019" + VALUE "LegalCopyright" ,"Copyright \251 The Khronos Group Inc 2016-2020" VALUE "FileVersion" ,OPENCL_ICD_LOADER_VERSION_STRING ".0" VALUE "CompanyName" ,"Khronos Group" VALUE "InternalName" ,"OpenCL" diff --git a/loader/windows/adapter.h b/loader/windows/adapter.h new file mode 100644 index 00000000..ef97d665 --- /dev/null +++ b/loader/windows/adapter.h @@ -0,0 +1,80 @@ +/* +* Copyright (c) 2019 The Khronos Group Inc. +* Copyright (c) 2019 Valve Corporation +* Copyright (c) 2019 LunarG, Inc. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* Author: Lenny Komow +*/ + +typedef struct LoaderEnumAdapters2 { + ULONG adapter_count; + struct { + UINT handle; + LUID luid; + ULONG source_count; + BOOL present_move_regions_preferred; + } * adapters; +} LoaderEnumAdapters2; + +typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderEnumAdapters2)(const LoaderEnumAdapters2 *); + +typedef enum AdapterInfoType { + LOADER_QUERY_TYPE_REGISTRY = 48, +} AdapterInfoType; + +typedef struct LoaderQueryAdapterInfo { + UINT handle; + AdapterInfoType type; + VOID *private_data; + UINT private_data_size; +} LoaderQueryAdapterInfo; + +typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderQueryAdapterInfo)(const LoaderQueryAdapterInfo *); + +typedef enum LoaderQueryRegistryType { + LOADER_QUERY_REGISTRY_ADAPTER_KEY = 1, +} LoaderQueryRegistryType; + +typedef enum LoaderQueryRegistryStatus { + LOADER_QUERY_REGISTRY_STATUS_SUCCESS = 0, + LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW = 1, +} LoaderQueryRegistryStatus; + +typedef struct LoaderQueryRegistryFlags { + union { + struct { + UINT translate_path : 1; + UINT mutable_value : 1; + UINT reserved : 30; + }; + UINT value; + }; +} LoaderQueryRegistryFlags; + +typedef struct LoaderQueryRegistryInfo { + LoaderQueryRegistryType query_type; + LoaderQueryRegistryFlags query_flags; + WCHAR value_name[MAX_PATH]; + ULONG value_type; + ULONG physical_adapter_index; + ULONG output_value_size; + LoaderQueryRegistryStatus status; + union { + DWORD output_dword; + UINT64 output_qword; + WCHAR output_string[1]; + BYTE output_binary[1]; + }; +} LoaderQueryRegistryInfo; diff --git a/loader/windows/icd_windows_dxgk.c b/loader/windows/icd_windows_dxgk.c index d16986b9..6f1568e4 100644 --- a/loader/windows/icd_windows_dxgk.c +++ b/loader/windows/icd_windows_dxgk.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Khronos Group Inc. + * Copyright (c) 2017-2020 The Khronos Group Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,109 +19,109 @@ #include "icd.h" #include "icd_windows_dxgk.h" -#if defined(OPENCL_ICD_LOADER_REQUIRE_WDK) #include +#include "adapter.h" #ifndef NTSTATUS typedef LONG NTSTATUS; #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023) -#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) -#endif - -#include +#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) #endif bool khrIcdOsVendorsEnumerateDXGK(void) { bool ret = false; int result = 0; -#if defined(OPENCL_ICD_LOADER_REQUIRE_WDK) -#if defined(DXGKDDI_INTERFACE_VERSION_WDDM2_4) && (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_4) + // Get handle to GDI Runtime HMODULE h = LoadLibrary("gdi32.dll"); if (h == NULL) return ret; - if(GetProcAddress((HMODULE)h, "D3DKMTSubmitPresentBltToHwQueue")) // OS Version check + if(GetProcAddress(h, "D3DKMTSubmitPresentBltToHwQueue")) // OS Version check { - D3DKMT_ADAPTERINFO* pAdapterInfo = NULL; - D3DKMT_ENUMADAPTERS2 EnumAdapters; - NTSTATUS Status = STATUS_SUCCESS; + LoaderEnumAdapters2 EnumAdapters; + NTSTATUS status = STATUS_SUCCESS; char cszLibraryName[MAX_PATH] = { 0 }; - EnumAdapters.NumAdapters = 0; - EnumAdapters.pAdapters = NULL; - PFND3DKMT_ENUMADAPTERS2 pEnumAdapters2 = (PFND3DKMT_ENUMADAPTERS2)GetProcAddress((HMODULE)h, "D3DKMTEnumAdapters2"); + EnumAdapters.adapter_count = 0; + EnumAdapters.adapters = NULL; + PFN_LoaderEnumAdapters2 pEnumAdapters2 = (PFN_LoaderEnumAdapters2)GetProcAddress(h, "D3DKMTEnumAdapters2"); if (!pEnumAdapters2) { - KHR_ICD_TRACE("GetProcAddress failed for D3DKMT_ENUMADAPTERS2\n"); + KHR_ICD_TRACE("GetProcAddress failed for D3DKMTEnumAdapters2\n"); + goto out; + } + PFN_LoaderQueryAdapterInfo pQueryAdapterInfo = (PFN_LoaderQueryAdapterInfo)GetProcAddress(h, "D3DKMTQueryAdapterInfo"); + if (!pQueryAdapterInfo) + { + KHR_ICD_TRACE("GetProcAddress failed for D3DKMTQueryAdapterInfo\n"); goto out; } while (1) { - EnumAdapters.NumAdapters = 0; - EnumAdapters.pAdapters = NULL; - Status = pEnumAdapters2(&EnumAdapters); - if (Status == STATUS_BUFFER_TOO_SMALL) + EnumAdapters.adapter_count = 0; + EnumAdapters.adapters = NULL; + status = pEnumAdapters2(&EnumAdapters); + if (status == STATUS_BUFFER_TOO_SMALL) { // Number of Adapters increased between calls, retry; continue; } - else if (!NT_SUCCESS(Status)) + else if (!NT_SUCCESS(status)) { - KHR_ICD_TRACE("D3DKMT_ENUMADAPTERS2 status != SUCCESS\n"); + KHR_ICD_TRACE("D3DKMTEnumAdapters2 status != SUCCESS\n"); goto out; } break; } - pAdapterInfo = (D3DKMT_ADAPTERINFO*)malloc(sizeof(D3DKMT_ADAPTERINFO)*(EnumAdapters.NumAdapters)); - if (pAdapterInfo == NULL) + EnumAdapters.adapters = malloc(sizeof(*EnumAdapters.adapters)*(EnumAdapters.adapter_count)); + if (EnumAdapters.adapters == NULL) { - KHR_ICD_TRACE("Allocation failure for AdapterInfo buffer\n"); + KHR_ICD_TRACE("Allocation failure for adapters buffer\n"); goto out; } - EnumAdapters.pAdapters = pAdapterInfo; - Status = pEnumAdapters2(&EnumAdapters); - if (!NT_SUCCESS(Status)) + status = pEnumAdapters2(&EnumAdapters); + if (!NT_SUCCESS(status)) { - KHR_ICD_TRACE("D3DKMT_ENUMADAPTERS2 status != SUCCESS\n"); + KHR_ICD_TRACE("D3DKMTEnumAdapters2 status != SUCCESS\n"); goto out; } const char* cszOpenCLRegKeyName = getOpenCLRegKeyName(); const int szOpenCLRegKeyName = (int)(strlen(cszOpenCLRegKeyName) + 1)*sizeof(cszOpenCLRegKeyName[0]); - for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.NumAdapters; AdapterIndex++) + for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.adapter_count; AdapterIndex++) { - D3DDDI_QUERYREGISTRY_INFO queryArgs = {0}; - D3DDDI_QUERYREGISTRY_INFO* pQueryArgs = &queryArgs; - D3DDDI_QUERYREGISTRY_INFO* pQueryBuffer = NULL; - queryArgs.QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY; - queryArgs.QueryFlags.TranslatePath = TRUE; - queryArgs.ValueType = REG_SZ; + LoaderQueryRegistryInfo queryArgs = {0}; + LoaderQueryRegistryInfo* pQueryArgs = &queryArgs; + LoaderQueryRegistryInfo* pQueryBuffer = NULL; + queryArgs.query_type = LOADER_QUERY_REGISTRY_ADAPTER_KEY; + queryArgs.query_flags.translate_path = TRUE; + queryArgs.value_type = REG_SZ; result = MultiByteToWideChar( CP_ACP, 0, cszOpenCLRegKeyName, szOpenCLRegKeyName, - queryArgs.ValueName, - ARRAYSIZE(queryArgs.ValueName)); + queryArgs.value_name, + ARRAYSIZE(queryArgs.value_name)); if (!result) { KHR_ICD_TRACE("MultiByteToWideChar status != SUCCESS\n"); continue; } - D3DKMT_QUERYADAPTERINFO queryAdapterInfo = {0}; - queryAdapterInfo.hAdapter = pAdapterInfo[AdapterIndex].hAdapter; - queryAdapterInfo.Type = KMTQAITYPE_QUERYREGISTRY; - queryAdapterInfo.pPrivateDriverData = &queryArgs; - queryAdapterInfo.PrivateDriverDataSize = sizeof(queryArgs); - Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo); - if (!NT_SUCCESS(Status)) + LoaderQueryAdapterInfo queryAdapterInfo = {0}; + queryAdapterInfo.handle = EnumAdapters.adapters[AdapterIndex].handle; + queryAdapterInfo.type = LOADER_QUERY_TYPE_REGISTRY; + queryAdapterInfo.private_data = &queryArgs; + queryAdapterInfo.private_data_size = sizeof(queryArgs); + status = pQueryAdapterInfo(&queryAdapterInfo); + if (!NT_SUCCESS(status)) { // Try a different value type. Some vendors write the key as a multi-string type. - queryArgs.ValueType = REG_MULTI_SZ; - Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo); - if (NT_SUCCESS(Status)) + queryArgs.value_type = REG_MULTI_SZ; + status = pQueryAdapterInfo(&queryAdapterInfo); + if (NT_SUCCESS(status)) { KHR_ICD_TRACE("Accepting multi-string registry key type\n"); } @@ -132,29 +132,30 @@ bool khrIcdOsVendorsEnumerateDXGK(void) continue; } } - if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW) + if (NT_SUCCESS(status) && pQueryArgs->status == LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW) { - ULONG queryBufferSize = sizeof(D3DDDI_QUERYREGISTRY_INFO) + queryArgs.OutputValueSize; - pQueryBuffer = (D3DDDI_QUERYREGISTRY_INFO*)malloc(queryBufferSize); + ULONG queryBufferSize = sizeof(LoaderQueryRegistryInfo) + queryArgs.output_value_size; + pQueryBuffer = malloc(queryBufferSize); if (pQueryBuffer == NULL) continue; - memcpy(pQueryBuffer, &queryArgs, sizeof(D3DDDI_QUERYREGISTRY_INFO)); - queryAdapterInfo.pPrivateDriverData = pQueryBuffer; - queryAdapterInfo.PrivateDriverDataSize = queryBufferSize; - Status = D3DKMTQueryAdapterInfo(&queryAdapterInfo); + memcpy(pQueryBuffer, &queryArgs, sizeof(LoaderQueryRegistryInfo)); + queryAdapterInfo.private_data = pQueryBuffer; + queryAdapterInfo.private_data_size = queryBufferSize; + status = pQueryAdapterInfo(&queryAdapterInfo); pQueryArgs = pQueryBuffer; } - if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS) + if (NT_SUCCESS(status) && pQueryArgs->status == LOADER_QUERY_REGISTRY_STATUS_SUCCESS) { - wchar_t* pWchar = pQueryArgs->OutputString; + wchar_t* pWchar = pQueryArgs->output_string; memset(cszLibraryName, 0, sizeof(cszLibraryName)); { - size_t len = wcstombs(cszLibraryName, pWchar, sizeof(cszLibraryName)); + size_t len; + wcstombs_s(&len, cszLibraryName, sizeof(cszLibraryName), pWchar, sizeof(cszLibraryName)); KHR_ICD_ASSERT(len == (sizeof(cszLibraryName) - 1)); - ret |= adapterAdd(cszLibraryName, pAdapterInfo[AdapterIndex].AdapterLuid); + ret |= adapterAdd(cszLibraryName, EnumAdapters.adapters[AdapterIndex].luid); } } - else if (Status == STATUS_INVALID_PARAMETER && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_FAIL) + else if (status == STATUS_INVALID_PARAMETER) { free(pQueryBuffer); goto out; @@ -162,12 +163,10 @@ bool khrIcdOsVendorsEnumerateDXGK(void) free(pQueryBuffer); } out: - free(pAdapterInfo); + free(EnumAdapters.adapters); } FreeLibrary(h); -#endif -#endif return ret; }