• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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