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 "testBase.h"
17 #include "harness/testHarness.h"
18
19 const char *context_test_kernels[] = {
20 "__kernel void sample_test_1(__global uint *src, __global uint *dst)\n"
21 "{\n"
22 " int tid = get_global_id(0);\n"
23 " dst[tid] = src[tid];\n"
24 "\n"
25 "}\n"
26
27 "__kernel void sample_test_2(__global uint *src, __global uint *dst)\n"
28 "{\n"
29 " int tid = get_global_id(0);\n"
30 " dst[tid] = src[tid] * 2;\n"
31 "\n"
32 "}\n"
33
34 "__kernel void sample_test_3(__global uint *src, __global uint *dst)\n"
35 "{\n"
36 " int tid = get_global_id(0);\n"
37 " dst[tid] = src[tid] / 2;\n"
38 "\n"
39 "}\n"
40
41 "__kernel void sample_test_4(__global uint *src, __global uint *dst)\n"
42 "{\n"
43 " int tid = get_global_id(0);\n"
44 " dst[tid] = src[tid] /3;\n"
45 "\n"
46 "}\n"
47 };
48
sampleAction1(cl_uint source)49 cl_uint sampleAction1(cl_uint source) { return source; }
sampleAction2(cl_uint source)50 cl_uint sampleAction2(cl_uint source) { return source * 2; }
sampleAction3(cl_uint source)51 cl_uint sampleAction3(cl_uint source) { return source / 2; }
sampleAction4(cl_uint source)52 cl_uint sampleAction4(cl_uint source) { return source / 3; }
53
54
55 typedef cl_uint (*sampleActionFn)(cl_uint source);
56
57 sampleActionFn sampleActions[4] = { sampleAction1, sampleAction2, sampleAction3, sampleAction4 };
58
59 #define BUFFER_COUNT 2
60 #define TEST_SIZE 512
61
62 typedef struct TestItem
63 {
64 struct TestItem *next;
65 cl_context c;
66 cl_command_queue q;
67 cl_program p;
68 cl_kernel k[4];
69 cl_mem m[BUFFER_COUNT];
70 MTdata d;
71 }TestItem;
72
73 static void DestroyTestItem( TestItem *item );
74
75 // Attempt to create a context and associated objects
CreateTestItem(cl_device_id deviceID,cl_int * err)76 TestItem *CreateTestItem( cl_device_id deviceID, cl_int *err )
77 {
78 cl_int error = 0;
79 size_t i;
80
81 // Allocate the TestItem struct
82 TestItem *item = (TestItem *) malloc( sizeof(TestItem ) );
83 if( NULL == item )
84 {
85 if( err )
86 {
87 log_error( "FAILURE: Failed to allocate TestItem -- out of host memory!\n" );
88 *err = CL_OUT_OF_HOST_MEMORY;
89 }
90 return NULL;
91 }
92 //zero so we know which fields we have initialized
93 memset( item, 0, sizeof( *item ) );
94
95 item->d = init_genrand( gRandomSeed );
96 if( NULL == item->d )
97 {
98 if( err )
99 {
100 log_error( "FAILURE: Failed to allocate mtdata om CreateTestItem -- out of host memory!\n" );
101 *err = CL_OUT_OF_HOST_MEMORY;
102 }
103 DestroyTestItem( item );
104 return NULL;
105 }
106
107
108 // Create a context
109 item->c = clCreateContext(NULL, 1, &deviceID, notify_callback, NULL, &error );
110 if( item->c == NULL || error != CL_SUCCESS)
111 {
112 if (err) {
113 log_error( "FAILURE: clCreateContext failed in CreateTestItem: %d\n", error);
114 *err = error;
115 }
116 DestroyTestItem( item );
117 return NULL;
118 }
119
120 // Create a queue
121 item->q = clCreateCommandQueue( item->c, deviceID, 0, &error);
122 if( item->q == NULL || error != CL_SUCCESS)
123 {
124 if (err) {
125 log_error( "FAILURE: clCreateCommandQueue failed in CreateTestItem: %d\n", error );
126 *err = error;
127 }
128 DestroyTestItem( item );
129 return NULL;
130 }
131
132 // Create a program
133 error = create_single_kernel_helper_create_program(item->c, &item->p, 1, context_test_kernels);
134 if( NULL == item->p || CL_SUCCESS != error )
135 {
136 if( err )
137 {
138 log_error( "FAILURE: clCreateProgram failed in CreateTestItem: %d\n", error );
139 *err = error;
140 }
141 DestroyTestItem( item );
142 return NULL;
143 }
144
145 error = clBuildProgram( item->p, 1, &deviceID, "", NULL, NULL );
146 if( error )
147 {
148 if( err )
149 {
150 log_error( "FAILURE: clBuildProgram failed in CreateTestItem: %d\n", error );
151 *err = error;
152 }
153 DestroyTestItem( item );
154 return NULL;
155 }
156
157 // create some kernels
158 for( i = 0; i < sizeof( item->k ) / sizeof( item->k[0] ); i++ )
159 {
160 static const char *kernelNames[] = { "sample_test_1", "sample_test_2", "sample_test_3", "sample_test_4" };
161 item->k[i] = clCreateKernel( item->p, kernelNames[i], &error );
162 if( NULL == item->k[i] || CL_SUCCESS != error )
163 {
164 if( err )
165 {
166 log_error( "FAILURE: clCreateKernel( \"%s\" ) failed in CreateTestItem: %d\n", kernelNames[i], error );
167 *err = error;
168 }
169 DestroyTestItem( item );
170 return NULL;
171 }
172 }
173
174 // create some mem objects
175 for( i = 0; i < BUFFER_COUNT; i++ )
176 {
177 item->m[i] = clCreateBuffer(item->c, CL_MEM_READ_WRITE,
178 TEST_SIZE * sizeof(cl_uint), NULL, &error);
179 if( NULL == item->m[i] || CL_SUCCESS != error )
180 {
181 if( err )
182 {
183 log_error("FAILURE: clCreateBuffer( %ld bytes ) failed in "
184 "CreateTestItem: %d\n",
185 TEST_SIZE * sizeof(cl_uint), error);
186 *err = error;
187 }
188 DestroyTestItem( item );
189 return NULL;
190 }
191 }
192
193
194 return item;
195 }
196
197 // Destroy a context and associate objects
DestroyTestItem(TestItem * item)198 static void DestroyTestItem( TestItem *item )
199 {
200 size_t i;
201
202 if( NULL == item )
203 return;
204
205 if( item->d )
206 free_mtdata( item->d );
207 if( item->c)
208 clReleaseContext( item->c );
209 if( item->q)
210 clReleaseCommandQueue( item->q );
211 if( item->p)
212 clReleaseProgram( item->p );
213 for( i = 0; i < sizeof( item->k ) / sizeof( item->k[0] ); i++ )
214 {
215 if( item->k[i])
216 clReleaseKernel( item->k[i] );
217 }
218 for( i = 0; i < BUFFER_COUNT; i++ )
219 {
220 if( item->m[i])
221 clReleaseMemObject( item->m[i] );
222 }
223 free(item );
224 }
225
226
UseTestItem(const TestItem * item,cl_int * err)227 cl_int UseTestItem( const TestItem *item, cl_int *err )
228 {
229 size_t i, j;
230 cl_int error = CL_SUCCESS;
231
232 // Fill buffer 0 with random numbers
233 cl_uint *mapped = (cl_uint *)clEnqueueMapBuffer(
234 item->q, item->m[0], CL_TRUE, CL_MAP_WRITE, 0,
235 TEST_SIZE * sizeof(cl_uint), 0, NULL, NULL, &error);
236 if( NULL == mapped || CL_SUCCESS != error )
237 {
238 if( err )
239 {
240 log_error( "FAILURE: Failed to map buffer 0 for writing: %d\n", error );
241 *err = error;
242 }
243 return error;
244 }
245
246 for( j = 0; j < TEST_SIZE; j++ )
247 mapped[j] = genrand_int32(item->d);
248
249 error = clEnqueueUnmapMemObject( item->q, item->m[0], mapped, 0, NULL, NULL );
250 if( CL_SUCCESS != error )
251 {
252 if( err )
253 {
254 log_error( "FAILURE: failure to unmap buffer 0 for writing: %d\n", error );
255 *err = error;
256 }
257 return error;
258 }
259
260 // try each kernel in turn.
261 for( j = 0; j < sizeof(item->k) / sizeof( item->k[0] ); j++ )
262 {
263 // Fill buffer 1 with 0xdeaddead
264 mapped = (cl_uint *)clEnqueueMapBuffer(
265 item->q, item->m[1], CL_TRUE, CL_MAP_WRITE, 0,
266 TEST_SIZE * sizeof(cl_uint), 0, NULL, NULL, &error);
267 if( NULL == mapped || CL_SUCCESS != error )
268 {
269 if( err )
270 {
271 log_error( "Failed to map buffer 1 for writing: %d\n", error );
272 *err = error;
273 }
274 return error;
275 }
276
277 for( i = 0; i < TEST_SIZE; i++ )
278 mapped[i] = 0xdeaddead;
279
280 error = clEnqueueUnmapMemObject( item->q, item->m[1], mapped, 0, NULL, NULL );
281 if( CL_SUCCESS != error )
282 {
283 if( err )
284 {
285 log_error( "Failed to unmap buffer 1 for writing: %d\n", error );
286 *err = error;
287 }
288 return error;
289 }
290
291 // Run the kernel
292 error = clSetKernelArg( item->k[j], 0, sizeof( cl_mem), &item->m[0] );
293 if( error )
294 {
295 if( err )
296 {
297 log_error( "FAILURE to set arg 0 for kernel # %ld : %d\n", j, error );
298 *err = error;
299 }
300 return error;
301 }
302
303 error = clSetKernelArg( item->k[j], 1, sizeof( cl_mem), &item->m[1] );
304 if( error )
305 {
306 if( err )
307 {
308 log_error( "FAILURE: Unable to set arg 1 for kernel # %ld : %d\n", j, error );
309 *err = error;
310 }
311 return error;
312 }
313
314 size_t work_size = TEST_SIZE;
315 size_t global_offset = 0;
316 error = clEnqueueNDRangeKernel( item->q, item->k[j], 1, &global_offset, &work_size, NULL, 0, NULL, NULL );
317 if( CL_SUCCESS != error )
318 {
319 if( err )
320 {
321 log_error( "FAILURE: Unable to enqueue kernel %ld: %d\n", j, error );
322 *err = error;
323 }
324 return error;
325 }
326
327 // Get the results back
328 mapped = (cl_uint *)clEnqueueMapBuffer(
329 item->q, item->m[1], CL_TRUE, CL_MAP_READ, 0,
330 TEST_SIZE * sizeof(cl_uint), 0, NULL, NULL, &error);
331 if( NULL == mapped || CL_SUCCESS != error )
332 {
333 if( err )
334 {
335 log_error( "Failed to map buffer 1 for reading: %d\n", error );
336 *err = error;
337 }
338 return error;
339 }
340
341 // Get our input data so we can check against it
342 cl_uint *inputData = (cl_uint *)clEnqueueMapBuffer(
343 item->q, item->m[0], CL_TRUE, CL_MAP_READ, 0,
344 TEST_SIZE * sizeof(cl_uint), 0, NULL, NULL, &error);
345 if( NULL == mapped || CL_SUCCESS != error )
346 {
347 if( err )
348 {
349 log_error( "Failed to map buffer 0 for reading: %d\n", error );
350 *err = error;
351 }
352 return error;
353 }
354
355
356 //Verify the results
357 for( i = 0; i < TEST_SIZE; i++ )
358 {
359 cl_uint expected = sampleActions[j](inputData[i]);
360 cl_uint result = mapped[i];
361 if( expected != result )
362 {
363 log_error( "FAILURE: Sample data at position %ld does not match expected result: *0x%8.8x vs. 0x%8.8x\n", i, expected, result );
364 if( err )
365 *err = -1;
366 return -1;
367 }
368 }
369
370 //Clean up
371 error = clEnqueueUnmapMemObject( item->q, item->m[0], inputData, 0, NULL, NULL );
372 if( CL_SUCCESS != error )
373 {
374 if( err )
375 {
376 log_error( "Failed to unmap buffer 0 for reading: %d\n", error );
377 *err = error;
378 }
379 return error;
380 }
381
382 error = clEnqueueUnmapMemObject( item->q, item->m[1], mapped, 0, NULL, NULL );
383 if( CL_SUCCESS != error )
384 {
385 if( err )
386 {
387 log_error( "Failed to unmap buffer 1 for reading: %d\n", error );
388 *err = error;
389 }
390 return error;
391 }
392
393 }
394
395 // Make sure that the last set of unmap calls get run
396 error = clFinish( item->q );
397 if( CL_SUCCESS != error )
398 {
399 if( err )
400 {
401 log_error( "Failed to clFinish: %d\n", error );
402 *err = error;
403 }
404 return error;
405 }
406
407 return CL_SUCCESS;
408 }
409
410
411
test_context_multiple_contexts_same_device(cl_device_id deviceID,size_t maxCount,size_t minCount)412 int test_context_multiple_contexts_same_device(cl_device_id deviceID, size_t maxCount, size_t minCount )
413 {
414 size_t i, j;
415 cl_int err = CL_SUCCESS;
416
417 //Figure out how many of these we can make before the first failure
418 TestItem *list = NULL;
419
420 for( i = 0; i < maxCount; i++ )
421 {
422 // create a context and accompanying objects
423 TestItem *current = CreateTestItem( deviceID, NULL /*no error reporting*/ );
424 if( NULL == current )
425 break;
426
427 // Attempt to use it
428 cl_int failed = UseTestItem( current, NULL );
429
430 if( failed )
431 {
432 DestroyTestItem( current );
433 break;
434 }
435
436 // Add the successful test item to the list
437 current->next = list;
438 list = current;
439 }
440
441 // Check to make sure we made the minimum amount
442 if( i < minCount )
443 {
444 log_error( "FAILURE: only could make %ld of %ld contexts!\n", i, minCount );
445 err = -1;
446 goto exit;
447 }
448
449 // Report how many contexts we made
450 if( i == maxCount )
451 log_info( "Successfully created all %lu contexts.\n", i );
452 else
453 log_info( "Successfully created %lu contexts out of %lu\n", i, maxCount );
454
455 // Set the count to be the number we succesfully made
456 maxCount = i;
457
458 // Make sure we can do it again a few times
459 log_info( "Tring to do it 5 more times" );
460 fflush( stdout);
461 for( j = 0; j < 5; j++ )
462 {
463 //free all the contexts we already made
464 while( list )
465 {
466 TestItem *current = list;
467 list = list->next;
468 current->next = NULL;
469 DestroyTestItem( current );
470 }
471
472 // Attempt to make them again
473 for( i = 0; i < maxCount; i++ )
474 {
475 // create a context and accompanying objects
476 TestItem *current = CreateTestItem( deviceID, &err );
477 if( err )
478 {
479 log_error( "\nTest Failed with error at CreateTestItem: %d\n", err );
480 goto exit;
481 }
482
483 // Attempt to use it
484 cl_int failed = UseTestItem( current, &err );
485
486 if( failed || err )
487 {
488 DestroyTestItem( current );
489 log_error( "\nTest Failed with error at UseTestItem: %d\n", err );
490 goto exit;
491 }
492
493 // Add the successful test item to the list
494 current->next = list;
495 list = current;
496 }
497 log_info( "." );
498 fflush( stdout );
499 }
500
501 log_info( "Done.\n" );
502
503 exit:
504 //free all the contexts we already made
505 while( list )
506 {
507 TestItem *current = list;
508 list = list->next;
509 current->next = NULL;
510
511 DestroyTestItem( current );
512 }
513
514 return err;
515 }
516
517 // This test tests to make sure that your implementation isn't super leaky. We make a bunch of contexts (up to some
518 // sane limit, currently 200), attempting to use each along the way. We keep track of how many we could make before
519 // a failure occurred. We then free everything and attempt to go do it again a few times. If you are able to make
520 // that many contexts 5 times over, then you pass.
test_context_multiple_contexts_same_device(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)521 int test_context_multiple_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
522 {
523 return test_context_multiple_contexts_same_device(deviceID, 200, 1);
524 }
525
test_context_two_contexts_same_device(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)526 int test_context_two_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
527 {
528 return test_context_multiple_contexts_same_device( deviceID, 2, 2 );
529 }
530
test_context_three_contexts_same_device(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)531 int test_context_three_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
532 {
533 return test_context_multiple_contexts_same_device( deviceID, 3, 3 );
534 }
535
test_context_four_contexts_same_device(cl_device_id deviceID,cl_context context,cl_command_queue queue,int num_elements)536 int test_context_four_contexts_same_device(cl_device_id deviceID, cl_context context, cl_command_queue queue, int num_elements)
537 {
538 return test_context_multiple_contexts_same_device( deviceID, 4, 4 );
539 }
540
541