• 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/conversions.h"
18 #include "harness/typeWrappers.h"
19 
20 #define TEST_SIZE 512
21 
22 const char *equivTestKernelPattern_double =
23 "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
24 "__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global long%s *destValues, __global long%s *destValuesB)\n"
25 "{\n"
26 "    int  tid = get_global_id(0);\n"
27 "    destValues[tid] = %s( sourceA[tid], sourceB[tid] );\n"
28 "    destValuesB[tid] = sourceA[tid] %s sourceB[tid];\n"
29 "\n"
30 "}\n";
31 
32 const char *equivTestKernelPatternLessGreater_double =
33 "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
34 "__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global long%s *destValues, __global long%s *destValuesB)\n"
35 "{\n"
36 "    int  tid = get_global_id(0);\n"
37 "    destValues[tid] = %s( sourceA[tid], sourceB[tid] );\n"
38 "    destValuesB[tid] = (sourceA[tid] < sourceB[tid]) | (sourceA[tid] > sourceB[tid]);\n"
39 "\n"
40 "}\n";
41 
42 
43 const char *equivTestKernelPattern_double3 =
44 "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
45 "__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global long%s *destValues, __global long%s *destValuesB)\n"
46 "{\n"
47 "    int  tid = get_global_id(0);\n"
48 "    double3 sampA = vload3(tid, (__global double *)sourceA);\n"
49 "    double3 sampB = vload3(tid, (__global double *)sourceB);\n"
50 "    vstore3(%s( sampA, sampB ), tid, (__global long *)destValues);\n"
51 "    vstore3(( sampA %s sampB ), tid, (__global long *)destValuesB);\n"
52 "\n"
53 "}\n";
54 
55 const char *equivTestKernelPatternLessGreater_double3 =
56 "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n"
57 "__kernel void sample_test(__global double%s *sourceA, __global double%s *sourceB, __global long%s *destValues, __global long%s *destValuesB)\n"
58 "{\n"
59 "    int  tid = get_global_id(0);\n"
60 "    double3 sampA = vload3(tid, (__global double *)sourceA);\n"
61 "    double3 sampB = vload3(tid, (__global double *)sourceB);\n"
62 "    vstore3(%s( sampA, sampB ), tid, (__global long *)destValues);\n"
63 "    vstore3(( sampA < sampB ) | (sampA > sampB), tid, (__global long *)destValuesB);\n"
64 "\n"
65 "}\n";
66 
67 
68 typedef bool (*equivVerifyFn)( double inDataA, double inDataB );
69 
verify_equiv_values_double(unsigned int vecSize,double * inDataA,double * inDataB,cl_long * outData,equivVerifyFn verifyFn)70 void verify_equiv_values_double( unsigned int vecSize, double *inDataA, double *inDataB, cl_long *outData, equivVerifyFn verifyFn )
71 {
72     unsigned int i;
73     cl_long trueResult;
74     bool result;
75 
76     trueResult = ( vecSize == 1 ) ? 1 : -1;
77     for( i = 0; i < vecSize; i++ )
78     {
79         result = verifyFn( inDataA[ i ], inDataB[ i ] );
80         outData[ i ] = result ? trueResult : 0;
81     }
82 }
83 
generate_equiv_test_data_double(double * outData,unsigned int vecSize,bool alpha,MTdata d)84 void generate_equiv_test_data_double( double *outData, unsigned int vecSize, bool alpha, MTdata d )
85 {
86     unsigned int i;
87 
88     generate_random_data( kDouble, vecSize * TEST_SIZE, d, outData );
89 
90     // Fill the first few vectors with NAN in each vector element (or the second set if we're alpha, so we can test either case)
91     if( alpha )
92         outData += vecSize * vecSize;
93     for( i = 0; i < vecSize; i++ )
94     {
95         outData[ 0 ] = NAN;
96         outData += vecSize + 1;
97     }
98     // Make sure the third set is filled regardless, to test the case where both have NANs
99     if( !alpha )
100         outData += vecSize * vecSize;
101     for( i = 0; i < vecSize; i++ )
102     {
103         outData[ 0 ] = NAN;
104         outData += vecSize + 1;
105     }
106 }
107 
test_equiv_kernel_double(cl_context context,cl_command_queue queue,const char * fnName,const char * opName,unsigned int vecSize,equivVerifyFn verifyFn,MTdata d)108 int test_equiv_kernel_double(cl_context context, cl_command_queue queue, const char *fnName, const char *opName,
109                              unsigned int vecSize, equivVerifyFn verifyFn, MTdata d )
110 {
111     clProgramWrapper program;
112     clKernelWrapper kernel;
113     clMemWrapper streams[4];
114     double inDataA[TEST_SIZE * 16], inDataB[ TEST_SIZE * 16 ];
115     cl_long outData[TEST_SIZE * 16], expected[16];
116     int error, i, j;
117     size_t threads[1], localThreads[1];
118     char kernelSource[10240];
119     char *programPtr;
120     char sizeName[4];
121 
122 
123     /* Create the source */
124     if( vecSize == 1 )
125         sizeName[ 0 ] = 0;
126     else
127         sprintf( sizeName, "%d", vecSize );
128 
129     if(DENSE_PACK_VECS && vecSize == 3) {
130         if (strcmp(fnName, "islessgreater")) {
131             sprintf( kernelSource, equivTestKernelPattern_double3, sizeName, sizeName, sizeName, sizeName, fnName, opName );
132         } else {
133             sprintf( kernelSource, equivTestKernelPatternLessGreater_double3, sizeName, sizeName, sizeName, sizeName, fnName );
134         }
135     } else {
136         if (strcmp(fnName, "islessgreater")) {
137             sprintf( kernelSource, equivTestKernelPattern_double, sizeName, sizeName, sizeName, sizeName, fnName, opName );
138         } else {
139             sprintf( kernelSource, equivTestKernelPatternLessGreater_double, sizeName, sizeName, sizeName, sizeName, fnName );
140         }
141     }
142 
143     /* Create kernels */
144     programPtr = kernelSource;
145     if( create_single_kernel_helper( context, &program, &kernel, 1, (const char **)&programPtr, "sample_test" ) )
146     {
147         return -1;
148     }
149 
150     /* Generate some streams */
151     generate_equiv_test_data_double( inDataA, vecSize, true, d );
152     generate_equiv_test_data_double( inDataB, vecSize, false, d );
153 
154     streams[0] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR,
155                                 sizeof(cl_double) * vecSize * TEST_SIZE,
156                                 &inDataA, &error);
157     if( streams[0] == NULL )
158     {
159         print_error( error, "Creating input array A failed!\n");
160         return -1;
161     }
162     streams[1] = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR,
163                                 sizeof(cl_double) * vecSize * TEST_SIZE,
164                                 &inDataB, &error);
165     if( streams[1] == NULL )
166     {
167         print_error( error, "Creating input array A failed!\n");
168         return -1;
169     }
170     streams[2] = clCreateBuffer( context, CL_MEM_READ_WRITE, sizeof( cl_long ) * vecSize * TEST_SIZE, NULL, &error);
171     if( streams[2] == NULL )
172     {
173         print_error( error, "Creating output array failed!\n");
174         return -1;
175     }
176     streams[3] = clCreateBuffer( context, CL_MEM_READ_WRITE, sizeof( cl_long ) * vecSize * TEST_SIZE, NULL, &error);
177     if( streams[3] == NULL )
178     {
179         print_error( error, "Creating output array failed!\n");
180         return -1;
181     }
182 
183 
184     /* Assign streams and execute */
185     error = clSetKernelArg( kernel, 0, sizeof( streams[0] ), &streams[0] );
186     test_error( error, "Unable to set indexed kernel arguments" );
187     error = clSetKernelArg( kernel, 1, sizeof( streams[1] ), &streams[1] );
188     test_error( error, "Unable to set indexed kernel arguments" );
189     error = clSetKernelArg( kernel, 2, sizeof( streams[2] ), &streams[2] );
190     test_error( error, "Unable to set indexed kernel arguments" );
191     error = clSetKernelArg( kernel, 3, sizeof( streams[3] ), &streams[3] );
192     test_error( error, "Unable to set indexed kernel arguments" );
193 
194 
195     /* Run the kernel */
196     threads[0] = TEST_SIZE;
197 
198     error = get_max_common_work_group_size( context, kernel, threads[0], &localThreads[0] );
199     test_error( error, "Unable to get work group size to use" );
200 
201     error = clEnqueueNDRangeKernel( queue, kernel, 1, NULL, threads, localThreads, 0, NULL, NULL );
202     test_error( error, "Unable to execute test kernel" );
203 
204     /* Now get the results */
205     error = clEnqueueReadBuffer( queue, streams[2], true, 0, sizeof( cl_long ) * TEST_SIZE * vecSize, outData, 0, NULL, NULL );
206     test_error( error, "Unable to read output array!" );
207 
208     /* And verify! */
209     for( i = 0; i < TEST_SIZE; i++ )
210     {
211         verify_equiv_values_double( vecSize, &inDataA[ i * vecSize ], &inDataB[ i * vecSize ], expected, verifyFn);
212 
213         for( j = 0; j < (int)vecSize; j++ )
214         {
215             if( expected[ j ] != outData[ i * vecSize + j ] )
216             {
217                 log_error( "ERROR: Data sample %d:%d at size %d does not validate! Expected %lld, got %lld, source %f,%f\n",
218                           i, j, vecSize, expected[ j ], outData[ i * vecSize + j ], inDataA[i*vecSize + j], inDataB[i*vecSize + j] );
219                 return -1;
220             }
221         }
222     }
223 
224     /* Now get the results */
225     error = clEnqueueReadBuffer( queue, streams[3], true, 0, sizeof( cl_long ) * TEST_SIZE * vecSize, outData, 0, NULL, NULL );
226     test_error( error, "Unable to read output array!" );
227 
228     /* And verify! */
229     for( i = 0; i < TEST_SIZE; i++ )
230     {
231         verify_equiv_values_double( vecSize, &inDataA[ i * vecSize ], &inDataB[ i * vecSize ], expected, verifyFn);
232 
233         for( j = 0; j < (int)vecSize; j++ )
234         {
235             if( expected[ j ] != outData[ i * vecSize + j ] )
236             {
237                 log_error( "ERROR: Data sample %d:%d at size %d does not validate! Expected %lld, got %lld, source %f,%f\n",
238                           i, j, vecSize, expected[ j ], outData[ i * vecSize + j ], inDataA[i*vecSize + j], inDataB[i*vecSize + j] );
239                 return -1;
240             }
241         }
242     }
243 
244     return 0;
245 }
246 
test_equiv_kernel_set_double(cl_device_id device,cl_context context,cl_command_queue queue,const char * fnName,const char * opName,equivVerifyFn verifyFn,MTdata d)247 int test_equiv_kernel_set_double(cl_device_id device, cl_context context, cl_command_queue queue, const char *fnName, const char *opName, equivVerifyFn verifyFn, MTdata d )
248 {
249     unsigned int vecSizes[] = { 1, 2, 3, 4, 8, 16, 0 };
250     unsigned int index;
251     int retVal = 0;
252 
253     if (!is_extension_available(device, "cl_khr_fp64")) {
254         log_info("Extension cl_khr_fp64 not supported; skipping double tests.\n");
255         return 0;
256     }
257     log_info("Testing doubles.\n");
258 
259     for( index = 0; vecSizes[ index ] != 0; index++ )
260     {
261         // Test!
262         if( test_equiv_kernel_double(context, queue, fnName, opName, vecSizes[ index ], verifyFn, d ) != 0 )
263         {
264             log_error( "   Vector double%d FAILED\n", vecSizes[ index ] );
265             retVal = -1;
266         }
267     }
268 
269     return retVal;
270 }
271 
isequal_verify_fn_double(double valueA,double valueB)272 bool isequal_verify_fn_double( double valueA, double valueB )
273 {
274     if( isnan( valueA ) || isnan( valueB ) )
275         return false;
276     return valueA == valueB;
277 }
278 
test_relational_isequal_double(cl_device_id device,cl_context context,cl_command_queue queue,int numElements)279 int test_relational_isequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
280 {
281     RandomSeed seed(gRandomSeed);
282     return test_equiv_kernel_set_double( device, context, queue, "isequal", "==", isequal_verify_fn_double, seed );
283 }
284 
isnotequal_verify_fn_double(double valueA,double valueB)285 bool isnotequal_verify_fn_double( double valueA, double valueB )
286 {
287     if( isnan( valueA ) || isnan( valueB ) )
288         return true;
289     return valueA != valueB;
290 }
291 
test_relational_isnotequal_double(cl_device_id device,cl_context context,cl_command_queue queue,int numElements)292 int test_relational_isnotequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
293 {
294     RandomSeed seed(gRandomSeed);
295     return test_equiv_kernel_set_double( device, context, queue, "isnotequal", "!=", isnotequal_verify_fn_double, seed );
296 }
297 
isgreater_verify_fn_double(double valueA,double valueB)298 bool isgreater_verify_fn_double( double valueA, double valueB )
299 {
300     if( isnan( valueA ) || isnan( valueB ) )
301         return false;
302     return valueA > valueB;
303 }
304 
test_relational_isgreater_double(cl_device_id device,cl_context context,cl_command_queue queue,int numElements)305 int test_relational_isgreater_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
306 {
307     RandomSeed seed(gRandomSeed);
308     return test_equiv_kernel_set_double( device, context, queue, "isgreater", ">", isgreater_verify_fn_double, seed );
309 }
310 
isgreaterequal_verify_fn_double(double valueA,double valueB)311 bool isgreaterequal_verify_fn_double( double valueA, double valueB )
312 {
313     if( isnan( valueA ) || isnan( valueB ) )
314         return false;
315     return valueA >= valueB;
316 }
317 
test_relational_isgreaterequal_double(cl_device_id device,cl_context context,cl_command_queue queue,int numElements)318 int test_relational_isgreaterequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
319 {
320     RandomSeed seed(gRandomSeed);
321     return test_equiv_kernel_set_double( device, context, queue, "isgreaterequal", ">=", isgreaterequal_verify_fn_double, seed );
322 }
323 
isless_verify_fn_double(double valueA,double valueB)324 bool isless_verify_fn_double( double valueA, double valueB )
325 {
326     if( isnan( valueA ) || isnan( valueB ) )
327         return false;
328     return valueA < valueB;
329 }
330 
test_relational_isless_double(cl_device_id device,cl_context context,cl_command_queue queue,int numElements)331 int test_relational_isless_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
332 {
333     RandomSeed seed(gRandomSeed);
334     return test_equiv_kernel_set_double( device, context, queue, "isless", "<", isless_verify_fn_double, seed );
335 }
336 
islessequal_verify_fn_double(double valueA,double valueB)337 bool islessequal_verify_fn_double( double valueA, double valueB )
338 {
339     if( isnan( valueA ) || isnan( valueB ) )
340         return false;
341     return valueA <= valueB;
342 }
343 
test_relational_islessequal_double(cl_device_id device,cl_context context,cl_command_queue queue,int numElements)344 int test_relational_islessequal_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
345 {
346     RandomSeed seed(gRandomSeed);
347     return test_equiv_kernel_set_double( device, context, queue, "islessequal", "<=", islessequal_verify_fn_double, seed );
348 }
349 
islessgreater_verify_fn_double(double valueA,double valueB)350 bool islessgreater_verify_fn_double( double valueA, double valueB )
351 {
352     if( isnan( valueA ) || isnan( valueB ) )
353         return false;
354     return ( valueA < valueB ) || ( valueA > valueB );
355 }
356 
test_relational_islessgreater_double(cl_device_id device,cl_context context,cl_command_queue queue,int numElements)357 int test_relational_islessgreater_double(cl_device_id device, cl_context context, cl_command_queue queue, int numElements )
358 {
359     RandomSeed seed(gRandomSeed);
360     return test_equiv_kernel_set_double( device, context, queue, "islessgreater", "<>", islessgreater_verify_fn_double, seed );
361 }
362 
363 
364