Windows 10 RS4 support for OpenCL ICD as per MS directive
authornikhiljnv <50375403+nikhiljnv@users.noreply.github.com>
Wed, 8 May 2019 13:06:17 +0000 (18:36 +0530)
committerNikhil Joshi <nikhilj@nvidia.com>
Tue, 21 May 2019 10:15:24 +0000 (15:45 +0530)
These are set of changes required by MS for Para-Virtualization
support for Windows 10 RS4.
Pull changes in pull request
https://github.com/KhronosGroup/OpenCL-ICD-Loader/pull/33

loader/windows/icd_windows.c
loader/windows/icd_windows_dxgk.c [new file with mode: 0644]
loader/windows/icd_windows_dxgk.h [new file with mode: 0644]
loader/windows/icd_windows_hkr.c

index 5f89085..ec86184 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "icd.h"
 #include "icd_windows_hkr.h"
+#include "icd_windows_dxgk.h"
 #include <stdio.h>
 #include <windows.h>
 #include <winreg.h>
@@ -39,9 +40,13 @@ BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVO
     HKEY platformsKey = NULL;
     DWORD dwIndex;
 
-    if (!khrIcdOsVendorsEnumerateHKR())
+    if (!khrIcdOsVendorsEnumerateDXGK())
     {
-        KHR_ICD_TRACE("Failed to enumerate HKR entries, continuing\n");
+        KHR_ICD_TRACE("Failed to load via DXGK interface on RS4, continuing\n");
+        if (!khrIcdOsVendorsEnumerateHKR())
+        {
+            KHR_ICD_TRACE("Failed to enumerate HKR entries, continuing\n");
+        }
     }
 
     KHR_ICD_TRACE("Opening key HKLM\\%s...\n", platformsName);
