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/compat.h"
17
18 #ifdef __APPLE__
19 #include <OpenCL/opencl.h>
20 #else
21 #include <CL/cl.h>
22 #endif
23
24 #include <assert.h>
25 #include <string>
26 #include <fstream>
27 #include <iterator>
28 #include <memory>
29 #include <sstream>
30 #include <vector>
31
32 #include "exceptions.h"
33 #include "datagen.h"
34 #include "run_services.h"
35
36 #define XSTR(A) STR(A)
37 #define STR(A) #A
38
39 /**
40 Based on the folder and the input string build the cl file nanme
41 */
get_cl_file_path(const char * folder,const char * test_name,std::string & cl_file_path)42 void get_cl_file_path (const char *folder, const char *test_name, std::string &cl_file_path)
43 {
44 assert(folder && "folder is empty");
45 assert(test_name && "test_name is empty");
46
47 cl_file_path.append(folder);
48 cl_file_path.append("/");
49 cl_file_path.append(test_name);
50 cl_file_path.append(".cl");
51 }
52
53 /**
54 Based on the folder and the input string build the bc file nanme
55 */
get_bc_file_path(const char * folder,const char * test_name,std::string & bc_file_path,cl_uint size_t_width)56 void get_bc_file_path (const char *folder, const char *test_name, std::string &bc_file_path, cl_uint size_t_width)
57 {
58 assert(folder && "folder is empty");
59 assert(test_name && "test_name is empty");
60 bc_file_path.append(folder);
61 bc_file_path.append("/");
62 bc_file_path.append(test_name);
63 if (32 == size_t_width)
64 bc_file_path.append(".bc32");
65 else
66 bc_file_path.append(".bc64");
67 }
68
69 /**
70 Based on the folder and the input string build the h file nanme
71 */
get_h_file_path(const char * folder,const char * file_name,std::string & h_file_path)72 void get_h_file_path (const char *folder, const char *file_name, std::string &h_file_path)
73 {
74 assert(folder && "folder is empty");
75 assert(file_name && "file_name is empty");
76
77 h_file_path.assign(folder);
78 h_file_path.append("/");
79 h_file_path.append(file_name);
80 }
81
82 /**
83 Fetch the kernel nanme from the test name
84 */
get_kernel_name(const char * test_name,std::string & kernel_name)85 void get_kernel_name (const char *test_name, std::string &kernel_name)
86 {
87 char *temp_str, *p;
88 std::string temp;
89
90 temp.assign(test_name);
91
92 // Check if the test name includes '.' -
93 // the convention is that the test's kernel name is embedded in the test name up to the first '.'
94 temp_str = (char *)temp.c_str();
95 p = strstr(temp_str, ".");
96 if (p != NULL)
97 {
98 *p = '\0';
99 }
100 kernel_name.assign(temp_str);
101 }
102
103 void CL_CALLBACK notify_callback(const char* errInfo, const void* privateInfo,
104 size_t cb, void* userData);
105
create_context_and_queue(cl_device_id device,cl_context * out_context,cl_command_queue * out_queue)106 void create_context_and_queue(cl_device_id device, cl_context *out_context, cl_command_queue *out_queue)
107 {
108 assert( out_context && "out_context arg must be a valid pointer");
109 assert( out_queue && "out_queue arg must be a valid pointer");
110
111 int error = CL_SUCCESS;
112
113 *out_context = clCreateContext( NULL, 1, &device, notify_callback, NULL, &error );
114 if( NULL == *out_context || error != CL_SUCCESS)
115 {
116 throw Exceptions::TestError("clCreateContext failed\n", error);
117 }
118
119 *out_queue = clCreateCommandQueue( *out_context, device, 0, &error );
120 if( NULL == *out_queue || error )
121 {
122 throw Exceptions::TestError("clCreateCommandQueue failed\n", error);
123 }
124 }
125
126 /**
127 Loads the kernel text from the given text file
128 */
load_file_cl(const std::string & file_name)129 std::string load_file_cl( const std::string& file_name)
130 {
131 std::ifstream ifs(file_name.c_str());
132 if( !ifs.good() )
133 throw Exceptions::TestError("Can't load the cl File " + file_name, 1);
134 std::string str( ( std::istreambuf_iterator<char>( ifs ) ), std::istreambuf_iterator<char>());
135 return str;
136 }
137
138 /**
139 Loads the kernel IR from the given binary file in SPIR BC format
140 */
load_file_bc(const std::string & file_name,size_t * binary_size)141 void* load_file_bc( const std::string& file_name, size_t *binary_size)
142 {
143 assert(binary_size && "binary_size arg should be valid");
144
145 std::ifstream file(file_name.c_str(), std::ios::binary);
146
147 if( !file.good() )
148 {
149 throw Exceptions::TestError("Can't load the bc File " + file_name, 1);
150 }
151
152 file.seekg(0, std::ios::end);
153 *binary_size = (size_t)file.tellg();
154 file.seekg(0, std::ios::beg);
155
156 void* buffer = malloc(*binary_size);
157 file.read((char*)buffer, *binary_size);
158 file.close();
159
160 return buffer;
161 }
162
163 /**
164 Create program from the CL source file
165 */
create_program_from_cl(cl_context context,const std::string & file_name)166 cl_program create_program_from_cl(cl_context context, const std::string& file_name)
167 {
168 std::string text_file = load_file_cl(file_name);
169 const char* text_str = text_file.c_str();
170 int error = CL_SUCCESS;
171
172 cl_program program = clCreateProgramWithSource( context, 1, &text_str, NULL, &error );
173 if( program == NULL || error != CL_SUCCESS)
174 {
175 throw Exceptions::TestError("Error creating program\n", error);
176 }
177
178 return program;
179 }
180
181 /**
182 Create program from the BC source file
183 */
create_program_from_bc(cl_context context,const std::string & file_name)184 cl_program create_program_from_bc (cl_context context, const std::string& file_name)
185 {
186 cl_int load_error = CL_SUCCESS;
187 cl_int error;
188 size_t binary_size;
189 BufferOwningPtr<const unsigned char> binary(load_file_bc(file_name, &binary_size));
190 const unsigned char* ptr = binary;
191
192 cl_device_id device = get_context_device(context);
193 cl_program program = clCreateProgramWithBinary( context, 1, &device, &binary_size, &ptr, &load_error, &error );
194
195
196 if( program == NULL || error != CL_SUCCESS )
197 {
198 throw Exceptions::TestError("clCreateProgramWithBinary failed: Unable to load valid program binary\n", error);
199 }
200
201 if( load_error != CL_SUCCESS )
202 {
203 throw Exceptions::TestError("clCreateProgramWithBinary failed: Unable to load valid device binary into program\n", load_error);
204 }
205
206 return program;
207 }
208
209 /**
210 Creates the kernel with the given name from the given program.
211 */
create_kernel_helper(cl_program program,const std::string & kernel_name)212 cl_kernel create_kernel_helper( cl_program program, const std::string& kernel_name )
213 {
214 int error = CL_SUCCESS;
215 cl_kernel kernel = NULL;
216 cl_device_id device = get_program_device(program);
217 /* And create a kernel from it */
218 kernel = clCreateKernel( program, kernel_name.c_str(), &error );
219 if( kernel == NULL || error != CL_SUCCESS)
220 throw Exceptions::TestError("Unable to create kernel\n", error);
221 return kernel;
222 }
223
get_context_device(cl_context context)224 cl_device_id get_context_device (cl_context context)
225 {
226 cl_device_id device[1];
227
228 int error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(device), device, NULL);
229 if( error != CL_SUCCESS )
230 {
231 throw Exceptions::TestError("clGetContextInfo failed\n", error);
232 }
233
234 return device[0];
235 }
236
get_program_device(cl_program program)237 cl_device_id get_program_device (cl_program program)
238 {
239 cl_device_id device[1];
240
241 int error = clGetProgramInfo(program, CL_PROGRAM_DEVICES, sizeof(device), device, NULL);
242 if( error != CL_SUCCESS )
243 {
244 throw Exceptions::TestError("clGetProgramInfo failed\n", error);
245 }
246
247 return device[0];
248 }
249
generate_kernel_ws(cl_device_id device,cl_kernel kernel,WorkSizeInfo & ws)250 void generate_kernel_ws( cl_device_id device, cl_kernel kernel, WorkSizeInfo& ws)
251 {
252 size_t compile_work_group_size[MAX_WORK_DIM];
253
254 memset(&ws, 0, sizeof(WorkSizeInfo));
255 ws.work_dim = 1;
256 ws.global_work_size[0] = (GLOBAL_WORK_SIZE <= 32) ? GLOBAL_WORK_SIZE : 32; // kernels limitations
257 ws.local_work_size[0] = ((GLOBAL_WORK_SIZE % 4) == 0) ? (GLOBAL_WORK_SIZE / 4) : (GLOBAL_WORK_SIZE / 2);
258
259 //Check if the kernel was compiled with specific work group size
260 int error = clGetKernelWorkGroupInfo(kernel, device, CL_KERNEL_COMPILE_WORK_GROUP_SIZE, sizeof(compile_work_group_size), &compile_work_group_size, NULL);
261 if( error != CL_SUCCESS )
262 {
263 throw Exceptions::TestError("clGetKernelWorkGroupInfo failed\n", error);
264 }
265
266 // if compile_work_group_size[0] is not 0 - use the compiled values
267 if ( 0 != compile_work_group_size[0] )
268 {
269 // the kernel compiled with __attribute__((reqd_work_group_size(X, Y, Z)))
270 memcpy(ws.global_work_size, compile_work_group_size, sizeof(ws.global_work_size));
271
272 // Now, check the correctness of the local work size and fix it if necessary
273 for ( int i = 0; i < MAX_WORK_DIM; ++i )
274 {
275 if ( ws.local_work_size[i] > compile_work_group_size[i] )
276 {
277 ws.local_work_size[i] = compile_work_group_size[i];
278 }
279 }
280 }
281 }
282
clone(cl_context ctx,const WorkSizeInfo & ws,const cl_kernel kernel,const cl_device_id device) const283 TestResult* TestResult::clone(cl_context ctx, const WorkSizeInfo& ws, const cl_kernel kernel, const cl_device_id device) const
284 {
285 TestResult *cpy = new TestResult();
286
287 for (size_t i=0; i<m_kernelArgs.getArgCount(); ++i)
288 cpy->m_kernelArgs.addArg(m_kernelArgs.getArg(i)->clone(ctx, ws, kernel, device));
289
290 return cpy;
291 }
292
293 /*
294 * class DataRow
295 */
296
operator [](int column) const297 const std::string& DataRow::operator[](int column)const
298 {
299 assert((column > -1 && (size_t)column < m_row.size()) && "Index out of bound");
300 return m_row[column];
301 }
302
operator [](int column)303 std::string& DataRow::operator[](int column)
304 {
305 assert((column > -1 && (size_t)column <= m_row.size())
306 && "Index out of bound");
307 if ((size_t)column == m_row.size()) m_row.push_back("");
308
309 return m_row[column];
310 }
311
312 /*
313 * class DataTable
314 */
315
getNumRows() const316 size_t DataTable::getNumRows() const
317 {
318 return m_rows.size();
319 }
320
addTableRow(DataRow * dr)321 void DataTable::addTableRow(DataRow *dr)
322 {
323 m_rows.push_back(dr);
324 }
325
operator [](int index) const326 const DataRow& DataTable::operator[](int index)const
327 {
328 assert((index > -1 && (size_t)index < m_rows.size()) && "Index out of bound");
329 return *m_rows[index];
330 }
331
operator [](int index)332 DataRow& DataTable::operator[](int index)
333 {
334 assert((index > -1 && (size_t)index < m_rows.size()) && "Index out of bound");
335 return *m_rows[index];
336 }
337
338 /*
339 * class OclExtensions
340 */
getDeviceCapabilities(cl_device_id devId)341 OclExtensions OclExtensions::getDeviceCapabilities(cl_device_id devId)
342 {
343 size_t size;
344 size_t set_size;
345 cl_int errcode = clGetDeviceInfo(devId, CL_DEVICE_EXTENSIONS, 0, NULL, &set_size);
346 if (errcode)
347 throw Exceptions::TestError("Device query failed");
348 // Querying the device for its supported extensions
349 std::vector<char> extensions(set_size);
350 errcode = clGetDeviceInfo(devId,
351 CL_DEVICE_EXTENSIONS,
352 extensions.size(),
353 extensions.data(),
354 &size);
355
356 if (errcode)
357 throw Exceptions::TestError("Device query failed");
358
359 char device_profile[1024] = {0};
360 errcode = clGetDeviceInfo(devId,
361 CL_DEVICE_PROFILE,
362 sizeof(device_profile),
363 device_profile,
364 NULL);
365 if (errcode)
366 throw Exceptions::TestError("Device query failed");
367
368 OclExtensions ret = OclExtensions::empty();
369 assert(size == set_size);
370 if (!size)
371 return ret;
372
373 // Iterate over the extensions, and convert them into the bit field.
374 std::list<std::string> extVector;
375 std::stringstream khrStream(extensions.data());
376 std::copy(std::istream_iterator<std::string>(khrStream),
377 std::istream_iterator<std::string>(),
378 std::back_inserter(extVector));
379
380 // full_profile devices supports embedded profile as core feature
381 if ( std::string( device_profile ) == "FULL_PROFILE" ) {
382 extVector.push_back("cles_khr_int64");
383 extVector.push_back("cles_khr_2d_image_array_writes");
384 }
385
386 for(std::list<std::string>::const_iterator it = extVector.begin(),
387 e = extVector.end(); it != e;
388 it++)
389 {
390 ret = ret | OclExtensions::fromString(*it);
391 }
392 return ret;
393 }
394
empty()395 OclExtensions OclExtensions::empty()
396 {
397 return OclExtensions(0);
398 }
399
fromString(const std::string & e)400 OclExtensions OclExtensions::fromString(const std::string& e)
401 {
402 std::string s = "OclExtensions::" + e;
403 RETURN_IF_ENUM(s, OclExtensions::cl_khr_int64_base_atomics);
404 RETURN_IF_ENUM(s, OclExtensions::cl_khr_int64_extended_atomics);
405 RETURN_IF_ENUM(s, OclExtensions::cl_khr_3d_image_writes);
406 RETURN_IF_ENUM(s, OclExtensions::cl_khr_fp16);
407 RETURN_IF_ENUM(s, OclExtensions::cl_khr_gl_sharing);
408 RETURN_IF_ENUM(s, OclExtensions::cl_khr_gl_event);
409 RETURN_IF_ENUM(s, OclExtensions::cl_khr_d3d10_sharing);
410 RETURN_IF_ENUM(s, OclExtensions::cl_khr_dx9_media_sharing);
411 RETURN_IF_ENUM(s, OclExtensions::cl_khr_d3d11_sharing);
412 RETURN_IF_ENUM(s, OclExtensions::cl_khr_depth_images);
413 RETURN_IF_ENUM(s, OclExtensions::cl_khr_gl_depth_images);
414 RETURN_IF_ENUM(s, OclExtensions::cl_khr_gl_msaa_sharing);
415 RETURN_IF_ENUM(s, OclExtensions::cl_khr_image2d_from_buffer);
416 RETURN_IF_ENUM(s, OclExtensions::cl_khr_initialize_memory);
417 RETURN_IF_ENUM(s, OclExtensions::cl_khr_spir);
418 RETURN_IF_ENUM(s, OclExtensions::cl_khr_fp64);
419 RETURN_IF_ENUM(s, OclExtensions::cl_khr_global_int32_base_atomics);
420 RETURN_IF_ENUM(s, OclExtensions::cl_khr_global_int32_extended_atomics);
421 RETURN_IF_ENUM(s, OclExtensions::cl_khr_local_int32_base_atomics);
422 RETURN_IF_ENUM(s, OclExtensions::cl_khr_local_int32_extended_atomics);
423 RETURN_IF_ENUM(s, OclExtensions::cl_khr_byte_addressable_store);
424 RETURN_IF_ENUM(s, OclExtensions::cles_khr_int64);
425 RETURN_IF_ENUM(s, OclExtensions::cles_khr_2d_image_array_writes);
426 // Unknown KHR string.
427 return OclExtensions::empty();
428 }
429
toString()430 std::string OclExtensions::toString()
431 {
432
433 #define APPEND_STR_IF_SUPPORTS( STR, E) \
434 if ( this->supports(E) ) \
435 { \
436 std::string ext_str( #E ); \
437 std::string prefix = "OclExtensions::"; \
438 size_t pos = ext_str.find( prefix ); \
439 if ( pos != std::string::npos ) \
440 { \
441 ext_str.replace( pos, prefix.length(), ""); \
442 } \
443 STR += ext_str; \
444 }
445
446 std::string s = "";
447
448 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_int64_base_atomics );
449 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_int64_extended_atomics );
450 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_3d_image_writes );
451 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_fp16 );
452 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_gl_sharing );
453 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_gl_event );
454 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_d3d10_sharing );
455 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_dx9_media_sharing );
456 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_d3d11_sharing );
457 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_depth_images );
458 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_gl_depth_images );
459 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_gl_msaa_sharing );
460 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_image2d_from_buffer );
461 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_initialize_memory );
462 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_spir );
463 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_fp64 );
464 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_global_int32_base_atomics );
465 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_global_int32_extended_atomics );
466 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_local_int32_base_atomics );
467 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_local_int32_extended_atomics );
468 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cl_khr_byte_addressable_store );
469 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cles_khr_int64 );
470 APPEND_STR_IF_SUPPORTS( s, OclExtensions::cles_khr_2d_image_array_writes );
471
472 return s;
473 }
474
operator <<(std::ostream & os,OclExtensions ext)475 std::ostream& operator<<(std::ostream& os, OclExtensions ext)
476 {
477 return os << ext.toString();
478 }
479
operator |(const OclExtensions & b) const480 OclExtensions OclExtensions::operator|(const OclExtensions& b) const
481 {
482 return OclExtensions(m_extVector | b.m_extVector);
483 }
484
supports(const OclExtensions & b) const485 bool OclExtensions::supports(const OclExtensions& b) const
486 {
487 return ((b.m_extVector & m_extVector) == b.m_extVector);
488 }
489
get_missing(const OclExtensions & b) const490 OclExtensions OclExtensions::get_missing(const OclExtensions& b) const
491 {
492 return OclExtensions( b.m_extVector & ( ~ m_extVector ) );
493 }
494
495 /*
496 * class KhrSupport
497 */
498
499 KhrSupport *KhrSupport::m_instance = NULL;
500
get(const std::string & path)501 const KhrSupport* KhrSupport::get(const std::string& path)
502 {
503 if(m_instance)
504 return m_instance;
505
506 m_instance = new KhrSupport();
507 // First invokation, parse the file into memory.
508 std::fstream csv(path.c_str(), std::ios_base::in);
509 if (!csv.is_open())
510 {
511 delete m_instance;
512 std::string msg;
513 msg.append("File ");
514 msg.append(path);
515 msg.append(" cannot be opened");
516 throw Exceptions::TestError(msg.c_str());
517 }
518
519 m_instance->parseCSV(csv);
520 csv.close();
521 return m_instance;
522 }
523
parseCSV(std::fstream & f)524 void KhrSupport::parseCSV(std::fstream& f)
525 {
526 assert(f.is_open() && "file is not in reading state.") ;
527 char line[1024];
528 while (!f.getline(line, sizeof(line)).eof())
529 {
530 DataRow *dr = parseLine(std::string(line));
531 m_dt.addTableRow(dr);
532 }
533 }
534
parseLine(const std::string & line)535 DataRow* KhrSupport::parseLine(const std::string& line)
536 {
537 const char DELIM = ',';
538 std::string token;
539 DataRow *dr = new DataRow();
540 int tIndex = 0;
541
542 for(std::string::const_iterator it = line.begin(), e = line.end(); it != e;
543 it++)
544 {
545 // Eat those characters away.
546 if(isspace(*it) || '"' == *it)
547 continue;
548
549 // If that's a delimiter, we need to tokenize the collected value.
550 if(*it == DELIM)
551 {
552 (*dr)[tIndex++] = token;
553 token.clear();
554 continue;
555 }
556
557 // Append to current token.
558 token.append(1U, *it);
559 }
560 if (!token.empty())
561 (*dr)[tIndex] = token;
562
563 assert(tIndex && "empty data row??");
564 return dr;
565 }
566
getRequiredExtensions(const char * suite,const char * test) const567 OclExtensions KhrSupport::getRequiredExtensions(const char* suite, const char* test) const
568 {
569 OclExtensions ret = OclExtensions::empty();
570
571 const std::string strSuite(suite), strTest(test);
572 // Iterating on the DataTable, searching whether the row with th requested
573 // row exists.
574 for(size_t rowIndex = 0; rowIndex < m_dt.getNumRows(); rowIndex++)
575 {
576 const DataRow& dr = m_dt[rowIndex];
577 const std::string csvSuite = dr[SUITE_INDEX], csvTest = dr[TEST_INDEX];
578 bool sameSuite = (csvSuite == strSuite), sameTest = (csvTest == strTest)||(csvTest == "*");
579 if (sameTest && sameSuite)
580 {
581 ret = ret | OclExtensions::fromString(dr[EXT_INDEX]);
582 }
583 }
584
585 return ret;
586 }
587
isImagesRequired(const char * suite,const char * test) const588 cl_bool KhrSupport::isImagesRequired(const char* suite, const char* test) const
589 {
590 cl_bool ret = CL_FALSE;
591 const std::string strSuite(suite), strTest(test);
592
593 // Iterating on the DataTable, searching whether the row with th requested
594 // row exists.
595 for(size_t rowIndex = 0; rowIndex < m_dt.getNumRows(); rowIndex++)
596 {
597 const DataRow& dr = m_dt[rowIndex];
598 const std::string csvSuite = dr[SUITE_INDEX], csvTest = dr[TEST_INDEX];
599 bool sameSuite = (csvSuite == strSuite), sameTest = (csvTest == strTest)||(csvTest == "*");
600 if (sameTest && sameSuite)
601 {
602 ret = (dr[IMAGES_INDEX] == "CL_TRUE") ? CL_TRUE : CL_FALSE;
603 break;
604 }
605 }
606
607 return ret;
608 }
609
isImages3DRequired(const char * suite,const char * test) const610 cl_bool KhrSupport::isImages3DRequired(const char* suite, const char* test) const
611 {
612 cl_bool ret = CL_FALSE;
613 const std::string strSuite(suite), strTest(test);
614
615 // Iterating on the DataTable, searching whether the row with th requested
616 // row exists.
617 for(size_t rowIndex = 0; rowIndex < m_dt.getNumRows(); rowIndex++)
618 {
619 const DataRow& dr = m_dt[rowIndex];
620 const std::string csvSuite = dr[SUITE_INDEX], csvTest = dr[TEST_INDEX];
621 bool sameSuite = (csvSuite == strSuite), sameTest = (csvTest == strTest)||(csvTest == "*");
622 if (sameTest && sameSuite)
623 {
624 ret = (dr[IMAGES_3D_INDEX] == "CL_TRUE") ? CL_TRUE : CL_FALSE;
625 break;
626 }
627 }
628
629 return ret;
630 }
631
632
generate_kernel_args(cl_context context,cl_kernel kernel,const WorkSizeInfo & ws,KernelArgs & cl_args,const cl_device_id device)633 static void generate_kernel_args(cl_context context, cl_kernel kernel, const WorkSizeInfo& ws, KernelArgs& cl_args, const cl_device_id device)
634 {
635 int error = CL_SUCCESS;
636 cl_uint num_args = 0;
637 KernelArg* cl_arg = NULL;
638 DataGenerator* dg = DataGenerator::getInstance();
639
640 error = clGetKernelInfo( kernel, CL_KERNEL_NUM_ARGS, sizeof( num_args ), &num_args, NULL );
641 if( error != CL_SUCCESS )
642 {
643 throw Exceptions::TestError("Unable to get kernel arg count\n", error);
644 }
645
646 for ( cl_uint j = 0; j < num_args; ++j )
647 {
648 KernelArgInfo kernel_arg_info;
649 size_t size;
650 const int max_name_len = 512;
651 char name[max_name_len];
652
653 // Try to get the address qualifier of each argument.
654 error = clGetKernelArgInfo( kernel, j, CL_KERNEL_ARG_ADDRESS_QUALIFIER, sizeof(cl_kernel_arg_address_qualifier), kernel_arg_info.getAddressQualifierRef(), &size);
655 if( error != CL_SUCCESS )
656 {
657 throw Exceptions::TestError("Unable to get argument address qualifier\n", error);
658 }
659
660 // Try to get the access qualifier of each argument.
661 error = clGetKernelArgInfo( kernel, j, CL_KERNEL_ARG_ACCESS_QUALIFIER, sizeof(cl_kernel_arg_access_qualifier), kernel_arg_info.getAccessQualifierRef(), &size );
662 if( error != CL_SUCCESS )
663 {
664 throw Exceptions::TestError("Unable to get argument access qualifier\n", error);
665 }
666
667 // Try to get the type qualifier of each argument.
668 error = clGetKernelArgInfo( kernel, j, CL_KERNEL_ARG_TYPE_QUALIFIER, sizeof(cl_kernel_arg_type_qualifier), kernel_arg_info.getTypeQualifierRef(), &size );
669 if( error != CL_SUCCESS )
670 {
671 throw Exceptions::TestError("Unable to get argument type qualifier\n", error);
672 }
673
674 // Try to get the type of each argument.
675 memset( name, 0, max_name_len );
676 error = clGetKernelArgInfo(kernel, j, CL_KERNEL_ARG_TYPE_NAME, max_name_len, name, NULL );
677 if( error != CL_SUCCESS )
678 {
679 throw Exceptions::TestError("Unable to get argument type name\n", error);
680 }
681 kernel_arg_info.setTypeName(name);
682
683 // Try to get the name of each argument.
684 memset( name, 0, max_name_len );
685 error = clGetKernelArgInfo( kernel, j, CL_KERNEL_ARG_NAME, max_name_len, name, NULL );
686 if( error != CL_SUCCESS )
687 {
688 throw Exceptions::TestError("Unable to get argument name\n", error);
689 }
690 kernel_arg_info.setName(name);
691
692 cl_arg = dg->generateKernelArg(context, kernel_arg_info, ws, NULL, kernel, device);
693 cl_args.addArg( cl_arg );
694 }
695 }
696
set_kernel_args(cl_kernel kernel,KernelArgs & args)697 void set_kernel_args( cl_kernel kernel, KernelArgs& args)
698 {
699 int error = CL_SUCCESS;
700 for( size_t i = 0; i < args.getArgCount(); ++ i )
701 {
702 error = clSetKernelArg( kernel, i, args.getArg(i)->getArgSize(), args.getArg(i)->getArgValue());
703 if( error != CL_SUCCESS )
704 {
705 throw Exceptions::TestError("clSetKernelArg failed\n", error);
706 }
707 }
708 }
709
710 /**
711 Run the single kernel
712 */
generate_kernel_data(cl_context context,cl_kernel kernel,WorkSizeInfo & ws,TestResult & results)713 void generate_kernel_data ( cl_context context, cl_kernel kernel, WorkSizeInfo &ws, TestResult& results)
714 {
715 cl_device_id device = get_context_device(context);
716 generate_kernel_ws( device, kernel, ws);
717 generate_kernel_args(context, kernel, ws, results.kernelArgs(), device);
718 }
719
720 /**
721 Run the single kernel
722 */
run_kernel(cl_kernel kernel,cl_command_queue queue,WorkSizeInfo & ws,TestResult & result)723 void run_kernel( cl_kernel kernel, cl_command_queue queue, WorkSizeInfo &ws, TestResult& result )
724 {
725 clEventWrapper execute_event;
726
727 set_kernel_args(kernel, result.kernelArgs());
728
729 int error = clEnqueueNDRangeKernel( queue, kernel, ws.work_dim, ws.global_work_offset, ws.global_work_size, ws.local_work_size, 0, NULL, &execute_event );
730 if( error != CL_SUCCESS )
731 {
732 throw Exceptions::TestError("clEnqueueNDRangeKernel failed\n", error);
733 }
734
735 error = clWaitForEvents( 1, &execute_event );
736 if( error != CL_SUCCESS )
737 {
738 throw Exceptions::TestError("clWaitForEvents failed\n", error);
739 }
740
741 // read all the buffers back to host
742 result.readToHost(queue);
743 }
744
745 /**
746 Compare two test results
747 */
compare_results(const TestResult & lhs,const TestResult & rhs,float ulps)748 bool compare_results( const TestResult& lhs, const TestResult& rhs, float ulps )
749 {
750 if( lhs.kernelArgs().getArgCount() != rhs.kernelArgs().getArgCount() )
751 {
752 log_error("number of kernel parameters differ between SPIR and CL version of the kernel\n");
753 return false;
754 }
755
756 for( size_t i = 0 ; i < lhs.kernelArgs().getArgCount(); ++i )
757 {
758 if( ! lhs.kernelArgs().getArg(i)->compare( *rhs.kernelArgs().getArg(i), ulps ) )
759 {
760 log_error("the kernel parameter (%d) is different between SPIR and CL version of the kernel\n", i);
761 return false;
762 }
763 }
764 return true;
765 }
766
767