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 #include "exceptions.h"
18 #include "datagen.h"
19 
20 RandomGenerator gRG;
21 
getGlobalWorkSize() const22 size_t WorkSizeInfo::getGlobalWorkSize() const
23 {
24     switch( work_dim )
25     {
26     case 1: return global_work_size[0];
27     case 2: return global_work_size[0] * global_work_size[1];
28     case 3: return global_work_size[0] * global_work_size[1] * global_work_size[2];
29     default:
30         throw Exceptions::TestError("wrong work dimention\n");
31     }
32 }
33 
34 /*
35  * DataGenerator
36  */
37 
38 DataGenerator* DataGenerator::Instance = NULL;
39 
getInstance()40 DataGenerator* DataGenerator::getInstance()
41 {
42     if (!Instance)
43         Instance = new DataGenerator();
44 
45     return Instance;
46 }
47 
DataGenerator()48 DataGenerator::DataGenerator()
49 {
50     #define TYPE_HNDL( type, isBuffer, base_element_size, vector_size, min_value, max_value, Generator) \
51     assert(m_argGenerators.find(type) == m_argGenerators.end()) ; \
52     m_argGenerators[type] = new Generator( isBuffer, vector_size, min_value, max_value);
53     #include "typeinfo.h"
54     #undef TYPE_HNDL
55 }
56 
~DataGenerator()57 DataGenerator::~DataGenerator()
58 {
59     ArgGeneratorsMap::iterator i = m_argGenerators.begin();
60     ArgGeneratorsMap::iterator e = m_argGenerators.end();
61 
62     for(; i != e; ++i)
63     {
64         delete i->second;
65     }
66 }
67 
getArgGenerator(const KernelArgInfo & argInfo)68 KernelArgGenerator* DataGenerator::getArgGenerator( const KernelArgInfo& argInfo )
69 {
70     //try to match the full type first
71     ArgGeneratorsMap::iterator i = m_argGenerators.find(argInfo.getTypeName());
72     ArgGeneratorsMap::iterator e = m_argGenerators.end();
73 
74     if( i != e )
75     {
76         return i->second;
77     }
78     // search for the proper prefix of the type
79     for(i = m_argGenerators.begin(); i != e; ++i)
80     {
81         if( 0 == argInfo.getTypeName().find(i->first))
82         {
83             return i->second;
84         }
85     }
86     throw Exceptions::TestError(std::string("Can't find the generator for the type ")
87       + argInfo.getTypeName() + " for argument " + argInfo.getName() + "\n");
88 }
89 
setArgGenerator(const KernelArgInfo & argInfo,KernelArgGenerator * pGen)90 void DataGenerator::setArgGenerator(const KernelArgInfo& argInfo,
91                                     KernelArgGenerator* pGen)
92 {
93     m_argGenerators[argInfo.getTypeName()] = pGen;
94 }
95 
get_random_int32(int low,int high,MTdata d)96 size_t get_random_int32(int low, int high, MTdata d)
97 {
98   int v = genrand_int32(d);
99 
100   assert(low <= high && "Invalid random number range specified");
101   size_t range = high - low;
102 
103   return (range) ? low + ((v - low) % range) : low;
104 }
105 
106 /*
107  * KernelArgGeneratorSampler
108  */
KernelArgGeneratorSampler(bool isBuffer,size_t vectorSize,int minValue,int maxValue)109 KernelArgGeneratorSampler::KernelArgGeneratorSampler(bool isBuffer,
110                                                      size_t vectorSize,
111                                                      int minValue,
112                                                      int maxValue) {
113   initToDefaults();
114 }
115 
initToDefaults()116 void KernelArgGeneratorSampler::initToDefaults() {
117   m_normalized = false;
118   m_addressingMode = CL_ADDRESS_NONE;
119   m_filterMode = CL_FILTER_NEAREST;
120 }
121 
KernelArgGeneratorSampler()122 KernelArgGeneratorSampler::KernelArgGeneratorSampler() {
123   initToDefaults();
124 
125 }
126 
setNormalized(cl_bool isNormalized)127 void KernelArgGeneratorSampler::setNormalized(cl_bool isNormalized)
128 {
129     m_normalized = isNormalized;
130 }
131 
setAddressingMode(cl_addressing_mode mode)132 void KernelArgGeneratorSampler::setAddressingMode(cl_addressing_mode mode)
133 {
134     m_addressingMode = mode;
135 }
136 
setFiterMode(cl_filter_mode mode)137 void KernelArgGeneratorSampler::setFiterMode(cl_filter_mode mode)
138 {
139     m_filterMode = mode;
140 }
141 
142 
143 /*
144  * SamplerValuesGenerator.
145  */
146 
147 /*
148  * Static fields initialization.
149  */
150 cl_bool SamplerValuesGenerator::coordNormalizations[] = {CL_TRUE, CL_FALSE};
151 
152 cl_filter_mode SamplerValuesGenerator::filterModes[]  = {
153     CL_FILTER_NEAREST,
154     CL_FILTER_LINEAR
155 };
156 
157 cl_addressing_mode SamplerValuesGenerator::addressingModes[] = {
158     CL_ADDRESS_NONE,
159     CL_ADDRESS_CLAMP,
160     CL_ADDRESS_CLAMP_TO_EDGE,
161     CL_ADDRESS_REPEAT,
162     CL_ADDRESS_MIRRORED_REPEAT
163 };
164 
165 const size_t NUM_NORM_MODES =
166     sizeof(SamplerValuesGenerator::coordNormalizations)/sizeof(cl_bool);
167 
168 const size_t NUM_FILTER_MODES =
169     sizeof(SamplerValuesGenerator::filterModes)/sizeof(cl_filter_mode);
170 
171 const size_t NUM_ADDR_MODES =
172     sizeof(SamplerValuesGenerator::addressingModes)/sizeof(cl_addressing_mode);
173 
end()174 SamplerValuesGenerator::iterator SamplerValuesGenerator::end()
175 {
176     return iterator(NUM_NORM_MODES-1, NUM_FILTER_MODES-1, NUM_ADDR_MODES-1);
177 }
178 
179 /*
180  * A constructor for generating an 'end iterator'.
181  */
iterator(size_t norm,size_t filter,size_t addressing)182 SamplerValuesGenerator::iterator::iterator(size_t norm, size_t filter,
183                                            size_t addressing):
184     m_normIndex(norm), m_filterIndex(filter), m_addressingModeIndex(addressing){}
185 
186 /*
187  * A constructor for generating a 'begin iterator'.
188  */
iterator()189 SamplerValuesGenerator::iterator::iterator():
190     m_normIndex(0), m_filterIndex(0), m_addressingModeIndex(0){}
191 
operator ++()192 SamplerValuesGenerator::iterator& SamplerValuesGenerator::iterator::operator ++()
193 {
194     if (incrementIndex(m_normIndex, NUM_NORM_MODES)) return *this;
195     if (incrementIndex(m_filterIndex, NUM_FILTER_MODES)) return *this;
196     if (incrementIndex(m_addressingModeIndex, NUM_ADDR_MODES)) return *this;
197 
198     assert(false && "incrementing end iterator!");
199     return *this;
200 }
201 
incrementIndex(size_t & i,const size_t limit)202 bool SamplerValuesGenerator::iterator::incrementIndex(size_t &i,
203                                                       const size_t limit)
204 {
205     i = (i+1) % limit;
206     return i != 0;
207 }
208 
operator ==(const iterator & other) const209 bool SamplerValuesGenerator::iterator::operator == (const iterator& other) const
210 {
211     return m_normIndex == other.m_normIndex &&
212          m_filterIndex == other.m_filterIndex &&
213          m_addressingModeIndex == other.m_addressingModeIndex;
214 }
215 
operator !=(const iterator & other) const216 bool SamplerValuesGenerator::iterator::operator != (const iterator& other) const
217 {
218     return !(*this == other);
219 }
220 
getNormalized() const221 cl_bool SamplerValuesGenerator::iterator::getNormalized() const
222 {
223     assert(m_normIndex < NUM_NORM_MODES && "illegal index");
224     return coordNormalizations[m_normIndex];
225 }
226 
getFilterMode() const227 cl_filter_mode SamplerValuesGenerator::iterator::getFilterMode() const
228 {
229     assert(m_filterIndex < NUM_FILTER_MODES && "illegal index");
230     return filterModes[m_filterIndex];
231 }
232 
getAddressingMode() const233 cl_addressing_mode SamplerValuesGenerator::iterator::getAddressingMode() const
234 {
235     assert(m_addressingModeIndex < NUM_ADDR_MODES && "illegal index");
236     return addressingModes[m_addressingModeIndex];
237 }
238 
toBitmap() const239 unsigned SamplerValuesGenerator::iterator::toBitmap() const
240 {
241     unsigned norm, filter, addressingModes;
242     switch (getNormalized())
243     {
244     case CL_TRUE:
245         norm = 8;
246         break;
247     case CL_FALSE:
248         norm = 0;
249         break;
250     default:
251     assert(0 && "invalid normalize value");
252     }
253 
254     switch (getFilterMode())
255     {
256     case CL_FILTER_NEAREST:
257         filter = 0;
258         break;
259     case CL_FILTER_LINEAR:
260         filter = 16;
261         break;
262     default:
263     assert(0 && "invalid filter value");
264     }
265 
266     switch(getAddressingMode())
267     {
268     case CL_ADDRESS_NONE:
269         addressingModes = 0;
270         break;
271     case CL_ADDRESS_CLAMP:
272         addressingModes = 1;
273         break;
274     case CL_ADDRESS_CLAMP_TO_EDGE:
275         addressingModes = 2;
276         break;
277     case CL_ADDRESS_REPEAT:
278         addressingModes = 3;
279         break;
280     case CL_ADDRESS_MIRRORED_REPEAT:
281         addressingModes = 4;
282         break;
283     default:
284     assert(0 && "invalid filter value");
285     }
286 
287     return norm | filter | addressingModes;
288 }
289 
toString() const290 std::string SamplerValuesGenerator::iterator::toString() const
291 {
292     std::string ret("(");
293 
294     switch (getNormalized())
295     {
296     case CL_TRUE:
297         ret.append("Normalized | ");
298         break;
299     case CL_FALSE:
300         ret.append("Not Normalized | ");
301         break;
302     default:
303     assert(0 && "invalid normalize value");
304     }
305 
306     switch (getFilterMode())
307     {
308     case CL_FILTER_NEAREST:
309         ret.append("Filter Nearest | ");
310         break;
311     case CL_FILTER_LINEAR:
312         ret.append("Filter Linear | ");
313         break;
314     default:
315     assert(0 && "invalid filter value");
316     }
317 
318     switch(getAddressingMode())
319     {
320     case CL_ADDRESS_NONE:
321         ret.append("Address None");
322         break;
323     case CL_ADDRESS_CLAMP:
324         ret.append("Address clamp");
325         break;
326     case CL_ADDRESS_CLAMP_TO_EDGE:
327         ret.append("Address clamp to edge");
328         break;
329     case CL_ADDRESS_REPEAT:
330         ret.append("Address repeat");
331         break;
332     case CL_ADDRESS_MIRRORED_REPEAT:
333         ret.append("Address mirrored repeat");
334         break;
335     default:
336     assert(0 && "invalid filter value");
337     }
338 
339     ret.append(")");
340     return ret;
341 }
342 
343 /*
344  * ImageValuesGenerator.
345  */
346 
347 /*
348  * Static fields initialization.
349  */
350 const char* ImageValuesGenerator::imageTypes[] = {
351     "image1d_array_float",
352     "image1d_array_int",
353     "image1d_array_uint",
354     "image1d_buffer_float",
355     "image1d_buffer_int",
356     "image1d_buffer_uint",
357     "image1d_float",
358     "image1d_int",
359     "image1d_uint",
360     "image2d_array_float",
361     "image2d_array_int",
362     "image2d_array_uint",
363     "image2d_float",
364     "image2d_int",
365     "image2d_uint",
366     "image3d_float",
367     "image3d_int",
368     "image3d_uint"
369 };
370 
371 cl_channel_order ImageValuesGenerator::channelOrders[] = {
372     CL_A,
373     CL_R,
374     CL_Rx,
375     CL_RG,
376     CL_RGx,
377     CL_RA,
378     CL_RGB,
379     CL_RGBx,
380     CL_RGBA,
381     CL_ARGB,
382     CL_BGRA,
383     CL_INTENSITY,
384     CL_LUMINANCE,
385     CL_DEPTH,
386     CL_DEPTH_STENCIL
387 };
388 
389 const size_t NUM_CHANNEL_ORDERS = sizeof(ImageValuesGenerator::channelOrders)/sizeof(ImageValuesGenerator::channelOrders[0]);
390 const size_t NUM_IMG_TYS = sizeof(ImageValuesGenerator::imageTypes)/sizeof(ImageValuesGenerator::imageTypes[0]);
391 
begin()392 ImageValuesGenerator::iterator ImageValuesGenerator::begin()
393 {
394     return ImageValuesGenerator::iterator(this);
395 }
396 
end()397 ImageValuesGenerator::iterator ImageValuesGenerator::end()
398 {
399     return ImageValuesGenerator::iterator(0);
400 }
401 /*
402  * Class Iterator
403  */
iterator(ImageValuesGenerator * pParent)404 ImageValuesGenerator::iterator::iterator(ImageValuesGenerator *pParent):
405     m_parent(pParent), m_channelIndex(0), m_imgTyIndex(0)
406 {
407 }
408 
409 /*
410  * Initializes an 'end' iterator.
411  */
iterator(int)412 ImageValuesGenerator::iterator::iterator(int):
413     m_parent(NULL),
414     m_channelIndex(NUM_CHANNEL_ORDERS),
415     m_imgTyIndex(NUM_IMG_TYS) {}
416 
operator ++()417 ImageValuesGenerator::iterator& ImageValuesGenerator::iterator::operator ++()
418 {
419     assert(m_channelIndex < NUM_CHANNEL_ORDERS && m_imgTyIndex < NUM_IMG_TYS &&
420            "Attempt to increment an end iterator");
421 
422     ImageValuesGenerator::iterator endIter = iterator(0);
423     // Incrementing untill we find the next legal combination, or we reach the
424     // end value.
425     while (incrementIndex(m_channelIndex,NUM_CHANNEL_ORDERS))
426         if (isLegalCombination())
427             return *this;
428 
429      // We have reach to this line because last increment caused an 'oveflow'
430      // in data channel order index.
431      if (incrementIndex(m_imgTyIndex, NUM_IMG_TYS))
432         // In case this combination is not legal, we go on to the next legal
433         // combo.
434         return isLegalCombination() ? *this : ++(*this);
435 
436     *this = endIter;
437     return *this;
438 }
439 
operator ==(const ImageValuesGenerator::iterator & o) const440 bool ImageValuesGenerator::iterator::operator == (
441     const ImageValuesGenerator::iterator& o) const
442 {
443     return m_channelIndex == o.m_channelIndex &&
444            m_imgTyIndex == o.m_imgTyIndex;
445 }
446 
operator !=(const ImageValuesGenerator::iterator & o) const447 bool ImageValuesGenerator::iterator::operator != (
448     const ImageValuesGenerator::iterator& o) const
449 {
450     return !(*this == o);
451 }
452 
getDataTypeName() const453 std::string ImageValuesGenerator::iterator::getDataTypeName() const
454 {
455     assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound");
456 
457     std::string tyName(imageTypes[m_imgTyIndex]);
458     // Find the last '_' and remove it (the suffix is _<channel type>).
459     size_t pos = tyName.find_last_of('_');
460     assert (std::string::npos != pos && "no under score in type name?");
461     tyName = tyName.erase(0, pos+1);
462     return tyName;
463 }
464 
getOpenCLChannelOrder() const465 int ImageValuesGenerator::iterator::getOpenCLChannelOrder() const
466 {
467     assert(m_channelIndex < NUM_CHANNEL_ORDERS && "channel index out of bound");
468     return channelOrders[m_channelIndex];
469 }
470 
getSPIRChannelOrder() const471 int ImageValuesGenerator::iterator::getSPIRChannelOrder() const
472 {
473     return getOpenCLChannelOrder();
474 }
475 
getImageTypeName() const476 std::string ImageValuesGenerator::iterator::getImageTypeName() const
477 {
478     assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound");
479 
480     std::string tyName = imageTypes[m_imgTyIndex];
481     // Find the last '_' and remove it (the suffix is _<channel type>).
482     size_t pos = tyName.find_last_of('_');
483     assert (std::string::npos != pos && "no under score in type name?");
484     tyName = tyName.erase(pos, tyName.size() - pos);
485 
486     return tyName;
487 }
488 
getImageGeneratorName() const489 std::string ImageValuesGenerator::iterator::getImageGeneratorName() const
490 {
491     assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound");
492     return imageTypes[m_imgTyIndex];
493 }
494 
getBaseImageGeneratorName() const495 std::string ImageValuesGenerator::iterator::getBaseImageGeneratorName() const
496 {
497     assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound");
498     std::string tyName = getImageTypeName();
499     tyName.append("_t");
500     return tyName;
501 }
502 
getDataType() const503 int ImageValuesGenerator::iterator::getDataType() const
504 {
505     assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound");
506     std::string tyName = getDataTypeName();
507 
508     if ("int" == tyName)
509        return SPIR_CLK_SIGNED_INT32;
510     if ("uint" == tyName)
511         return SPIR_CLK_UNSIGNED_INT32;
512     if ("float" == tyName)
513         return SPIR_CLK_FLOAT;
514     assert (false && "unkown image data type");
515     return -1;
516 }
517 
toString() const518 std::string ImageValuesGenerator::iterator::toString() const
519 {
520     if (*this == m_parent->end())
521         return "End iterator";
522 
523     // Sanity.
524     assert(m_imgTyIndex < NUM_IMG_TYS && "image type index is out of bound");
525     assert(m_channelIndex < NUM_CHANNEL_ORDERS && "channel index out of bound");
526 
527     std::string str = imageTypes[m_imgTyIndex];
528     str.append("_");
529 
530     switch (channelOrders[m_channelIndex])
531     {
532     case CL_R:
533         str.append("cl_r");
534         break;
535     case CL_A:
536         str.append("cl_a");
537         break;
538     case CL_RG:
539         str.append("cl_rg");
540         break;
541     case CL_RA:
542         str.append("cl_ra");
543         break;
544     case CL_RGB:
545         str.append("cl_rgb");
546         break;
547     case CL_RGBA:
548         str.append("cl_rgba");
549         break;
550     case CL_BGRA:
551         str.append("cl_bgra");
552         break;
553     case CL_ARGB:
554         str.append("cl_argb");
555         break;
556     case CL_INTENSITY:
557         str.append("cl_intensity");
558         break;
559     case CL_LUMINANCE:
560         str.append("cl_luminace");
561         break;
562     case CL_Rx:
563         str.append("cl_Rx");
564         break;
565     case CL_RGx:
566         str.append("cl_RGx");
567         break;
568     case CL_RGBx:
569         str.append("cl_RGBx");
570         break;
571     case CL_DEPTH:
572         str.append("cl_depth");
573         break;
574     case CL_DEPTH_STENCIL:
575         str.append( "cl_depth_stencil");
576         break;
577     default:
578         assert(false && "Invalid channel order");
579         str.append("<invalid channel order>");
580         break;
581     }
582 
583     return str;
584 }
585 
incrementIndex(size_t & index,size_t arrSize)586 bool ImageValuesGenerator::iterator::incrementIndex(size_t& index,
587                                                     size_t arrSize)
588 {
589     index = (index + 1) % arrSize;
590     return index != 0;
591 }
592 
isLegalCombination() const593 bool ImageValuesGenerator::iterator::isLegalCombination() const
594 {
595     cl_channel_order corder = channelOrders[m_channelIndex];
596     std::string strImgTy(imageTypes[m_imgTyIndex]);
597 
598     if (corder == CL_INTENSITY || corder == CL_LUMINANCE)
599     {
600         return getDataTypeName() == std::string("float");
601     }
602 
603     if (corder == CL_DEPTH)
604         return false;
605 
606     if (corder == CL_RGBx || corder == CL_RGB // Can only be applied for int unorms.
607         || corder == CL_ARGB || corder == CL_BGRA) // Can only be applied for int8.
608         return false;
609 
610     return true;
611 }
612 
613