1e46f6b60fe6cec90258ddcbca49df923851ccb6
[platform/upstream/OpenCL-ICD-Loader.git] / loader / windows / icd_windows_dxgk.c
1 /*
2  * Copyright (c) 2018 The Khronos Group Inc.
3  *
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
10  * conditions:
11  *
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;
16  *
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/;
22  *
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
25  * Materials.
26  *
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
33  * THE MATERIALS.
34  *
35  * OpenCL is a trademark of Apple Inc. used under license by Khronos.
36  */
37
38 #include "icd.h"
39 #include <windows.h>
40 #include "icd_windows_dxgk.h"
41 #include <assert.h>
42
43 #ifndef NTSTATUS
44 typedef LONG NTSTATUS;
45 #define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)
46 #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023)
47 #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
48 #endif
49
50 #include "d3dkmthk.h"
51
52 bool khrIcdOsVendorsEnumerateDXGK(void)
53 {
54 #if defined(DXGKDDI_INTERFACE_VERSION_WDDM2_4) && (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_4)
55     {
56         D3DKMT_ADAPTERINFO* pAdapterInfo;
57         D3DKMT_ENUMADAPTERS2 EnumAdapters;
58         NTSTATUS Status = STATUS_SUCCESS;
59
60         // Get handle to GDI Runtime
61         HMODULE h = LoadLibrary("gdi32.dll");
62
63         char cszLibraryName[1024] = { 0 };
64         EnumAdapters.NumAdapters = 0;
65         EnumAdapters.pAdapters = NULL;
66         PFND3DKMT_ENUMADAPTERS2 pEnumAdapters2 = (PFND3DKMT_ENUMADAPTERS2)GetProcAddress((HMODULE)h, "D3DKMTEnumAdapters2");
67         if (!pEnumAdapters2)
68         {
69             FreeLibrary(h);
70             return FALSE;
71         }
72         Status = pEnumAdapters2(&EnumAdapters);
73         if (!NT_SUCCESS(Status) && (Status != STATUS_BUFFER_TOO_SMALL))
74         {
75             FreeLibrary(h);
76             return FALSE;
77         }
78         pAdapterInfo = (D3DKMT_ADAPTERINFO*)malloc(sizeof(D3DKMT_ADAPTERINFO)*(EnumAdapters.NumAdapters));
79         EnumAdapters.pAdapters = pAdapterInfo;
80         Status = pEnumAdapters2(&EnumAdapters);
81         if (!NT_SUCCESS(Status))
82         {
83             FreeLibrary(h);
84             if (pAdapterInfo) free(pAdapterInfo);
85             return FALSE;
86         }
87         for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.NumAdapters; AdapterIndex++)
88         {
89             D3DDDI_QUERYREGISTRY_INFO QueryArgs = {0};
90             D3DDDI_QUERYREGISTRY_INFO* pQueryArgs = &QueryArgs;
91             D3DDDI_QUERYREGISTRY_INFO* pQueryBuffer = NULL;
92             QueryArgs.QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY;
93             QueryArgs.QueryFlags.TranslatePath = TRUE;
94             QueryArgs.ValueType = REG_MULTI_SZ;
95 #ifdef _WIN64
96             wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverName"), L"OpenCLDriverName");
97 #else
98             wcscpy_s(QueryArgs.ValueName, ARRAYSIZE(L"OpenCLDriverNameWow"), L"OpenCLDriverNameWow");
99 #endif
100             D3DKMT_QUERYADAPTERINFO QueryAdapterInfo = {0};
101             QueryAdapterInfo.hAdapter = pAdapterInfo[AdapterIndex].hAdapter;
102             QueryAdapterInfo.Type = KMTQAITYPE_QUERYREGISTRY;
103             QueryAdapterInfo.pPrivateDriverData = &QueryArgs;
104             QueryAdapterInfo.PrivateDriverDataSize = sizeof(QueryArgs);
105             Status = D3DKMTQueryAdapterInfo(&QueryAdapterInfo);
106             if (!NT_SUCCESS(Status))
107             {
108                 FreeLibrary(h);
109                 if (pAdapterInfo) free(pAdapterInfo);
110                 return FALSE;
111             }
112             if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW)
113             {
114                 unsigned int QueryBufferSize = sizeof(D3DDDI_QUERYREGISTRY_INFO) + QueryArgs.OutputValueSize;
115                 pQueryBuffer = (D3DDDI_QUERYREGISTRY_INFO*)malloc(QueryBufferSize);
116                 memcpy(pQueryBuffer, &QueryArgs, sizeof(D3DDDI_QUERYREGISTRY_INFO));
117                 QueryAdapterInfo.pPrivateDriverData = pQueryBuffer;
118                 QueryAdapterInfo.PrivateDriverDataSize = QueryBufferSize;
119                                 KHR_ICD_TRACE("Attempting to retrieve adpater info for adapter handle %x\n", pAdapterInfo[AdapterIndex].hAdapter);
120                 Status = pQueryAdapterInfo(&QueryAdapterInfo);
121                                 if (!NT_SUCCESS(Status))
122                                 {
123                                 KHR_ICD_TRACE("Failed to retrieve adpater info for adapter handle %x, continuing with next adapater\n", pAdapterInfo[AdapterIndex].hAdapter);                   
124                     // Continue trying to get as much info on each adapter as possible.
125                         // It's too late to return FALSE and claim WDDM2_4 enumeration is not available here.
126                                 continue;
127                                 }
128                 pQueryArgs = pQueryBuffer;
129             }
130             if (NT_SUCCESS(Status) && pQueryArgs->Status == D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
131             {
132                 wchar_t* pWchar = pQueryArgs->OutputString;
133                 unsigned int i = 0;
134                 memset(cszLibraryName, 0, sizeof(cszLibraryName));
135                 {
136                     while ((*pWchar != L'\0') && (i<1023))
137                     {
138                         cszLibraryName[i] = (char)*pWchar;
139                         i++;
140                         pWchar++;
141                     }
142                     if (i < 1023) khrIcdVendorAdd(cszLibraryName);
143                 }
144             }
145             if (pQueryBuffer) free(pQueryBuffer);
146         }
147         if (pAdapterInfo) free(pAdapterInfo);
148         FreeLibrary(h);
149         // Tried all available adapters and the status is not success.
150         if (!NT_SUCCESS(Status)) {
151             return FALSE;
152         }
153         else {
154             return TRUE;
155         }
156     }
157 #endif
158     return FALSE;
159 }