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
18 #include "gl_headers.h"
19
get_kernel_suffix(cl_image_format * format)20 const char *get_kernel_suffix( cl_image_format *format )
21 {
22 switch( format->image_channel_data_type )
23 {
24 case CL_UNORM_INT8:
25 case CL_UNORM_INT16:
26 case CL_SNORM_INT8:
27 case CL_SNORM_INT16:
28 case CL_FLOAT:
29 return "f";
30 case CL_HALF_FLOAT:
31 return "h";
32 case CL_SIGNED_INT8:
33 case CL_SIGNED_INT16:
34 case CL_SIGNED_INT32:
35 return "i";
36 case CL_UNSIGNED_INT8:
37 case CL_UNSIGNED_INT16:
38 case CL_UNSIGNED_INT32:
39 return "ui";
40 default:
41 return "";
42 }
43 }
44
get_read_kernel_type(cl_image_format * format)45 ExplicitType get_read_kernel_type( cl_image_format *format )
46 {
47 switch( format->image_channel_data_type )
48 {
49 case CL_UNORM_INT8:
50 case CL_UNORM_INT16:
51 case CL_SNORM_INT8:
52 case CL_SNORM_INT16:
53 case CL_FLOAT:
54 return kFloat;
55 case CL_HALF_FLOAT:
56 return kHalf;
57 case CL_SIGNED_INT8:
58 case CL_SIGNED_INT16:
59 case CL_SIGNED_INT32:
60 return kInt;
61 case CL_UNSIGNED_INT8:
62 case CL_UNSIGNED_INT16:
63 case CL_UNSIGNED_INT32:
64 return kUInt;
65 default:
66 return kInt;
67 }
68 }
69
get_write_kernel_type(cl_image_format * format)70 ExplicitType get_write_kernel_type( cl_image_format *format )
71 {
72 switch( format->image_channel_data_type )
73 {
74 case CL_UNORM_INT8:
75 return kFloat;
76 case CL_UNORM_INT16:
77 return kFloat;
78 case CL_SNORM_INT8:
79 return kFloat;
80 case CL_SNORM_INT16:
81 return kFloat;
82 case CL_HALF_FLOAT:
83 return kHalf;
84 case CL_FLOAT:
85 return kFloat;
86 case CL_SIGNED_INT8:
87 return kChar;
88 case CL_SIGNED_INT16:
89 return kShort;
90 case CL_SIGNED_INT32:
91 return kInt;
92 case CL_UNSIGNED_INT8:
93 return kUChar;
94 case CL_UNSIGNED_INT16:
95 return kUShort;
96 case CL_UNSIGNED_INT32:
97 return kUInt;
98 default:
99 return kInt;
100 }
101 }
102
get_write_conversion(cl_image_format * format,ExplicitType type)103 const char* get_write_conversion( cl_image_format *format, ExplicitType type )
104 {
105 switch( format->image_channel_data_type )
106 {
107 case CL_UNORM_INT8:
108 case CL_UNORM_INT16:
109 case CL_SNORM_INT8:
110 case CL_SNORM_INT16:
111 case CL_FLOAT:
112 if(type != kFloat) return "convert_float4";
113 break;
114 case CL_HALF_FLOAT:
115 break;
116 case CL_SIGNED_INT8:
117 case CL_SIGNED_INT16:
118 case CL_SIGNED_INT32:
119 if(type != kInt) return "convert_int4";
120 break;
121 case CL_UNSIGNED_INT8:
122 case CL_UNSIGNED_INT16:
123 case CL_UNSIGNED_INT32:
124 if(type != kUInt) return "convert_uint4";
125 break;
126 default:
127 return "";
128 }
129 return "";
130 }
131
132 // The only three input types to this function are kInt, kUInt and kFloat, due to the way we set up our tests
133 // The output types, though, are pretty much anything valid for GL to receive
134
135 #define DOWNSCALE_INTEGER_CASE( enum, type, bitShift ) \
136 case enum: \
137 { \
138 cl_##type *dst = new cl_##type[ numPixels * 4 ]; \
139 for( size_t i = 0; i < numPixels * 4; i++ ) \
140 dst[ i ] = src[ i ]; \
141 return (char *)dst; \
142 }
143
144 #define UPSCALE_FLOAT_CASE( enum, type, typeMax ) \
145 case enum: \
146 { \
147 cl_##type *dst = new cl_##type[ numPixels * 4 ]; \
148 for( size_t i = 0; i < numPixels * 4; i++ ) \
149 dst[ i ] = (cl_##type)( src[ i ] * typeMax ); \
150 return (char *)dst; \
151 }
152
convert_to_expected(void * inputBuffer,size_t numPixels,ExplicitType inType,ExplicitType outType)153 char * convert_to_expected( void * inputBuffer, size_t numPixels, ExplicitType inType, ExplicitType outType )
154 {
155 #ifdef GLES_DEBUG
156 log_info( "- Converting from input type '%s' to output type '%s'\n",
157 get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
158 #endif
159
160 if( inType == outType )
161 {
162 char *outData = new char[ numPixels * 4 * get_explicit_type_size(outType) ] ; // sizeof( cl_int ) ];
163 memcpy( outData, inputBuffer, numPixels * 4 * get_explicit_type_size(inType) );
164 return outData;
165 }
166 else if( inType == kChar )
167 {
168 cl_char *src = (cl_char *)inputBuffer;
169
170 switch( outType )
171 {
172 case kInt:
173 {
174 cl_int *outData = new cl_int[ numPixels * 4 ];
175 for( size_t i = 0; i < numPixels * 4; i++ )
176 {
177 outData[ i ] = (cl_int)((src[ i ]));
178 }
179 return (char *)outData;
180 }
181 case kFloat:
182 {
183 // If we're converting to float, then CL decided that we should be normalized
184 cl_float *outData = new cl_float[ numPixels * 4 ];
185 for( size_t i = 0; i < numPixels * 4; i++ )
186 {
187 outData[ i ] = (cl_float)src[ i ] / 127.0f;
188 }
189 return (char *)outData;
190 }
191 default:
192 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
193 return NULL;
194 }
195 }
196 else if( inType == kUChar )
197 {
198 cl_uchar *src = (cl_uchar *)inputBuffer;
199
200 switch( outType )
201 {
202 case kUInt:
203 {
204 cl_uint *outData = new cl_uint[ numPixels * 4 ];
205 for( size_t i = 0; i < numPixels * 4; i++ )
206 {
207 outData[ i ] = (cl_uint)((src[ i ]));
208 }
209 return (char *)outData;
210 }
211 case kFloat:
212 {
213 // If we're converting to float, then CL decided that we should be normalized
214 cl_float *outData = new cl_float[ numPixels * 4 ];
215 for( size_t i = 0; i < numPixels * 4; i++ )
216 {
217 outData[ i ] = (cl_float)(src[ i ]) / 256.0f;
218 }
219 return (char *)outData;
220 }
221 default:
222 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
223 return NULL;
224 }
225 }
226 else if( inType == kShort )
227 {
228 cl_short *src = (cl_short *)inputBuffer;
229
230 switch( outType )
231 {
232 case kInt:
233 {
234 cl_int *outData = new cl_int[ numPixels * 4 ];
235 for( size_t i = 0; i < numPixels * 4; i++ )
236 {
237 outData[ i ] = (cl_int)((src[ i ]));
238 }
239 return (char *)outData;
240 }
241 case kFloat:
242 {
243 // If we're converting to float, then CL decided that we should be normalized
244 cl_float *outData = new cl_float[ numPixels * 4 ];
245 for( size_t i = 0; i < numPixels * 4; i++ )
246 {
247 outData[ i ] = (cl_float)src[ i ] / 32768.0f;
248 }
249 return (char *)outData;
250 }
251 default:
252 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
253 return NULL;
254 }
255 }
256 else if( inType == kUShort )
257 {
258 cl_ushort *src = (cl_ushort *)inputBuffer;
259
260 switch( outType )
261 {
262 case kUInt:
263 {
264 cl_uint *outData = new cl_uint[ numPixels * 4 ];
265 for( size_t i = 0; i < numPixels * 4; i++ )
266 {
267 outData[ i ] = (cl_uint)((src[ i ]));
268 }
269 return (char *)outData;
270 }
271 case kFloat:
272 {
273 // If we're converting to float, then CL decided that we should be normalized
274 cl_float *outData = new cl_float[ numPixels * 4 ];
275 for( size_t i = 0; i < numPixels * 4; i++ )
276 {
277 outData[ i ] = (cl_float)(src[ i ]) / 65535.0f;
278 }
279 return (char *)outData;
280 }
281 default:
282 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
283 return NULL;
284 }
285 }
286 else if( inType == kInt )
287 {
288 cl_int *src = (cl_int *)inputBuffer;
289
290 switch( outType )
291 {
292 DOWNSCALE_INTEGER_CASE( kShort, short, 16 )
293 DOWNSCALE_INTEGER_CASE( kChar, char, 24 )
294 case kFloat:
295 {
296 // If we're converting to float, then CL decided that we should be normalized
297 cl_float *outData = new cl_float[ numPixels * 4 ];
298 for( size_t i = 0; i < numPixels * 4; i++ )
299 {
300 outData[ i ] = (cl_float)fmaxf( (float)src[ i ] / 2147483647.f, -1.f );
301 }
302 return (char *)outData;
303 }
304 default:
305 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
306 return NULL;
307 }
308 }
309 else if( inType == kUInt )
310 {
311 cl_uint *src = (cl_uint *)inputBuffer;
312
313 switch( outType )
314 {
315 DOWNSCALE_INTEGER_CASE( kUShort, ushort, 16 )
316 DOWNSCALE_INTEGER_CASE( kUChar, uchar, 24 )
317 case kFloat:
318 {
319 // If we're converting to float, then CL decided that we should be normalized
320 cl_float *outData = new cl_float[ numPixels * 4 ];
321 for( size_t i = 0; i < numPixels * 4; i++ )
322 {
323 outData[ i ] = (cl_float)src[ i ] / 4294967295.f;
324 }
325 return (char *)outData;
326 }
327 default:
328 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
329 return NULL;
330 }
331 }
332 else
333 {
334 cl_float *src = (cl_float *)inputBuffer;
335
336 switch( outType )
337 {
338 UPSCALE_FLOAT_CASE( kChar, char, 127.f )
339 UPSCALE_FLOAT_CASE( kUChar, uchar, 255.f )
340 UPSCALE_FLOAT_CASE( kShort, short, 32767.f )
341 UPSCALE_FLOAT_CASE( kUShort, ushort, 65535.f )
342 UPSCALE_FLOAT_CASE( kInt, int, 2147483647.f )
343 UPSCALE_FLOAT_CASE( kUInt, uint, 4294967295.f )
344 default:
345 log_error( "ERROR: Unsupported conversion from %s to %s!\n", get_explicit_type_name( inType ), get_explicit_type_name( outType ) );
346 return NULL;
347 }
348 }
349
350 return NULL;
351 }
352
validate_integer_results(void * expectedResults,void * actualResults,size_t width,size_t height,size_t typeSize)353 int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t typeSize )
354 {
355 return validate_integer_results( expectedResults, actualResults, width, height, 0, typeSize );
356 }
357
validate_integer_results(void * expectedResults,void * actualResults,size_t width,size_t height,size_t depth,size_t typeSize)358 int validate_integer_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth, size_t typeSize )
359 {
360 char *expected = (char *)expectedResults;
361 char *actual = (char *)actualResults;
362 for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ )
363 {
364 for( size_t y = 0; y < height; y++ )
365 {
366 for( size_t x = 0; x < width; x++ )
367 {
368 if( memcmp( expected, actual, typeSize * 4 ) != 0 )
369 {
370 char scratch[ 1024 ];
371
372 if( depth == 0 )
373 log_error( "ERROR: Data sample %d,%d did not validate!\n", (int)x, (int)y );
374 else
375 log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)z );
376 log_error( "\tExpected: %s\n", GetDataVectorString( expected, typeSize, 4, scratch ) );
377 log_error( "\t Actual: %s\n", GetDataVectorString( actual, typeSize, 4, scratch ) );
378 return -1;
379 }
380 expected += typeSize * 4;
381 actual += typeSize * 4;
382 }
383 }
384 }
385
386 return 0;
387 }
388
validate_float_results(void * expectedResults,void * actualResults,size_t width,size_t height)389 int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height )
390 {
391 return validate_float_results( expectedResults, actualResults, width, height, 0 );
392 }
393
validate_float_results(void * expectedResults,void * actualResults,size_t width,size_t height,size_t depth)394 int validate_float_results( void *expectedResults, void *actualResults, size_t width, size_t height, size_t depth )
395 {
396 cl_float *expected = (cl_float *)expectedResults;
397 cl_float *actual = (cl_float *)actualResults;
398 for( size_t z = 0; z < ( ( depth == 0 ) ? 1 : depth ); z++ )
399 {
400 for( size_t y = 0; y < height; y++ )
401 {
402 for( size_t x = 0; x < width; x++ )
403 {
404 float err = 0.f;
405 for( size_t i = 0; i < 4; i++ )
406 {
407 float error = fabsf( expected[ i ] - actual[ i ] );
408 if( error > err )
409 err = error;
410 }
411
412 if( err > 1.f / 127.f ) // Max expected range of error if we converted from an 8-bit integer to a normalized float
413 {
414 if( depth == 0 )
415 log_error( "ERROR: Data sample %d,%d did not validate!\n", (int)x, (int)y );
416 else
417 log_error( "ERROR: Data sample %d,%d,%d did not validate!\n", (int)x, (int)y, (int)z );
418 log_error( "\tExpected: %f %f %f %f\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
419 log_error( "\t : %a %a %a %a\n", expected[ 0 ], expected[ 1 ], expected[ 2 ], expected[ 3 ] );
420 log_error( "\t Actual: %f %f %f %f\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
421 log_error( "\t : %a %a %a %a\n", actual[ 0 ], actual[ 1 ], actual[ 2 ], actual[ 3 ] );
422 return -1;
423 }
424 expected += 4;
425 actual += 4;
426 }
427 }
428 }
429
430 return 0;
431 }
432
CheckGLObjectInfo(cl_mem mem,cl_gl_object_type expected_cl_gl_type,GLuint expected_gl_name,GLenum expected_cl_gl_texture_target,GLint expected_cl_gl_mipmap_level)433 int CheckGLObjectInfo(cl_mem mem, cl_gl_object_type expected_cl_gl_type, GLuint expected_gl_name,
434 GLenum expected_cl_gl_texture_target, GLint expected_cl_gl_mipmap_level)
435 {
436 cl_gl_object_type object_type;
437 GLuint object_name;
438 GLenum texture_target;
439 GLint mipmap_level;
440 int error;
441
442 error = (*clGetGLObjectInfo_ptr)(mem, &object_type, &object_name);
443 test_error( error, "clGetGLObjectInfo failed");
444 if (object_type != expected_cl_gl_type) {
445 log_error("clGetGLObjectInfo did not return expected object type: expected %d, got %d.\n", expected_cl_gl_type, object_type);
446 return -1;
447 }
448 if (object_name != expected_gl_name) {
449 log_error("clGetGLObjectInfo did not return expected object name: expected %d, got %d.\n", expected_gl_name, object_name);
450 return -1;
451 }
452
453 if (object_type == CL_GL_OBJECT_TEXTURE2D || object_type == CL_GL_OBJECT_TEXTURE3D) {
454 error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_TEXTURE_TARGET, sizeof(texture_target), &texture_target, NULL);
455 test_error( error, "clGetGLTextureInfo for CL_GL_TEXTURE_TARGET failed");
456
457 if (texture_target != expected_cl_gl_texture_target) {
458 log_error("clGetGLTextureInfo did not return expected texture target: expected %d, got %d.\n", expected_cl_gl_texture_target, texture_target);
459 return -1;
460 }
461
462 error = (*clGetGLTextureInfo_ptr)(mem, CL_GL_MIPMAP_LEVEL, sizeof(mipmap_level), &mipmap_level, NULL);
463 test_error( error, "clGetGLTextureInfo for CL_GL_MIPMAP_LEVEL failed");
464
465 if (mipmap_level != expected_cl_gl_mipmap_level) {
466 log_error("clGetGLTextureInfo did not return expected mipmap level: expected %d, got %d.\n", expected_cl_gl_mipmap_level, mipmap_level);
467 return -1;
468 }
469 }
470 return 0;
471 }
472
CheckGLIntegerExtensionSupport()473 bool CheckGLIntegerExtensionSupport()
474 {
475 // Get the OpenGL version and supported extensions
476 const GLubyte *glVersion = glGetString(GL_VERSION);
477 const GLubyte *glExtensionList = glGetString(GL_EXTENSIONS);
478
479 // Check if the OpenGL vrsion is 3.0 or grater or GL_EXT_texture_integer is supported
480 return (((glVersion[0] - '0') >= 3) || (strstr((const char*)glExtensionList, "GL_EXT_texture_integer")));
481 }
482