• 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 "../harness/compat.h"
17 
18 #include <stdio.h>
19 #include <string.h>
20 
21 #if !defined(_WIN32)
22 #include <unistd.h>
23 #include <sys/time.h>
24 #endif
25 
26 #include "../testBase.h"
27 #include "../harness/fpcontrol.h"
28 #include "../harness/parseParameters.h"
29 
30 #include <vector>
31 
32 #if defined(__PPC__)
33 // Global varaiable used to hold the FPU control register state. The FPSCR register can not
34 // be used because not all Power implementations retain or observed the NI (non-IEEE
35 // mode) bit.
36 __thread fpu_control_t fpu_control = 0;
37 #endif
38 
39 bool gDebugTrace;
40 bool gExtraValidateInfo;
41 bool gDisableOffsets;
42 bool gTestSmallImages;
43 bool gTestMaxImages;
44 bool gTestImage2DFromBuffer;
45 bool gTestMipmaps;
46 bool gDeviceLt20 = false;
47 cl_filter_mode    gFilterModeToUse = (cl_filter_mode)-1;
48 // Default is CL_MEM_USE_HOST_PTR for the test
49 cl_mem_flags    gMemFlagsToUse = CL_MEM_USE_HOST_PTR;
50 bool            gUseKernelSamplers = false;
51 int                gTypesToTest = 0;
52 cl_addressing_mode gAddressModeToUse = (cl_addressing_mode)-1;
53 int             gNormalizedModeToUse = 7;
54 cl_channel_type gChannelTypeToUse = (cl_channel_type)-1;
55 cl_channel_order gChannelOrderToUse = (cl_channel_order)-1;
56 bool            gEnablePitch = false;
57 
58 int             gtestTypesToRun = 0;
59 static int testTypesToRun;
60 
61 #define MAX_ALLOWED_STD_DEVIATION_IN_MB        8.0
62 
63 static void printUsage( const char *execName );
64 
65 extern int test_image_set( cl_device_id device, cl_context context, cl_command_queue queue, test_format_set_fn formatTestFn, cl_mem_object_type imageType );
66 
67 /** read_write images only support sampler-less read buildt-ins which require special settings
68   * for some global parameters. This pair of functions temporarily overwrite those global parameters
69   * and then recover them after completing a read_write test.
70   */
overwrite_global_params_for_read_write_test(bool * tTestMipmaps,bool * tDisableOffsets,bool * tNormalizedModeToUse,cl_filter_mode * tFilterModeToUse)71 static void overwrite_global_params_for_read_write_test(  bool            *tTestMipmaps,
72                                                             bool            *tDisableOffsets,
73                                                             bool            *tNormalizedModeToUse,
74                                                             cl_filter_mode  *tFilterModeToUse)
75 {
76     log_info("Overwrite global settings for read_write image tests. The overwritten values:\n");
77     log_info("gTestMipmaps = false, gDisableOffsets = true, gNormalizedModeToUse = false, gFilterModeToUse = CL_FILTER_NEAREST\n" );
78     // mipmap images only support sampler read built-in while read_write images only support
79     // sampler-less read built-in. Hence we cannot test mipmap for read_write image.
80     *tTestMipmaps = gTestMipmaps;
81     gTestMipmaps = false;
82 
83     // Read_write images are read by sampler-less read which does not handle out-of-bound read
84     // It's application responsibility to make sure that the read happens in-bound
85     // Therefore we should not enable offset in testing read_write images because it will cause out-of-bound
86     *tDisableOffsets    = gDisableOffsets;
87     gDisableOffsets     = true;
88 
89     // The sampler-less read image functions behave exactly as the corresponding read image functions
90 
91 
92     *tNormalizedModeToUse   = gNormalizedModeToUse;
93     gNormalizedModeToUse    = false;
94     *tFilterModeToUse       = gFilterModeToUse;
95     gFilterModeToUse        = CL_FILTER_NEAREST;
96 }
97 
98 /** Recover the global settings overwritten for read_write tests. This is necessary because
99   * there may be other tests (i.e. read or write) are called together with read_write test.
100   */
recover_global_params_from_read_write_test(bool tTestMipmaps,bool tDisableOffsets,bool tNormalizedModeToUse,cl_filter_mode tFilterModeToUse)101 static void recover_global_params_from_read_write_test(bool            tTestMipmaps,
102                                                          bool            tDisableOffsets,
103                                                          bool            tNormalizedModeToUse,
104                                                          cl_filter_mode  tFilterModeToUse)
105 {
106     gTestMipmaps            = tTestMipmaps;
107     gDisableOffsets         = tDisableOffsets;
108     gNormalizedModeToUse    = tNormalizedModeToUse;
109     gFilterModeToUse        = tFilterModeToUse;
110 }
111 
doTest(cl_device_id device,cl_context context,cl_command_queue queue,cl_mem_object_type imageType)112 static int doTest( cl_device_id device, cl_context context, cl_command_queue queue, cl_mem_object_type imageType )
113 {
114     int ret = 0;
115     bool is_2d_image = imageType == CL_MEM_OBJECT_IMAGE2D;
116     bool            tTestMipMaps = false;
117     bool            tDisableOffsets = false;
118     bool            tNormalizedModeToUse = false;
119     cl_filter_mode  tFilterModeToUse = (cl_filter_mode)-1;
120     auto version = get_device_cl_version(device);
121     if (version < Version(2, 0)) {
122         gDeviceLt20 = true;
123     }
124 
125     if( testTypesToRun & kReadTests )
126     {
127         gtestTypesToRun = kReadTests;
128         ret += test_image_set( device, context, queue, test_read_image_formats, imageType );
129 
130         if( is_2d_image && is_extension_available( device, "cl_khr_image2d_from_buffer" ) )
131         {
132             log_info( "Testing read_image{f | i | ui} for 2D image from buffer\n" );
133 
134             // NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages, gTestRounding and gTestMipmaps must be false
135             if( gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false )
136             {
137                 cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse;
138                 gTestImage2DFromBuffer = true;
139 
140                 // disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0
141                 gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
142 
143                 ret += test_image_set( device, context, queue, test_read_image_formats, imageType );
144 
145                 gTestImage2DFromBuffer = false;
146                 gMemFlagsToUse = saved_gMemFlagsToUse;
147             }
148         }
149     }
150 
151     if( testTypesToRun & kWriteTests )
152     {
153         gtestTypesToRun = kWriteTests;
154         ret += test_image_set( device, context, queue, test_write_image_formats, imageType );
155 
156         if( is_2d_image && is_extension_available( device, "cl_khr_image2d_from_buffer" ) )
157         {
158             log_info( "Testing write_image{f | i | ui} for 2D image from buffer\n" );
159 
160             // NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages,gTestRounding and gTestMipmaps must be false
161             if( gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false )
162             {
163                 bool saved_gEnablePitch = gEnablePitch;
164                 cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse;
165                 gEnablePitch = true;
166 
167                 // disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0
168                 gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
169                 gTestImage2DFromBuffer = true;
170 
171                 ret += test_image_set( device, context, queue, test_write_image_formats, imageType );
172 
173                 gTestImage2DFromBuffer = false;
174                 gMemFlagsToUse = saved_gMemFlagsToUse;
175                 gEnablePitch = saved_gEnablePitch;
176             }
177         }
178     }
179 
180     if (testTypesToRun & kReadWriteTests) {
181         if (gDeviceLt20)  {
182             log_info("TEST skipped, Opencl 2.0 + requried for this test");
183             return ret;
184         }
185     }
186 
187     if( ( testTypesToRun & kReadWriteTests ) && !gTestMipmaps )
188     {
189         gtestTypesToRun = kReadWriteTests;
190         overwrite_global_params_for_read_write_test(&tTestMipMaps, &tDisableOffsets, &tNormalizedModeToUse, &tFilterModeToUse);
191         ret += test_image_set( device, context, queue, test_read_image_formats, imageType );
192 
193         if( is_2d_image && is_extension_available( device, "cl_khr_image2d_from_buffer" ) )
194         {
195             log_info("Testing read_image{f | i | ui} for 2D image from buffer\n");
196 
197             // NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages, gTestRounding and gTestMipmaps must be false
198             if( gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false )
199             {
200                 cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse;
201                 gTestImage2DFromBuffer = true;
202 
203                 // disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0
204                 gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
205 
206                 ret += test_image_set( device, context, queue, test_read_image_formats, imageType );
207 
208                 gTestImage2DFromBuffer = false;
209                 gMemFlagsToUse = saved_gMemFlagsToUse;
210             }
211         }
212 
213         ret += test_image_set( device, context, queue, test_write_image_formats, imageType );
214 
215         if( is_2d_image && is_extension_available( device, "cl_khr_image2d_from_buffer" ) )
216         {
217             log_info("Testing write_image{f | i | ui} for 2D image from buffer\n");
218 
219             // NOTE: for 2D image from buffer test, gTestSmallImages, gTestMaxImages,gTestRounding and gTestMipmaps must be false
220             if( gTestSmallImages == false && gTestMaxImages == false && gTestRounding == false && gTestMipmaps == false )
221             {
222                 bool saved_gEnablePitch = gEnablePitch;
223                 cl_mem_flags saved_gMemFlagsToUse = gMemFlagsToUse;
224                 gEnablePitch = true;
225 
226                 // disable CL_MEM_USE_HOST_PTR for 1.2 extension but enable this for 2.0
227                 gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
228                 gTestImage2DFromBuffer = true;
229 
230                 ret += test_image_set( device, context, queue, test_write_image_formats, imageType );
231 
232                 gTestImage2DFromBuffer = false;
233                 gMemFlagsToUse = saved_gMemFlagsToUse;
234                 gEnablePitch = saved_gEnablePitch;
235             }
236         }
237 
238         recover_global_params_from_read_write_test( tTestMipMaps, tDisableOffsets, tNormalizedModeToUse, tFilterModeToUse );
239     }
240 
241     return ret;
242 }
243 
test_1D(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)244 int test_1D(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
245 {
246     return doTest( device, context, queue, CL_MEM_OBJECT_IMAGE1D );
247 }
test_2D(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)248 int test_2D(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
249 {
250     return doTest( device, context, queue, CL_MEM_OBJECT_IMAGE2D );
251 }
test_3D(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)252 int test_3D(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
253 {
254     return doTest( device, context, queue, CL_MEM_OBJECT_IMAGE3D );
255 }
test_1Darray(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)256 int test_1Darray(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
257 {
258     return doTest( device, context, queue, CL_MEM_OBJECT_IMAGE1D_ARRAY );
259 }
test_2Darray(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)260 int test_2Darray(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
261 {
262     return doTest( device, context, queue, CL_MEM_OBJECT_IMAGE2D_ARRAY );
263 }
264 
265 test_definition test_list[] = {
266     ADD_TEST( 1D ),
267     ADD_TEST( 2D ),
268     ADD_TEST( 3D ),
269     ADD_TEST( 1Darray ),
270     ADD_TEST( 2Darray ),
271 };
272 
273 const int test_num = ARRAY_SIZE( test_list );
274 
main(int argc,const char * argv[])275 int main(int argc, const char *argv[])
276 {
277     cl_channel_type chanType;
278     cl_channel_order chanOrder;
279 
280     argc = parseCustomParam(argc, argv);
281     if (argc == -1)
282     {
283         return -1;
284     }
285 
286     const char ** argList = (const char **)calloc( argc, sizeof( char*) );
287 
288     if( NULL == argList )
289     {
290         log_error( "Failed to allocate memory for argList array.\n" );
291         return 1;
292     }
293 
294     argList[0] = argv[0];
295     size_t argCount = 1;
296 
297     // Parse arguments
298     for( int i = 1; i < argc; i++ )
299     {
300         if( strcmp( argv[i], "debug_trace" ) == 0 )
301             gDebugTrace = true;
302 
303         else if( strcmp( argv[i], "CL_FILTER_NEAREST" ) == 0 || strcmp( argv[i], "NEAREST" ) == 0 )
304             gFilterModeToUse = CL_FILTER_NEAREST;
305         else if( strcmp( argv[i], "CL_FILTER_LINEAR" ) == 0 || strcmp( argv[i], "LINEAR" ) == 0 )
306             gFilterModeToUse = CL_FILTER_LINEAR;
307 
308         else if( strcmp( argv[i], "CL_ADDRESS_NONE" ) == 0 )
309             gAddressModeToUse = CL_ADDRESS_NONE;
310         else if( strcmp( argv[i], "CL_ADDRESS_CLAMP" ) == 0 )
311             gAddressModeToUse = CL_ADDRESS_CLAMP;
312         else if( strcmp( argv[i], "CL_ADDRESS_CLAMP_TO_EDGE" ) == 0 )
313             gAddressModeToUse = CL_ADDRESS_CLAMP_TO_EDGE;
314         else if( strcmp( argv[i], "CL_ADDRESS_REPEAT" ) == 0 )
315             gAddressModeToUse = CL_ADDRESS_REPEAT;
316         else if( strcmp( argv[i], "CL_ADDRESS_MIRRORED_REPEAT" ) == 0 )
317             gAddressModeToUse = CL_ADDRESS_MIRRORED_REPEAT;
318 
319         else if( strcmp( argv[i], "NORMALIZED" ) == 0 )
320             gNormalizedModeToUse = true;
321         else if( strcmp( argv[i], "UNNORMALIZED" ) == 0 )
322             gNormalizedModeToUse = false;
323 
324 
325         else if( strcmp( argv[i], "no_offsets" ) == 0 )
326             gDisableOffsets = true;
327         else if( strcmp( argv[i], "small_images" ) == 0 )
328             gTestSmallImages = true;
329         else if( strcmp( argv[i], "max_images" ) == 0 )
330             gTestMaxImages = true;
331         else if( strcmp( argv[i], "use_pitches" ) == 0 )
332             gEnablePitch = true;
333         else if( strcmp( argv[i], "rounding" ) == 0 )
334             gTestRounding = true;
335         else if( strcmp( argv[i], "extra_validate" ) == 0 )
336             gExtraValidateInfo = true;
337         else if( strcmp( argv[i], "test_mipmaps" ) == 0 ) {
338             // 2.0 Spec does not allow using mem flags, unnormalized coordinates with mipmapped images
339             gTestMipmaps = true;
340             gMemFlagsToUse = 0;
341             gNormalizedModeToUse = true;
342         }
343 
344         else if( strcmp( argv[i], "read" ) == 0 )
345             testTypesToRun |= kReadTests;
346         else if( strcmp( argv[i], "write" ) == 0 )
347             testTypesToRun |= kWriteTests;
348         else if( strcmp( argv[i], "read_write" ) == 0 )
349         {
350             testTypesToRun |= kReadWriteTests;
351         }
352 
353         else if( strcmp( argv[i], "local_samplers" ) == 0 )
354             gUseKernelSamplers = true;
355 
356         else if( strcmp( argv[i], "int" ) == 0 )
357             gTypesToTest |= kTestInt;
358         else if( strcmp( argv[i], "uint" ) == 0 )
359             gTypesToTest |= kTestUInt;
360         else if( strcmp( argv[i], "float" ) == 0 )
361             gTypesToTest |= kTestFloat;
362 
363         else if( strcmp( argv[i], "CL_MEM_COPY_HOST_PTR" ) == 0 || strcmp( argv[i], "COPY_HOST_PTR" ) == 0 )
364             gMemFlagsToUse = CL_MEM_COPY_HOST_PTR;
365         else if( strcmp( argv[i], "CL_MEM_USE_HOST_PTR" ) == 0 || strcmp( argv[i], "USE_HOST_PTR" ) == 0 )
366             gMemFlagsToUse = CL_MEM_USE_HOST_PTR;
367         else if( strcmp( argv[i], "CL_MEM_ALLOC_HOST_PTR" ) == 0 || strcmp( argv[i], "ALLOC_HOST_PTR" ) == 0 )
368             gMemFlagsToUse = CL_MEM_ALLOC_HOST_PTR;
369         else if( strcmp( argv[i], "NO_HOST_PTR" ) == 0 )
370             gMemFlagsToUse = 0;
371 
372         else if( strcmp( argv[i], "--help" ) == 0 || strcmp( argv[i], "-h" ) == 0 )
373         {
374             printUsage( argv[ 0 ] );
375             return -1;
376         }
377 
378         else if( ( chanType = get_channel_type_from_name( argv[i] ) ) != (cl_channel_type)-1 )
379             gChannelTypeToUse = chanType;
380 
381         else if( ( chanOrder = get_channel_order_from_name( argv[i] ) ) != (cl_channel_order)-1 )
382             gChannelOrderToUse = chanOrder;
383         else
384         {
385             argList[argCount] = argv[i];
386             argCount++;
387         }
388     }
389 
390     if( testTypesToRun == 0 )
391         testTypesToRun = kAllTests;
392     if( gTypesToTest == 0 )
393         gTypesToTest = kTestAllTypes;
394 
395     if( gTestSmallImages )
396         log_info( "Note: Using small test images\n" );
397 
398     // On most platforms which support denorm, default is FTZ off. However,
399     // on some hardware where the reference is computed, default might be flush denorms to zero e.g. arm.
400     // This creates issues in result verification. Since spec allows the implementation to either flush or
401     // not flush denorms to zero, an implementation may choose not to flush i.e. return denorm result whereas
402     // reference result may be zero (flushed denorm). Hence we need to disable denorm flushing on host side
403     // where reference is being computed to make sure we get non-flushed reference result. If implementation
404     // returns flushed result, we correctly take care of that in verification code.
405 
406     FPU_mode_type oldMode;
407     DisableFTZ(&oldMode);
408 
409     int ret = runTestHarness( argCount, argList, test_num, test_list, true, false, 0 );
410 
411     // Restore FP state before leaving
412     RestoreFPState(&oldMode);
413 
414     free(argList);
415     return ret;
416 }
417 
printUsage(const char * execName)418 static void printUsage( const char *execName )
419 {
420     const char *p = strrchr( execName, '/' );
421     if( p != NULL )
422         execName = p + 1;
423 
424     log_info( "Usage: %s [options] [test_names]\n", execName );
425     log_info( "Options:\n" );
426     log_info( "\n" );
427     log_info( "\tThe following flags specify what kinds of operations to test. They can be combined; if none are specified, all are tested:\n" );
428     log_info( "\t\tread - Tests reading from an image\n" );
429     log_info( "\t\twrite - Tests writing to an image (can be specified with read to run both; default is both)\n" );
430     log_info( "\n" );
431     log_info( "\tThe following flags specify the types to test. They can be combined; if none are specified, all are tested:\n" );
432     log_info( "\t\tint - Test integer I/O (read_imagei, write_imagei)\n" );
433     log_info( "\t\tuint - Test unsigned integer I/O (read_imageui, write_imageui)\n" );
434     log_info( "\t\tfloat - Test float I/O (read_imagef, write_imagef)\n" );
435     log_info( "\n" );
436     log_info( "\tCL_FILTER_LINEAR - Only tests formats with CL_FILTER_LINEAR filtering\n" );
437     log_info( "\tCL_FILTER_NEAREST - Only tests formats with CL_FILTER_NEAREST filtering\n" );
438     log_info( "\n" );
439     log_info( "\tNORMALIZED - Only tests formats with NORMALIZED coordinates\n" );
440     log_info( "\tUNNORMALIZED - Only tests formats with UNNORMALIZED coordinates\n" );
441     log_info( "\n" );
442     log_info( "\tCL_ADDRESS_CLAMP - Only tests formats with CL_ADDRESS_CLAMP addressing\n" );
443     log_info( "\tCL_ADDRESS_CLAMP_TO_EDGE - Only tests formats with CL_ADDRESS_CLAMP_TO_EDGE addressing\n" );
444     log_info( "\tCL_ADDRESS_REPEAT - Only tests formats with CL_ADDRESS_REPEAT addressing\n" );
445     log_info( "\tCL_ADDRESS_MIRRORED_REPEAT - Only tests formats with CL_ADDRESS_MIRRORED_REPEAT addressing\n" );
446     log_info( "\n" );
447     log_info( "You may also use appropriate CL_ channel type and ordering constants.\n" );
448     log_info( "\n" );
449     log_info( "\tlocal_samplers - Use samplers declared in the kernel functions instead of passed in as arguments\n" );
450     log_info( "\n" );
451     log_info( "\tThe following specify to use the specific flag to allocate images to use in the tests:\n" );
452     log_info( "\t\tCL_MEM_COPY_HOST_PTR\n" );
453     log_info( "\t\tCL_MEM_USE_HOST_PTR (default)\n" );
454     log_info( "\t\tCL_MEM_ALLOC_HOST_PTR\n" );
455     log_info( "\t\tNO_HOST_PTR - Specifies to use none of the above flags\n" );
456     log_info( "\n" );
457     log_info( "\tThe following modify the types of images tested:\n" );
458     log_info( "\t\tsmall_images - Runs every format through a loop of widths 1-13 and heights 1-9, instead of random sizes\n" );
459     log_info( "\t\tmax_images - Runs every format through a set of size combinations with the max values, max values - 1, and max values / 128\n" );
460     log_info( "\t\trounding - Runs every format through a single image filled with every possible value for that image format, to verify rounding works properly\n" );
461     log_info( "\n" );
462     log_info( "\tno_offsets - Disables offsets when testing reads (can be good for diagnosing address repeating/clamping problems)\n" );
463     log_info( "\tdebug_trace - Enables additional debug info logging\n" );
464     log_info( "\textra_validate - Enables additional validation failure debug information\n" );
465     log_info( "\tuse_pitches - Enables row and slice pitches\n" );
466     log_info( "\ttest_mipmaps - Enables mipmapped images\n");
467     log_info( "\n" );
468     log_info( "Test names:\n" );
469     for( int i = 0; i < test_num; i++ )
470     {
471         log_info( "\t%s\n", test_list[i].name );
472     }
473 }
474