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