1 //
2 // Copyright (c) 2022 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
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #if !defined(_WIN32)
21 #include <stdbool.h>
22 #endif
23
24 #include <math.h>
25 #include <string.h>
26
27 #if !defined(__APPLE__)
28 #include <CL/cl.h>
29 #else
30 #include <OpenCL/cl.h>
31 #endif
32
33
34 #include "procs.h"
35 #include "harness/testHarness.h"
36 #include "harness/parseParameters.h"
37 #include "harness/deviceInfo.h"
38
39 #if !defined(_WIN32)
40 #include <unistd.h>
41 #endif
42 #include <vulkan_interop_common.hpp>
43 #include <vulkan_wrapper.hpp>
44
45 #define BUFFERSIZE 3000
46
params_reset()47 static void params_reset()
48 {
49 numCQ = 1;
50 multiImport = false;
51 multiCtx = false;
52 }
53
54 extern int test_buffer_common(cl_device_id device_, cl_context context_,
55 cl_command_queue queue_, int numElements_);
56 extern int test_image_common(cl_device_id device_, cl_context context_,
57 cl_command_queue queue_, int numElements_);
58
test_buffer_single_queue(cl_device_id device_,cl_context context_,cl_command_queue queue_,int numElements_)59 int test_buffer_single_queue(cl_device_id device_, cl_context context_,
60 cl_command_queue queue_, int numElements_)
61 {
62 params_reset();
63 log_info("RUNNING TEST WITH ONE QUEUE...... \n\n");
64 return test_buffer_common(device_, context_, queue_, numElements_);
65 }
test_buffer_multiple_queue(cl_device_id device_,cl_context context_,cl_command_queue queue_,int numElements_)66 int test_buffer_multiple_queue(cl_device_id device_, cl_context context_,
67 cl_command_queue queue_, int numElements_)
68 {
69 params_reset();
70 numCQ = 2;
71 log_info("RUNNING TEST WITH TWO QUEUE...... \n\n");
72 return test_buffer_common(device_, context_, queue_, numElements_);
73 }
test_buffer_multiImport_sameCtx(cl_device_id device_,cl_context context_,cl_command_queue queue_,int numElements_)74 int test_buffer_multiImport_sameCtx(cl_device_id device_, cl_context context_,
75 cl_command_queue queue_, int numElements_)
76 {
77 params_reset();
78 multiImport = true;
79 log_info("RUNNING TEST WITH MULTIPLE DEVICE MEMORY IMPORT "
80 "IN SAME CONTEXT...... \n\n");
81 return test_buffer_common(device_, context_, queue_, numElements_);
82 }
test_buffer_multiImport_diffCtx(cl_device_id device_,cl_context context_,cl_command_queue queue_,int numElements_)83 int test_buffer_multiImport_diffCtx(cl_device_id device_, cl_context context_,
84 cl_command_queue queue_, int numElements_)
85 {
86 params_reset();
87 multiImport = true;
88 multiCtx = true;
89 log_info("RUNNING TEST WITH MULTIPLE DEVICE MEMORY IMPORT "
90 "IN DIFFERENT CONTEXT...... \n\n");
91 return test_buffer_common(device_, context_, queue_, numElements_);
92 }
test_image_single_queue(cl_device_id device_,cl_context context_,cl_command_queue queue_,int numElements_)93 int test_image_single_queue(cl_device_id device_, cl_context context_,
94 cl_command_queue queue_, int numElements_)
95 {
96 params_reset();
97 log_info("RUNNING TEST WITH ONE QUEUE...... \n\n");
98 return test_image_common(device_, context_, queue_, numElements_);
99 }
test_image_multiple_queue(cl_device_id device_,cl_context context_,cl_command_queue queue_,int numElements_)100 int test_image_multiple_queue(cl_device_id device_, cl_context context_,
101 cl_command_queue queue_, int numElements_)
102 {
103 params_reset();
104 numCQ = 2;
105 log_info("RUNNING TEST WITH TWO QUEUE...... \n\n");
106 return test_image_common(device_, context_, queue_, numElements_);
107 }
108
109 test_definition test_list[] = { ADD_TEST(buffer_single_queue),
110 ADD_TEST(buffer_multiple_queue),
111 ADD_TEST(buffer_multiImport_sameCtx),
112 ADD_TEST(buffer_multiImport_diffCtx),
113 ADD_TEST(image_single_queue),
114 ADD_TEST(image_multiple_queue),
115 ADD_TEST(consistency_external_buffer),
116 ADD_TEST(consistency_external_image),
117 ADD_TEST(consistency_external_semaphore),
118 ADD_TEST(platform_info),
119 ADD_TEST(device_info) };
120
121 const int test_num = ARRAY_SIZE(test_list);
122
123 cl_device_type gDeviceType = CL_DEVICE_TYPE_DEFAULT;
124 char *choosen_platform_name = NULL;
125 cl_platform_id platform = NULL;
126 cl_int choosen_platform_index = -1;
127 char platform_name[1024] = "";
128 cl_platform_id select_platform = NULL;
129 char *extensions = NULL;
130 size_t extensionSize = 0;
131 cl_uint num_devices = 0;
132 cl_uint device_no = 0;
133 cl_device_id *devices;
134 const size_t bufsize = BUFFERSIZE;
135 char buf[BUFFERSIZE];
136 cl_uchar uuid[CL_UUID_SIZE_KHR];
137 unsigned int numCQ;
138 bool multiImport;
139 bool multiCtx;
140 bool debug_trace = false;
141 bool useSingleImageKernel = false;
142 bool useDeviceLocal = false;
143 bool disableNTHandleType = false;
144 bool enableOffset = false;
145 bool non_dedicated = false;
146
printUsage(const char * execName)147 static void printUsage(const char *execName)
148 {
149 const char *p = strrchr(execName, '/');
150 if (p != NULL) execName = p + 1;
151
152 log_info("Usage: %s [test_names] [options]\n", execName);
153 log_info("Test names:\n");
154 for (int i = 0; i < test_num; i++)
155 {
156 log_info("\t%s\n", test_list[i].name);
157 }
158 log_info("\n");
159 log_info("Options:\n");
160 log_info("\t--debug_trace - Enables additional debug info logging\n");
161 log_info("\t--non_dedicated - Choose dedicated Vs. non_dedicated \n");
162 }
163
parseParams(int argc,const char * argv[],const char ** argList)164 size_t parseParams(int argc, const char *argv[], const char **argList)
165 {
166 size_t argCount = 1;
167 for (int i = 1; i < argc; i++)
168 {
169 if (argv[i] == NULL) break;
170 if (argv[i][0] == '-')
171 {
172 if (!strcmp(argv[i], "--debug_trace"))
173 {
174 debug_trace = true;
175 }
176 if (!strcmp(argv[i], "--useSingleImageKernel"))
177 {
178 useSingleImageKernel = true;
179 }
180 if (!strcmp(argv[i], "--useDeviceLocal"))
181 {
182 useDeviceLocal = true;
183 }
184 if (!strcmp(argv[i], "--disableNTHandleType"))
185 {
186 disableNTHandleType = true;
187 }
188 if (!strcmp(argv[i], "--enableOffset"))
189 {
190 enableOffset = true;
191 }
192 if (!strcmp(argv[i], "--non_dedicated"))
193 {
194 non_dedicated = true;
195 }
196 if (strcmp(argv[i], "-h") == 0)
197 {
198 printUsage(argv[0]);
199 argCount = 0; // Returning argCount=0 to assert error in main()
200 break;
201 }
202 }
203 else
204 {
205 argList[argCount] = argv[i];
206 argCount++;
207 }
208 }
209 return argCount;
210 }
211
main(int argc,const char * argv[])212 int main(int argc, const char *argv[])
213 {
214 int errNum = 0;
215
216 test_start();
217 params_reset();
218
219 if (!checkVkSupport())
220 {
221 log_info("Vulkan supported GPU not found \n");
222 log_info("TEST SKIPPED \n");
223 return 0;
224 }
225
226 VulkanDevice vkDevice;
227
228 cl_device_type requestedDeviceType = CL_DEVICE_TYPE_GPU;
229 char *force_cpu = getenv("CL_DEVICE_TYPE");
230 if (force_cpu != NULL)
231 {
232 if (strcmp(force_cpu, "gpu") == 0
233 || strcmp(force_cpu, "CL_DEVICE_TYPE_GPU") == 0)
234 requestedDeviceType = CL_DEVICE_TYPE_GPU;
235 else if (strcmp(force_cpu, "cpu") == 0
236 || strcmp(force_cpu, "CL_DEVICE_TYPE_CPU") == 0)
237 requestedDeviceType = CL_DEVICE_TYPE_CPU;
238 else if (strcmp(force_cpu, "accelerator") == 0
239 || strcmp(force_cpu, "CL_DEVICE_TYPE_ACCELERATOR") == 0)
240 requestedDeviceType = CL_DEVICE_TYPE_ACCELERATOR;
241 else if (strcmp(force_cpu, "CL_DEVICE_TYPE_DEFAULT") == 0)
242 requestedDeviceType = CL_DEVICE_TYPE_DEFAULT;
243 }
244
245 if (requestedDeviceType != CL_DEVICE_TYPE_GPU)
246 {
247 log_info("Vulkan tests can only run on a GPU device.\n");
248 return 0;
249 }
250 gDeviceType = CL_DEVICE_TYPE_GPU;
251
252 const char **argList = (const char **)calloc(argc, sizeof(char *));
253 size_t argCount = parseParams(argc, argv, argList);
254 if (argCount == 0) return 0;
255 // get the platform ID
256 errNum = clGetPlatformIDs(1, &platform, NULL);
257 if (errNum != CL_SUCCESS)
258 {
259 print_error(errNum, "Error: Failed to get platform\n");
260 return errNum;
261 }
262
263 errNum =
264 clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &num_devices);
265 if (CL_SUCCESS != errNum)
266 {
267 print_error(errNum, "clGetDeviceIDs failed in returning of devices\n");
268 return errNum;
269 }
270 devices = (cl_device_id *)malloc(num_devices * sizeof(cl_device_id));
271 if (NULL == devices)
272 {
273 print_error(errNum, "Unable to allocate memory for devices\n");
274 return CL_OUT_OF_HOST_MEMORY;
275 }
276 errNum = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, num_devices, devices,
277 NULL);
278 if (CL_SUCCESS != errNum)
279 {
280 print_error(errNum, "Failed to get deviceID.\n");
281 return errNum;
282 }
283 for (device_no = 0; device_no < num_devices; device_no++)
284 {
285 errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS, 0,
286 NULL, &extensionSize);
287 if (CL_SUCCESS != errNum)
288 {
289 log_error("Error in clGetDeviceInfo for getting "
290 "device_extension size....\n");
291 return errNum;
292 }
293 extensions = (char *)malloc(extensionSize);
294 if (NULL == extensions)
295 {
296 log_error("Unable to allocate memory for extensions\n");
297 return CL_OUT_OF_HOST_MEMORY;
298 }
299 errNum =
300 clGetDeviceInfo(devices[device_no], CL_DEVICE_EXTENSIONS,
301 extensionSize, extensions, NULL /*&extensionSize*/);
302 if (CL_SUCCESS != errNum)
303 {
304 print_error(errNum,
305 "Error in clGetDeviceInfo for getting "
306 "device_extension\n");
307 return errNum;
308 }
309 errNum = clGetDeviceInfo(devices[device_no], CL_DEVICE_UUID_KHR,
310 CL_UUID_SIZE_KHR, uuid, &extensionSize);
311 if (CL_SUCCESS != errNum)
312 {
313 print_error(errNum, "clGetDeviceInfo failed with error\n ");
314 return errNum;
315 }
316 errNum =
317 memcmp(uuid, vkDevice.getPhysicalDevice().getUUID(), VK_UUID_SIZE);
318 if (errNum == 0)
319 {
320 break;
321 }
322 }
323 if (device_no >= num_devices)
324 {
325 fprintf(stderr,
326 "OpenCL error: "
327 "No Vulkan-OpenCL Interop capable GPU found.\n");
328 }
329 if (!(is_extension_available(devices[device_no], "cl_khr_external_memory")
330 && is_extension_available(devices[device_no],
331 "cl_khr_external_semaphore")))
332 {
333 log_info("Device does not support cl_khr_external_memory "
334 "or cl_khr_external_semaphore\n");
335 log_info(" TEST SKIPPED\n");
336 return CL_SUCCESS;
337 }
338 init_cl_vk_ext(platform);
339
340 // Execute tests.
341 // Note: don't use the entire harness, because we have a different way of
342 // obtaining the device (via the context)
343 errNum = parseAndCallCommandLineTests(argCount, argList, devices[device_no],
344 test_num, test_list, true, 0, 1024);
345 return errNum;
346 }
347