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 #include "harness/testHarness.h"
17 #include <iostream>
18 #include <string>
19 
20 bool gHost = false; // flag for testing native host threads (test verification)
21 bool gOldAPI = false; // flag for testing with old API (OpenCL 1.2) - test verification
22 bool gContinueOnError = false; // execute all cases even when errors detected
23 bool gNoGlobalVariables = false; // disable cases with global atomics in program scope
24 bool gNoGenericAddressSpace = false; // disable cases with generic address space
25 bool gUseHostPtr = false; // use malloc/free with CL_MEM_USE_HOST_PTR instead of clSVMAlloc/clSVMFree
26 bool gDebug = false; // always print OpenCL kernel code
27 int gInternalIterations = 10000; // internal test iterations for atomic operation, sufficient to verify atomicity
28 int gMaxDeviceThreads = 1024; // maximum number of threads executed on OCL device
29 cl_device_atomic_capabilities gAtomicMemCap,
30     gAtomicFenceCap; // atomic memory and fence capabilities for this device
31 
32 extern int test_atomic_init(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
33 extern int test_atomic_store(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
34 extern int test_atomic_load(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
35 extern int test_atomic_store_load(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
36 extern int test_atomic_exchange(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
37 extern int test_atomic_compare_exchange_weak(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
38 extern int test_atomic_compare_exchange_strong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
39 extern int test_atomic_fetch_add(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
40 extern int test_atomic_fetch_sub(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
41 extern int test_atomic_fetch_and(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
42 extern int test_atomic_fetch_or(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
43 extern int test_atomic_fetch_orand(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
44 extern int test_atomic_fetch_xor(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
45 extern int test_atomic_fetch_xor2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
46 extern int test_atomic_fetch_min(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
47 extern int test_atomic_fetch_max(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
48 extern int test_atomic_flag(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
49 extern int test_atomic_fence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
50 
51 extern int test_svm_atomic_init(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
52 extern int test_svm_atomic_store(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
53 extern int test_svm_atomic_load(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
54 extern int test_svm_atomic_store_load(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
55 extern int test_svm_atomic_exchange(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
56 extern int test_svm_atomic_compare_exchange_weak(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
57 extern int test_svm_atomic_compare_exchange_strong(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
58 extern int test_svm_atomic_fetch_add(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
59 extern int test_svm_atomic_fetch_sub(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
60 extern int test_svm_atomic_fetch_and(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
61 extern int test_svm_atomic_fetch_or(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
62 extern int test_svm_atomic_fetch_orand(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
63 extern int test_svm_atomic_fetch_xor(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
64 extern int test_svm_atomic_fetch_xor2(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
65 extern int test_svm_atomic_fetch_min(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
66 extern int test_svm_atomic_fetch_max(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
67 extern int test_svm_atomic_flag(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
68 extern int test_svm_atomic_fence(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements);
69 
70 test_definition test_list[] = {
71     ADD_TEST( atomic_init ),
72     ADD_TEST( atomic_store ),
73     ADD_TEST( atomic_load ),
74     ADD_TEST( atomic_exchange ),
75     ADD_TEST( atomic_compare_exchange_weak ),
76     ADD_TEST( atomic_compare_exchange_strong ),
77     ADD_TEST( atomic_fetch_add ),
78     ADD_TEST( atomic_fetch_sub ),
79     ADD_TEST( atomic_fetch_and ),
80     ADD_TEST( atomic_fetch_or ),
81     ADD_TEST( atomic_fetch_orand ),
82     ADD_TEST( atomic_fetch_xor ),
83     ADD_TEST( atomic_fetch_xor2 ),
84     ADD_TEST( atomic_fetch_min ),
85     ADD_TEST( atomic_fetch_max ),
86     ADD_TEST( atomic_flag ),
87     ADD_TEST( atomic_fence ),
88 
89     ADD_TEST( svm_atomic_init ),
90     ADD_TEST( svm_atomic_store ),
91     ADD_TEST( svm_atomic_load ),
92     ADD_TEST( svm_atomic_exchange ),
93     ADD_TEST( svm_atomic_compare_exchange_weak ),
94     ADD_TEST( svm_atomic_compare_exchange_strong ),
95     ADD_TEST( svm_atomic_fetch_add ),
96     ADD_TEST( svm_atomic_fetch_sub ),
97     ADD_TEST( svm_atomic_fetch_and ),
98     ADD_TEST( svm_atomic_fetch_or ),
99     ADD_TEST( svm_atomic_fetch_orand ),
100     ADD_TEST( svm_atomic_fetch_xor ),
101     ADD_TEST( svm_atomic_fetch_xor2 ),
102     ADD_TEST( svm_atomic_fetch_min ),
103     ADD_TEST( svm_atomic_fetch_max ),
104     ADD_TEST( svm_atomic_flag ),
105     ADD_TEST( svm_atomic_fence ),
106 };
107 
108 const int test_num = ARRAY_SIZE( test_list );
109 
InitCL(cl_device_id device)110 test_status InitCL(cl_device_id device) {
111     auto version = get_device_cl_version(device);
112     auto expected_min_version = Version(2, 0);
113 
114     if (version < expected_min_version)
115     {
116         version_expected_info("Test", "OpenCL",
117                               expected_min_version.to_string().c_str(),
118                               version.to_string().c_str());
119         return TEST_SKIP;
120     }
121 
122     if (version >= Version(3, 0))
123     {
124         cl_int error;
125 
126         error = clGetDeviceInfo(device, CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES,
127                                 sizeof(gAtomicMemCap), &gAtomicMemCap, NULL);
128         if (error != CL_SUCCESS)
129         {
130             print_error(error, "Unable to get atomic memory capabilities\n");
131             return TEST_FAIL;
132         }
133 
134         error =
135             clGetDeviceInfo(device, CL_DEVICE_ATOMIC_FENCE_CAPABILITIES,
136                             sizeof(gAtomicFenceCap), &gAtomicFenceCap, NULL);
137         if (error != CL_SUCCESS)
138         {
139             print_error(error, "Unable to get atomic fence capabilities\n");
140             return TEST_FAIL;
141         }
142 
143         if ((gAtomicFenceCap
144              & (CL_DEVICE_ATOMIC_ORDER_RELAXED | CL_DEVICE_ATOMIC_ORDER_ACQ_REL
145                 | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP))
146             == 0)
147         {
148             log_info(
149                 "Minimum atomic fence capabilities unsupported by device\n");
150             return TEST_FAIL;
151         }
152 
153         if ((gAtomicMemCap
154              & (CL_DEVICE_ATOMIC_ORDER_RELAXED
155                 | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP))
156             == 0)
157         {
158             log_info(
159                 "Minimum atomic memory capabilities unsupported by device\n");
160             return TEST_FAIL;
161         }
162 
163         // Disable program scope global variable testing in the case that it is
164         // not supported on an OpenCL-3.0 driver.
165         size_t max_global_variable_size{};
166         test_error_ret(clGetDeviceInfo(device,
167                                        CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE,
168                                        sizeof(max_global_variable_size),
169                                        &max_global_variable_size, nullptr),
170                        "Unable to get max global variable size\n", TEST_FAIL);
171         if (0 == max_global_variable_size)
172         {
173             gNoGlobalVariables = true;
174         }
175 
176         // Disable generic address space testing in the case that it is not
177         // supported on an OpenCL-3.0 driver.
178         cl_bool generic_address_space_support{};
179         test_error_ret(
180             clGetDeviceInfo(device, CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT,
181                             sizeof(generic_address_space_support),
182                             &generic_address_space_support, nullptr),
183             "Unable to get generic address space support\n", TEST_FAIL);
184         if (CL_FALSE == generic_address_space_support)
185         {
186             gNoGenericAddressSpace = true;
187         }
188     }
189     else
190     {
191         // OpenCL 2.x device, default to all capabilities
192         gAtomicMemCap = CL_DEVICE_ATOMIC_ORDER_RELAXED
193             | CL_DEVICE_ATOMIC_ORDER_ACQ_REL | CL_DEVICE_ATOMIC_ORDER_SEQ_CST
194             | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP | CL_DEVICE_ATOMIC_SCOPE_DEVICE
195             | CL_DEVICE_ATOMIC_SCOPE_ALL_DEVICES;
196 
197         gAtomicFenceCap = CL_DEVICE_ATOMIC_ORDER_RELAXED
198             | CL_DEVICE_ATOMIC_ORDER_ACQ_REL | CL_DEVICE_ATOMIC_ORDER_SEQ_CST
199             | CL_DEVICE_ATOMIC_SCOPE_WORK_ITEM
200             | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP | CL_DEVICE_ATOMIC_SCOPE_DEVICE
201             | CL_DEVICE_ATOMIC_SCOPE_ALL_DEVICES;
202     }
203 
204     return TEST_PASS;
205 }
206 
main(int argc,const char * argv[])207 int main(int argc, const char *argv[])
208 {
209   bool noCert = false;
210   while(true)
211   {
212     if(std::string(argv[argc-1]) == "-h")
213     {
214       log_info("Test options:\n");
215       log_info("  '-host'                    flag for testing native host threads (test verification)\n");
216       log_info("  '-oldAPI'                  flag for testing with old API (OpenCL 1.2) - test verification\n");
217       log_info("  '-continueOnError'         execute all cases even when errors detected\n");
218       log_info("  '-noGlobalVariables'       disable cases with global atomics in program scope\n");
219       log_info("  '-noGenericAddressSpace'   disable cases with generic address space\n");
220       log_info("  '-useHostPtr'              use malloc/free with CL_MEM_USE_HOST_PTR instead of clSVMAlloc/clSVMFree\n");
221       log_info("  '-debug'                   always print OpenCL kernel code\n");
222       log_info("  '-internalIterations <X>'  internal test iterations for atomic operation, sufficient to verify atomicity\n");
223       log_info("  '-maxDeviceThreads <X>'    maximum number of threads executed on OCL device");
224 
225       break;
226     }
227     if(std::string(argv[argc-1]) == "-host") // temporary option for testing native host threads
228     {
229       gHost = true;
230       noCert = true;
231     }
232     else if(std::string(argv[argc-1]) == "-oldAPI") // temporary flag for testing with old API (OpenCL 1.2)
233     {
234       gOldAPI = true;
235       gNoGlobalVariables = true;
236       gNoGenericAddressSpace = true;
237       gUseHostPtr = true;
238       noCert = true;
239     }
240     else if(std::string(argv[argc-1]) == "-continueOnError") // execute all cases even when errors detected
241       gContinueOnError = true;
242     else if(std::string(argv[argc-1]) == "-noGlobalVariables") // disable cases with global atomics in program scope
243     {
244       gNoGlobalVariables = true;
245       noCert = true;
246     }
247     else if(std::string(argv[argc-1]) == "-noGenericAddressSpace") // disable cases with generic address space
248     {
249       gNoGenericAddressSpace = true;
250       noCert = true;
251     }
252     else if(std::string(argv[argc-1]) == "-useHostPtr") // use malloc/free with CL_MEM_USE_HOST_PTR instead of clSVMAlloc/clSVMFree
253     {
254       gUseHostPtr = true;
255       noCert = true;
256     }
257     else if(std::string(argv[argc-1]) == "-debug") // print OpenCL kernel code
258       gDebug = true;
259     else if(argc > 2 && std::string(argv[argc-2]) == "-internalIterations") // internal test iterations for atomic operation, sufficient to verify atomicity
260     {
261       gInternalIterations = atoi(argv[argc-1]);
262       if(gInternalIterations < 1)
263       {
264         log_info("Invalid value: Number of internal iterations (%d) must be > 0\n", gInternalIterations);
265         return -1;
266       }
267       argc--;
268       noCert = true;
269     }
270     else if(argc > 2 && std::string(argv[argc-2]) == "-maxDeviceThreads") // maximum number of threads executed on OCL device
271     {
272       gMaxDeviceThreads = atoi(argv[argc-1]);
273       argc--;
274       noCert = true;
275     }
276     else
277       break;
278     argc--;
279   }
280   if(noCert)
281   {
282     log_info("\n" );
283     log_info("***                                                                        ***\n");
284     log_info("*** WARNING: Test execution in debug mode (forced by command-line option)! ***\n");
285     log_info("*** Use of this mode is not sufficient to verify correctness.              ***\n");
286     log_info("***                                                                        ***\n");
287   }
288   return runTestHarnessWithCheck(argc, argv, test_num, test_list, false, false, InitCL);
289 }
290