diff --git a/loader/windows/icd_windows_dxgk.c b/loader/windows/icd_windows_dxgk.c
new file mode 100644 (file)
index 0000000..1e46f6b
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2018 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software source and associated documentation files (the "Materials"),
+ * to deal in the Materials without restriction, including without limitation
+ * the rights to use, copy, modify, compile, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Materials, and to permit persons to
+ * whom the Materials are furnished to do so, subject the following terms and
+ * conditions:
+ *
+ * All modifications to the Materials used to create a binary that is
+ * distributed to third parties shall be provided to Khronos with an
+ * unrestricted license to use for the purposes of implementing bug fixes and
+ * enhancements to the Materials;
+ *
+ * If the binary is used as part of an OpenCL(TM) implementation, whether binary
+ * is distributed together with or separately to that implementation, then
+ * recipient must become an OpenCL Adopter and follow the published OpenCL
+ * conformance process for that implementation, details at:
+ * http://www.khronos.org/conformance/;
+ *
+ * The above copyright notice, the OpenCL trademark license, and this permission
+ * notice shall be included in all copies or substantial portions of the
+ * Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN
+ * THE MATERIALS.
+ *
+ * OpenCL is a trademark of Apple Inc. used under license by Khronos.
+ */
+
+#include "icd.h"
+#include <windows.h>
+#include "icd_windows_dxgk.h"
+#include <assert.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 "d3dkmthk.h"
+
+bool khrIcdOsVendorsEnumerateDXGK(void)
+{
+#if defined(DXGKDDI_INTERFACE_VERSION_WDDM2_4) && (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_4)
+    {
+        D3DKMT_ADAPTERINFO* pAdapterInfo;
+        D3DKMT_ENUMADAPTERS2 EnumAdapters;
+        NTSTATUS Status = STATUS_SUCCESS;
+
+        // Get handle to GDI Runtime
+        HMODULE h = LoadLibrary("gdi32.dll");
+
+        char cszLibraryName[1024] = { 0 };
+        EnumAdapters.NumAdapters = 0;
+        EnumAdapters.pAdapters = NULL;
+        PFND3DKMT_ENUMADAPTERS2 pEnumAdapters2 = (PFND3DKMT_ENUMADAPTERS2)GetProcAddress((HMODULE)h, "D3DKMTEnumAdapters2");
+        if (!pEnumAdapters2)
+        {
+            FreeLibrary(h);
+            return FALSE;
+        }
+        Status = pEnumAdapters2(&EnumAdapters);
+        if (!NT_SUCCESS(Status) && (Status != STATUS_BUFFER_TOO_SMALL))
+        {
+            FreeLibrary(h);
+            return FALSE;
+        }
+        pAdapterInfo = (D3DKMT_ADAPTERINFO*)malloc(sizeof(D3DKMT_ADAPTERINFO)*(EnumAdapters.NumAdapters));
+        EnumAdapters.pAdapters = pAdapterInfo;
+        Status = pEnumAdapters2(&EnumAdapters);
+        if (!NT_SUCCESS(Status))
+        {
+            FreeLibrary(h);
+            if (pAdapterInfo) free(pAdapterInfo);
+            return FALSE;
+        }
+        for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.NumAdapters; 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_MULTI_SZ;
+#ifdef _WIN64
+            wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverName"), L"OpenCLDriverName");
+#else
+            wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverNameWow"), L"OpenCLDriverNameWow");
+#endif
+            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))
+            {
+                FreeLibrary(h);
+                if (pAdapterInfo) free(pAdapterInfo);
+                return FALSE;
+            }
+            if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW)
+            {
+                unsigned int QueryBufferSize = sizeof(D3DDDI_QUERYREGISTRY_INFO) + QueryArgs.OutputValueSize;
+                pQueryBuffer = (D3DDDI_QUERYREGISTRY_INFO*)malloc(QueryBufferSize);
+                memcpy(pQueryBuffer, &QueryArgs, sizeof(D3DDDI_QUERYREGISTRY_INFO));
+                QueryAdapterInfo.pPrivateDriverData = pQueryBuffer;
+                QueryAdapterInfo.PrivateDriverDataSize = QueryBufferSize;
+                               KHR_ICD_TRACE("Attempting to retrieve adpater info for adapter handle %x\n", pAdapterInfo[AdapterIndex].hAdapter);
+                Status = pQueryAdapterInfo(&QueryAdapterInfo);
+                               if (!NT_SUCCESS(Status))
+                               {
+                               KHR_ICD_TRACE("Failed to retrieve adpater info for adapter handle %x, continuing with next adapater\n", pAdapterInfo[AdapterIndex].hAdapter);                   
+                   // Continue trying to get as much info on each adapter as possible.
+                       // It's too late to return FALSE and claim WDDM2_4 enumeration is not available here.
+                               continue;
+                               }
+                pQueryArgs = pQueryBuffer;
+            }
+            if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
+            {
+                wchar_t* pWchar = pQueryArgs->OutputString;
+                unsigned int i = 0;
+                memset(cszLibraryName, 0, sizeof(cszLibraryName));
+                {
+                    while ((*pWchar != L'\0') && (i<1023))
+                    {
+                        cszLibraryName[i] = (char)*pWchar;
+                        i++;
+                        pWchar++;
+                    }
+                    if (i < 1023) khrIcdVendorAdd(cszLibraryName);
+                }
+            }
+            if (pQueryBuffer) free(pQueryBuffer);
+        }
+        if (pAdapterInfo) free(pAdapterInfo);
+        FreeLibrary(h);
+        // Tried all available adapters and the status is not success.
+        if (!NT_SUCCESS(Status)) {
+            return FALSE;
+        }
+        else {
+            return TRUE;
+        }
+    }
+#endif
+    return FALSE;
+}
diff --git a/loader/windows/icd_windows_dxgk.h b/loader/windows/icd_windows_dxgk.h
new file mode 100644 (file)
index 0000000..c66c396
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software source and associated documentation files (the "Materials"),
+ * to deal in the Materials without restriction, including without limitation
+ * the rights to use, copy, modify, compile, merge, publish, distribute,
+ * sublicense, and/or sell copies of the Materials, and to permit persons to
+ * whom the Materials are furnished to do so, subject the following terms and
+ * conditions:
+ *
+ * All modifications to the Materials used to create a binary that is
+ * distributed to third parties shall be provided to Khronos with an
+ * unrestricted license to use for the purposes of implementing bug fixes and
+ * enhancements to the Materials;
+ *
+ * If the binary is used as part of an OpenCL(TM) implementation, whether binary
+ * is distributed together with or separately to that implementation, then
+ * recipient must become an OpenCL Adopter and follow the published OpenCL
+ * conformance process for that implementation, details at:
+ * http://www.khronos.org/conformance/;
+ *
+ * The above copyright notice, the OpenCL trademark license, and this permission
+ * notice shall be included in all copies or substantial portions of the
+ * Materials.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN
+ * THE MATERIALS.
+ *
+ * OpenCL is a trademark of Apple Inc. used under license by Khronos.
+ */
+
+#include <stdbool.h>
+
+bool khrIcdOsVendorsEnumerateDXGK(void);
index 5f6c534..092746a 100644 (file)
@@ -128,7 +128,7 @@ static bool ReadOpenCLKey(DEVINST dnDevNode)
             goto out;
         }
 
-        if (REG_SZ != dwLibraryNameType)
+        if (REG_MULTI_SZ != dwLibraryNameType)
         {
             KHR_ICD_TRACE("Unexpected registry entry 0x%x! continuing\n", dwLibraryNameType);
             goto out;
@@ -168,6 +168,7 @@ static DeviceProbeResult ProbeDevice(DEVINST devnode)
         devnode,
         0);
 
+    // TODO: consider extracting warning messages out of this function
     if (CR_SUCCESS != ret)
     {
         KHR_ICD_TRACE("    WARNING: failed to probe the status of the device 0x%x\n", ret);
@@ -340,6 +341,8 @@ bool khrIcdOsVendorsEnumerateHKR(void)
                     &szGuid,
                     0);
 
+                KHR_ICD_ASSERT(devpropType == DEVPROP_TYPE_GUID);
+
                 if (CR_SUCCESS != ret ||
                     !IsEqualGUID(&OCL_GUID_DEVCLASS_SOFTWARECOMPONENT, &guid))
                 {