1 //
2 // Copyright (c) 2017 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 #define INITGUID
17 #include "harness.h"
18 #include <vector>
19
20 #include <tchar.h>
21
22 /*
23 * OpenCL state
24 */
25
26 clGetDeviceIDsFromD3D10KHR_fn clGetDeviceIDsFromD3D10KHR = NULL;
27 clCreateFromD3D10BufferKHR_fn clCreateFromD3D10BufferKHR = NULL;
28 clCreateFromD3D10Texture2DKHR_fn clCreateFromD3D10Texture2DKHR = NULL;
29 clCreateFromD3D10Texture3DKHR_fn clCreateFromD3D10Texture3DKHR = NULL;
30 clEnqueueAcquireD3D10ObjectsKHR_fn clEnqueueAcquireD3D10ObjectsKHR = NULL;
31 clEnqueueReleaseD3D10ObjectsKHR_fn clEnqueueReleaseD3D10ObjectsKHR = NULL;
32
33 #define INITPFN(x) \
34 x = (x ## _fn)clGetExtensionFunctionAddressForPlatform(platform, #x); NonTestRequire(x, "Failed to get function pointer for %s", #x);
35
36 void
HarnessD3D10_ExtensionCheck()37 HarnessD3D10_ExtensionCheck()
38 {
39 bool extensionPresent = false;
40 cl_int result = CL_SUCCESS;
41 cl_platform_id platform = NULL;
42 size_t set_size;
43
44 HarnessD3D10_TestBegin("Extension query");
45
46 result = clGetPlatformIDs(1, &platform, NULL);
47 NonTestRequire(result == CL_SUCCESS, "Failed to get any platforms.");
48 result = clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS, 0, NULL, &set_size);
49 NonTestRequire(result == CL_SUCCESS, "Failed to get size of extensions string.");
50 std::vector<char> extensions(set_size);
51 result = clGetPlatformInfo(platform, CL_PLATFORM_EXTENSIONS, extensions.size(), extensions.data(), NULL);
52 NonTestRequire(result == CL_SUCCESS, "Failed to list extensions.");
53 extensionPresent = strstr(extensions.data(), "cl_khr_d3d10_sharing") ? true : false;
54
55 if (!extensionPresent) {
56 // platform is required to report the extension only if all devices support it
57 cl_uint devicesCount;
58 result = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &devicesCount);
59 NonTestRequire(result == CL_SUCCESS, "Failed to get devices count.");
60 std::vector<cl_device_id> devices(devicesCount);
61 result = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, devicesCount, &devices[0], NULL);
62 NonTestRequire(result == CL_SUCCESS, "Failed to get devices count.");
63
64 for (cl_uint i = 0; i < devicesCount; i++) {
65 if (is_extension_available(devices[i], "cl_khr_d3d10_sharing")) {
66 extensionPresent = true;
67 break;
68 }
69 }
70 }
71
72 OSVERSIONINFO osvi;
73 osvi.dwOSVersionInfoSize = sizeof(osvi);
74 GetVersionEx(&osvi);
75 if (osvi.dwMajorVersion <= 5)
76 {
77 TestRequire(!extensionPresent, "Extension should not be exported on Windows < 6");
78 }
79 else
80 {
81 TestRequire(extensionPresent, "Extension should be exported on Windows >= 6");
82 }
83
84 Cleanup:
85 HarnessD3D10_TestEnd();
86
87 // early-out of the extension is not present
88 if (!extensionPresent)
89 {
90 HarnessD3D10_TestStats();
91 }
92 }
93
94 void
HarnessD3D10_Initialize(cl_platform_id platform)95 HarnessD3D10_Initialize(cl_platform_id platform)
96 {
97 HarnessD3D10_ExtensionCheck();
98
99 // extract function pointers for exported functions
100 INITPFN(clGetDeviceIDsFromD3D10KHR);
101 INITPFN(clCreateFromD3D10BufferKHR);
102 INITPFN(clCreateFromD3D10Texture2DKHR);
103 INITPFN(clCreateFromD3D10Texture3DKHR);
104 INITPFN(clEnqueueAcquireD3D10ObjectsKHR);
105 INITPFN(clEnqueueReleaseD3D10ObjectsKHR);
106 }
107
108 /*
109 * Window management
110 */
111
112 static IDXGISwapChain* HarnessD3D10_pSwapChain = NULL;
113 static ID3D10Device* HarnessD3D10_pDevice = NULL;
114 static HWND HarnessD3D10_hWnd = NULL;
115
HarnessD3D10_Proc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)116 static LRESULT WINAPI HarnessD3D10_Proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
117 {
118 switch(msg)
119 {
120 case WM_KEYDOWN:
121 return 0;
122 break;
123 case WM_DESTROY:
124 HarnessD3D10_hWnd = NULL;
125 PostQuitMessage(0);
126 return 0;
127 case WM_PAINT:
128 ValidateRect(hWnd, NULL);
129 return 0;
130 }
131 return DefWindowProc(hWnd, msg, wParam, lParam);
132 }
133
HarnessD3D10_InteractiveLoop()134 static void HarnessD3D10_InteractiveLoop()
135 {
136 MSG msg;
137 while(PeekMessage(&msg,HarnessD3D10_hWnd,0,0,PM_REMOVE))
138 {
139 TranslateMessage(&msg);
140 DispatchMessage(&msg);
141 }
142 }
143
HarnessD3D10_CreateDevice(IDXGIAdapter * pAdapter,ID3D10Device ** ppDevice)144 cl_int HarnessD3D10_CreateDevice(IDXGIAdapter* pAdapter, ID3D10Device **ppDevice)
145 {
146 HRESULT hr = S_OK;
147 unsigned int cuStatus = 1;
148
149 *ppDevice = NULL;
150
151 // create window
152 static WNDCLASSEX wc =
153 {
154 sizeof(WNDCLASSEX),
155 CS_CLASSDC,
156 HarnessD3D10_Proc,
157 0L,
158 0L,
159 GetModuleHandle(NULL),
160 NULL,
161 NULL,
162 NULL,
163 NULL,
164 _T( "cl_khr_d3d10_sharing_conformance" ),
165 NULL
166 };
167 RegisterClassEx(&wc);
168 HarnessD3D10_hWnd = CreateWindow(
169 _T( "cl_khr_d3d10_sharing_conformance" ),
170 _T( "cl_khr_d3d10_sharing_conformance" ),
171 WS_OVERLAPPEDWINDOW,
172 0, 0, 256, 256,
173 NULL,
174 NULL,
175 wc.hInstance,
176 NULL);
177 NonTestRequire(0 != HarnessD3D10_hWnd, "Failed to create window");
178
179 ShowWindow(HarnessD3D10_hWnd,SW_SHOWDEFAULT);
180 UpdateWindow(HarnessD3D10_hWnd);
181
182 RECT rc;
183 GetClientRect(HarnessD3D10_hWnd, &rc);
184 UINT width = rc.right - rc.left;
185 UINT height = rc.bottom - rc.top;
186
187 // Create device and swapchain
188 DXGI_SWAP_CHAIN_DESC sd;
189 ZeroMemory(&sd, sizeof(sd));
190 sd.BufferCount = 1;
191 sd.BufferDesc.Width = width;
192 sd.BufferDesc.Height = height;
193 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
194 sd.BufferDesc.RefreshRate.Numerator = 60;
195 sd.BufferDesc.RefreshRate.Denominator = 1;
196 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
197 sd.OutputWindow = HarnessD3D10_hWnd;
198 sd.SampleDesc.Count = 1;
199 sd.SampleDesc.Quality = 0;
200 sd.Windowed = TRUE;
201 hr = D3D10CreateDeviceAndSwapChain(
202 pAdapter,
203 D3D10_DRIVER_TYPE_HARDWARE,
204 NULL,
205 0,
206 D3D10_SDK_VERSION,
207 &sd,
208 &HarnessD3D10_pSwapChain,
209 &HarnessD3D10_pDevice);
210
211 if (FAILED(hr) ) {
212 return CL_DEVICE_NOT_FOUND;
213 }
214
215 *ppDevice = HarnessD3D10_pDevice;
216 return CL_SUCCESS;
217 }
218
HarnessD3D10_DestroyDevice()219 void HarnessD3D10_DestroyDevice()
220 {
221 HarnessD3D10_pSwapChain->Release();
222 HarnessD3D10_pDevice->Release();
223
224 if (HarnessD3D10_hWnd) DestroyWindow(HarnessD3D10_hWnd);
225 HarnessD3D10_hWnd = 0;
226 }
227
228 /*
229 *
230 * texture formats
231 *
232 */
233
234 #define ADD_TEXTURE_FORMAT(x,y,z,a,b,g) { x, y, z, a*b/8, g, #x, #y, #z, }
235 TextureFormat formats[] =
236 {
237 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_FLOAT , CL_RGBA , CL_FLOAT , 32, 4, TextureFormat::GENERIC_FLOAT ),
238 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_UINT , CL_RGBA , CL_UNSIGNED_INT32 , 32, 4, TextureFormat::GENERIC_UINT ),
239 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32B32A32_SINT , CL_RGBA , CL_SIGNED_INT32 , 32, 4, TextureFormat::GENERIC_SINT ),
240 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_FLOAT , CL_RGBA , CL_HALF_FLOAT , 16, 4, TextureFormat::GENERIC_FLOAT ),
241 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_UNORM , CL_RGBA , CL_UNORM_INT16 , 16, 4, TextureFormat::GENERIC_FLOAT ),
242 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_UINT , CL_RGBA , CL_UNSIGNED_INT16 , 16, 4, TextureFormat::GENERIC_UINT ),
243 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_SNORM , CL_RGBA , CL_SNORM_INT16 , 16, 4, TextureFormat::GENERIC_FLOAT ),
244 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16B16A16_SINT , CL_RGBA , CL_SIGNED_INT16 , 16, 4, TextureFormat::GENERIC_SINT ),
245 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_UNORM , CL_RGBA , CL_UNORM_INT8 , 8, 4, TextureFormat::GENERIC_FLOAT ),
246 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_UINT , CL_RGBA , CL_UNSIGNED_INT8 , 8, 4, TextureFormat::GENERIC_UINT ),
247 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_SNORM , CL_RGBA , CL_SNORM_INT8 , 8, 4, TextureFormat::GENERIC_FLOAT ),
248 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8B8A8_SINT , CL_RGBA , CL_SIGNED_INT8 , 8, 4, TextureFormat::GENERIC_SINT ),
249
250 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_FLOAT , CL_RG , CL_FLOAT , 32, 2, TextureFormat::GENERIC_FLOAT ),
251 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_UINT , CL_RG , CL_UNSIGNED_INT32 , 32, 2, TextureFormat::GENERIC_UINT ),
252 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32G32_SINT , CL_RG , CL_SIGNED_INT32 , 32, 2, TextureFormat::GENERIC_SINT ),
253 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_FLOAT , CL_RG , CL_HALF_FLOAT , 16, 2, TextureFormat::GENERIC_FLOAT ),
254 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_UNORM , CL_RG , CL_UNORM_INT16 , 16, 2, TextureFormat::GENERIC_FLOAT ),
255 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_UINT , CL_RG , CL_UNSIGNED_INT16 , 16, 2, TextureFormat::GENERIC_UINT ),
256 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_SNORM , CL_RG , CL_SNORM_INT16 , 16, 2, TextureFormat::GENERIC_FLOAT ),
257 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16G16_SINT , CL_RG , CL_SIGNED_INT16 , 16, 2, TextureFormat::GENERIC_SINT ),
258 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_UNORM , CL_RG , CL_UNORM_INT8 , 8, 2, TextureFormat::GENERIC_FLOAT ),
259 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_UINT , CL_RG , CL_UNSIGNED_INT8 , 8, 2, TextureFormat::GENERIC_UINT ),
260 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_SNORM , CL_RG , CL_SNORM_INT8 , 8, 2, TextureFormat::GENERIC_FLOAT ),
261 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8G8_SINT , CL_RG , CL_SIGNED_INT8 , 8, 2, TextureFormat::GENERIC_SINT ),
262
263 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_FLOAT , CL_R , CL_FLOAT , 32, 1, TextureFormat::GENERIC_FLOAT ),
264 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_UINT , CL_R , CL_UNSIGNED_INT32 , 32, 1, TextureFormat::GENERIC_UINT ),
265 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R32_SINT , CL_R , CL_SIGNED_INT32 , 32, 1, TextureFormat::GENERIC_SINT ),
266 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_FLOAT , CL_R , CL_HALF_FLOAT , 16, 1, TextureFormat::GENERIC_FLOAT ),
267 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_UNORM , CL_R , CL_UNORM_INT16 , 16, 1, TextureFormat::GENERIC_FLOAT ),
268 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_UINT , CL_R , CL_UNSIGNED_INT16 , 16, 1, TextureFormat::GENERIC_UINT ),
269 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_SNORM , CL_R , CL_SNORM_INT16 , 16, 1, TextureFormat::GENERIC_FLOAT ),
270 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R16_SINT , CL_R , CL_SIGNED_INT16 , 16, 1, TextureFormat::GENERIC_SINT ),
271 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_UNORM , CL_R , CL_UNORM_INT8 , 8, 1, TextureFormat::GENERIC_FLOAT ),
272 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_UINT , CL_R , CL_UNSIGNED_INT8 , 8, 1, TextureFormat::GENERIC_UINT ),
273 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_SNORM , CL_R , CL_SNORM_INT8 , 8, 1, TextureFormat::GENERIC_FLOAT ),
274 ADD_TEXTURE_FORMAT( DXGI_FORMAT_R8_SINT , CL_R , CL_SIGNED_INT8 , 8, 1, TextureFormat::GENERIC_SINT ),
275 };
276 UINT formatCount = sizeof(formats)/sizeof(formats[0]);
277
278 /*
279 *
280 * Logging and error reporting
281 *
282 */
283
284 static struct
285 {
286 cl_int testCount;
287 cl_int passCount;
288
289 cl_int nonTestFailures;
290 cl_int inTest;
291 cl_int currentTestPass;
292
293 char currentTestName[1024];
294 } HarnessD3D10_testStats = {0};
295
HarnessD3D10_TestBegin(const char * fmt,...)296 void HarnessD3D10_TestBegin(const char* fmt, ...)
297 {
298 va_list ap;
299
300 va_start(ap, fmt);
301 vsprintf(HarnessD3D10_testStats.currentTestName, fmt, ap);
302 va_end(ap);
303
304 TestPrint("[%s] ... ", HarnessD3D10_testStats.currentTestName);
305
306 HarnessD3D10_testStats.inTest = 1;
307 HarnessD3D10_testStats.currentTestPass = 1;
308 }
309
HarnessD3D10_TestFail()310 void HarnessD3D10_TestFail()
311 {
312 if (HarnessD3D10_testStats.inTest)
313 {
314 HarnessD3D10_testStats.currentTestPass = 0;
315 }
316 else
317 {
318 ++HarnessD3D10_testStats.nonTestFailures;
319 }
320 }
321
HarnessD3D10_TestEnd()322 void HarnessD3D10_TestEnd()
323 {
324 HarnessD3D10_testStats.inTest = 0;
325
326 HarnessD3D10_testStats.testCount += 1;
327 HarnessD3D10_testStats.passCount += HarnessD3D10_testStats.currentTestPass;
328
329 TestPrint("%s\n",
330 HarnessD3D10_testStats.currentTestPass ? "PASSED" : "FAILED");
331 }
332
HarnessD3D10_TestStats()333 void HarnessD3D10_TestStats()
334 {
335 TestPrint("PASSED %d of %d tests.\n", HarnessD3D10_testStats.passCount, HarnessD3D10_testStats.testCount);
336 if (HarnessD3D10_testStats.testCount > HarnessD3D10_testStats.passCount)
337 {
338 TestPrint("***FAILED***\n");
339 exit(1);
340 }
341 else
342 {
343 TestPrint("&&&& cl_khr_d3d10_sharing test PASSED\n");
344 }
345 exit(0);
346 }
347
348 /*
349 *
350 * Helper function
351 *
352 */
353
HarnessD3D10_CreateKernelFromSource(cl_kernel * outKernel,cl_device_id device,cl_context context,const char * source,const char * entrypoint)354 cl_int HarnessD3D10_CreateKernelFromSource(
355 cl_kernel *outKernel,
356 cl_device_id device,
357 cl_context context,
358 const char *source,
359 const char *entrypoint)
360 {
361 cl_int status;
362 cl_program program = NULL;
363 cl_kernel kernel = NULL;
364
365 // compile program
366 {
367 const char *sourceTexts[] = {source};
368 size_t sourceLengths[] = {strlen(source) };
369
370 status = create_single_kernel_helper_create_program(context, &program, 1, &sourceTexts[0]);
371 TestRequire(
372 CL_SUCCESS == status,
373 "clCreateProgramWithSource failed");
374 }
375 status = clBuildProgram(
376 program,
377 0,
378 NULL,
379 NULL,
380 NULL,
381 NULL);
382 if (CL_SUCCESS != status)
383 {
384 char log[2048] = {0};
385 status = clGetProgramBuildInfo(
386 program,
387 device,
388 CL_PROGRAM_BUILD_LOG,
389 sizeof(log),
390 log,
391 NULL);
392 TestPrint("error: %s\n", log);
393 TestRequire(
394 CL_SUCCESS == status,
395 "Compilation error log:\n%s\n", log);
396 }
397
398 kernel = clCreateKernel(
399 program,
400 entrypoint,
401 &status);
402 TestRequire(
403 CL_SUCCESS == status,
404 "clCreateKernel failed");
405
406 clReleaseProgram(program);
407 *outKernel = kernel;
408
409 Cleanup:
410
411 return CL_SUCCESS;
412 }
413
414
415
416