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 <stdio.h>
17 #include <stdlib.h>
18
19 #if !defined(_WIN32)
20 #include <stdbool.h>
21 #endif
22
23 #include <math.h>
24 #include <string.h>
25
26 #if !defined (__APPLE__)
27 #include <CL/cl.h>
28 #endif
29
30 #include "procs.h"
31 #include "gles/setup.h"
32 #include "harness/testHarness.h"
33
34 #if !defined(_WIN32)
35 #include <unistd.h>
36 #endif
37
38 static cl_context sCurrentContext = NULL;
39
40
41 #define TEST_FN_REDIRECT( fn ) ADD_TEST( redirect_##fn )
42 #define TEST_FN_REDIRECTOR( fn ) \
43 int test_redirect_##fn(cl_device_id device, cl_context context, cl_command_queue queue, int numElements ) \
44 { \
45 int error; \
46 clCommandQueueWrapper realQueue = clCreateCommandQueue( sCurrentContext, device, 0, &error ); \
47 test_error( error, "Unable to create command queue" ); \
48 return test_##fn( device, sCurrentContext, realQueue, numElements ); \
49 }
50
51 TEST_FN_REDIRECTOR( buffers )
52 TEST_FN_REDIRECTOR( buffers_getinfo )
53 TEST_FN_REDIRECTOR( images_read )
54 TEST_FN_REDIRECTOR( images_2D_getinfo )
55 TEST_FN_REDIRECTOR( images_read_cube )
56 TEST_FN_REDIRECTOR( images_cube_getinfo )
57 TEST_FN_REDIRECTOR( images_read_3D )
58 TEST_FN_REDIRECTOR( images_3D_getinfo )
59 TEST_FN_REDIRECTOR( images_write )
60 TEST_FN_REDIRECTOR( images_write_cube )
61 TEST_FN_REDIRECTOR( renderbuffer_read )
62 TEST_FN_REDIRECTOR( renderbuffer_write )
63 TEST_FN_REDIRECTOR( renderbuffer_getinfo )
64
65 #ifdef GL_ES_VERSION_3_0
66 TEST_FN_REDIRECTOR(fence_sync)
67 #endif
68
69 test_definition test_list[] = {
70 TEST_FN_REDIRECT( buffers ),
71 TEST_FN_REDIRECT( buffers_getinfo ),
72 TEST_FN_REDIRECT( images_read ),
73 TEST_FN_REDIRECT( images_2D_getinfo ),
74 TEST_FN_REDIRECT( images_read_cube ),
75 TEST_FN_REDIRECT( images_cube_getinfo ),
76 TEST_FN_REDIRECT( images_read_3D ),
77 TEST_FN_REDIRECT( images_3D_getinfo ),
78 TEST_FN_REDIRECT( images_write ),
79 TEST_FN_REDIRECT( images_write_cube ),
80 TEST_FN_REDIRECT( renderbuffer_read ),
81 TEST_FN_REDIRECT( renderbuffer_write ),
82 TEST_FN_REDIRECT( renderbuffer_getinfo )
83 };
84
85 #ifdef GL_ES_VERSION_3_0
86 test_definition test_list32[] = {
87 TEST_FN_REDIRECT( fence_sync )
88 };
89 #endif
90
91 const int test_num = ARRAY_SIZE( test_list );
92
93 #ifdef GL_ES_VERSION_3_0
94 const int test_num32 = ARRAY_SIZE( test_list32 );
95 #endif
96
97
main(int argc,const char * argv[])98 int main(int argc, const char *argv[])
99 {
100 int error = 0;
101 cl_platform_id platform_id = NULL;
102 /* To keep it simple, use a static allocation of 32 argv pointers.
103 argc is not expected to go beyond 32 */
104 const char* argv_tmp[32] = {0};
105 int argc_tmp = 0;
106
107 test_start();
108
109 cl_device_type requestedDeviceType = CL_DEVICE_TYPE_DEFAULT;
110
111 for(int z = 1; z < argc; ++z)
112 {//for
113 if(strcmp( argv[ z ], "-list" ) == 0 )
114 {
115 log_info( "Available 2.x tests:\n" );
116 for( int i = 0; i < test_num; i++ )
117 log_info( "\t%s\n", test_list[i].name );
118
119 #ifdef GL_ES_VERSION_3_0
120 log_info( "Available 3.2 tests:\n" );
121 for( int i = 0; i < test_num32; i++ )
122 log_info( "\t%s\n", test_list32[i].name );
123 #endif
124
125 log_info("Note: Any 3.2 test names must follow 2.1 test names on the "
126 "command line.");
127 log_info("Use environment variables to specify desired device.");
128
129 return 0;
130 }
131
132 /* support requested device type */
133 if(!strcmp(argv[z], "CL_DEVICE_TYPE_GPU"))
134 {
135 printf("Requested device type is CL_DEVICE_TYPE_GPU\n");
136 requestedDeviceType = CL_DEVICE_TYPE_GPU;
137 }
138 else
139 if(!strcmp(argv[z], "CL_DEVICE_TYPE_CPU"))
140 {
141 printf("Requested device type is CL_DEVICE_TYPE_CPU\n");
142 log_info("Invalid CL device type. GL tests can only run on a GPU device.\n");
143 return 0;
144 }
145 }//for
146
147 // Check to see if any 2.x or 3.2 test names were specified on the command line.
148 unsigned first_32_testname = 0;
149
150 #ifdef GL_ES_VERSION_3_0
151 for (int j=1; (j<argc) && (!first_32_testname); ++j)
152 for (int i = 0; i < test_num32; ++i)
153 if (strcmp(test_list32[i].name, argv[j]) == 0 ) {
154 first_32_testname = j;
155 break;
156 }
157 #endif
158
159 // Create the environment for the test.
160 GLEnvironment *glEnv = GLEnvironment::Instance();
161
162 // Check if any devices of the requested type support CL/GL interop.
163 int supported = glEnv->SupportsCLGLInterop( requestedDeviceType );
164 if( supported == 0 ) {
165 log_info("Test not run because GL-CL interop is not supported for any devices of the requested type.\n");
166 error = 0;
167 goto cleanup;
168 } else if ( supported == -1 ) {
169 log_error("Failed to determine if CL-GL interop is supported.\n");
170 error = -1;
171 goto cleanup;
172 }
173
174 // OpenGL tests for non-3.2 ////////////////////////////////////////////////////////
175 if ((argc == 1) || (first_32_testname != 1)) {
176
177 // At least one device supports CL-GL interop, so init the test.
178 if( glEnv->Init( &argc, (char **)argv, CL_FALSE ) ) {
179 log_error("Failed to initialize the GL environment for this test.\n");
180 error = -1;
181 goto cleanup;
182 }
183
184 // Create a context to use and then grab a device (or devices) from it
185 sCurrentContext = glEnv->CreateCLContext();
186 if( sCurrentContext == NULL )
187 {
188 log_error( "ERROR: Unable to obtain CL context from GL\n" );
189 error = -1;
190 goto cleanup;
191 }
192
193 size_t numDevices = 0;
194 cl_device_id deviceIDs[ 16 ];
195
196 error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, 0, NULL, &numDevices);
197 if( error != CL_SUCCESS )
198 {
199 print_error( error, "Unable to get device count from context" );
200 error = -1;
201 goto cleanup;
202 }
203 numDevices /= sizeof(cl_device_id);
204
205 if (numDevices < 1) {
206 log_error("No devices found.\n");
207 error = -1;
208 goto cleanup;
209 }
210
211 error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, sizeof( deviceIDs ), deviceIDs, NULL);
212 if( error != CL_SUCCESS ) {
213 print_error( error, "Unable to get device list from context" );
214 error = -1;
215 goto cleanup;
216 }
217
218 // Execute tests.
219 int argc_ = (first_32_testname) ? first_32_testname : argc;
220
221 for( size_t i = 0; i < numDevices; i++ ) {
222 log_info( "\nTesting OpenGL 2.x\n" );
223 if( printDeviceHeader( deviceIDs[ i ] ) != CL_SUCCESS ) {
224 error = -1;
225 goto cleanup;
226 }
227
228 error = clGetDeviceInfo(deviceIDs[ i ],
229 CL_DEVICE_PLATFORM,
230 sizeof(platform_id),
231 &platform_id,
232 NULL);
233 if(error)
234 {
235 goto cleanup;
236 }
237
238 error = init_clgl_ext(platform_id);
239 if (error < 0)
240 {
241 goto cleanup;
242 }
243
244 /* parseAndCallCommandLineTests considers every command line argument
245 as a test name. This results in the test failing because of considering
246 args such as 'CL_DEVICE_TYPE_GPU' as test names unless
247 the actual test name happens to be the first argument.
248 Instead of changing the behaviour of parseAndCallCommandLineTests
249 modify the arguments passed to it so as to not affect other tests.
250 */
251 int w = 1;
252 argc_tmp= argc_;
253 for(int k = 1; k < argc; k++)
254 {
255 if( (strcmp(argv[k], "full") == 0) ||
256 (strcmp(argv[k], "CL_DEVICE_TYPE_CPU") == 0) ||
257 (strcmp(argv[k], "CL_DEVICE_TYPE_GPU") == 0))
258 {
259 argc_tmp--;
260 continue;
261 }
262 else
263 {
264 argv_tmp[w++] = argv[k];
265 }
266 }
267
268 // Note: don't use the entire harness, because we have a different way of obtaining the device (via the context)
269 test_harness_config config{};
270 config.forceNoContextCreation = true;
271 config.numElementsToUse = 1024;
272 config.queueProps = 0;
273 error = parseAndCallCommandLineTests(argc_tmp, argv_tmp, deviceIDs[i],
274 test_num, test_list, config);
275 if (error != 0) break;
276 }
277
278 // Clean-up.
279 // We move this to a common cleanup step to make sure that things will be released properly before the test exit
280 goto cleanup;
281 // clReleaseContext( sCurrentContext );
282 // delete glEnv;
283 }
284
285 // OpenGL 3.2 tests. ////////////////////////////////////////////////////////
286 if ((argc==1) || first_32_testname) {
287
288 // At least one device supports CL-GL interop, so init the test.
289 if( glEnv->Init( &argc, (char **)argv, CL_TRUE ) ) {
290 log_error("Failed to initialize the GL environment for this test.\n");
291 error = -1;
292 goto cleanup;
293 }
294
295 // Create a context to use and then grab a device (or devices) from it
296 sCurrentContext = glEnv->CreateCLContext();
297 if( sCurrentContext == NULL ) {
298 log_error( "ERROR: Unable to obtain CL context from GL\n" );
299 error = -1;
300 goto cleanup;
301 }
302
303 size_t numDevices = 0;
304 cl_device_id deviceIDs[ 16 ];
305
306 error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, 0, NULL, &numDevices);
307 if( error != CL_SUCCESS ) {
308 print_error( error, "Unable to get device count from context" );
309 error = -1;
310 goto cleanup;
311 }
312 numDevices /= sizeof(cl_device_id);
313
314 if (numDevices < 1) {
315 log_error("No devices found.\n");
316 error = -1;
317 goto cleanup;
318 }
319
320 error = clGetContextInfo( sCurrentContext, CL_CONTEXT_DEVICES, sizeof( deviceIDs ), deviceIDs, NULL);
321 if( error != CL_SUCCESS ) {
322 print_error( error, "Unable to get device list from context" );
323 error = -1;
324 goto cleanup;
325 }
326
327 #ifdef GLES3
328 int argc_ = (first_32_testname) ? 1 + (argc - first_32_testname) : argc;
329 const char** argv_ = (first_32_testname) ? &argv[first_32_testname-1] : argv;
330 #endif
331
332 // Execute the tests.
333 for( size_t i = 0; i < numDevices; i++ ) {
334 log_info( "\nTesting OpenGL 3.2\n" );
335 if( printDeviceHeader( deviceIDs[ i ] ) != CL_SUCCESS ) {
336 error = -1;
337 goto cleanup;
338 }
339 #ifndef GLES3
340 log_info("Cannot test OpenGL 3.2! This test was built for OpenGL ES 2.0\n");
341 error = -1;
342 goto cleanup;
343 #else
344 // Note: don't use the entire harness, because we have a different way of obtaining the device (via the context)
345 test_harness_config config{};
346 config.forceNoContextCreation = true;
347 config.numElementsToUse = 1024;
348 config.queueProps = 0;
349 error = parseAndCallCommandLineTests(argc_, argv_, deviceIDs[i],
350 test_num32, test_list32, config);
351 if( error != 0 )
352 break;
353 #endif
354 }
355
356 // Converge on a common cleanup to make sure that things will be released properly before the test exit
357 goto cleanup;
358 }
359
360
361 // cleanup CL/GL/EGL environment properly when the test exit.
362 // This change does not affect any functionality of the test
363
364 // Intentional falling through
365 cleanup:
366
367 // Always make sure that OpenCL context is released properly when the test exit
368 if(sCurrentContext)
369 {
370 clReleaseContext( sCurrentContext );
371 sCurrentContext = NULL;
372 }
373
374 // Cleanup EGL
375 glEnv->terminate_egl_display();
376
377 delete glEnv;
378
379 return error;
380 }
381